Skip to content

Commit

Permalink
Merge pull request #134 from rsksmart/fix_merge_mining_with_cache
Browse files Browse the repository at this point in the history
Fix merge mining with cache for ginger
  • Loading branch information
aeidelman authored Jul 10, 2017
2 parents 5e93590 + 7ef1e22 commit 1818932
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 5 deletions.
5 changes: 4 additions & 1 deletion rskj-core/src/main/java/co/rsk/mine/MinerClientImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

@Component("MinerClient")
public class MinerClientImpl implements MinerClient {
private long nextNonceToUse = 0;

@Autowired
private Rsk rsk;
Expand Down Expand Up @@ -171,14 +172,16 @@ public boolean mineBlock() {
*/
private boolean findNonce(@Nonnull final co.rsk.bitcoinj.core.BtcBlock bitcoinMergedMiningBlock,
@Nonnull final BigInteger target) {
bitcoinMergedMiningBlock.setNonce(nextNonceToUse++);

while (!stop && !newBestBlockArrivedFromAnotherNode) {
// Is our proof of work valid yet?
BigInteger blockHashBI = bitcoinMergedMiningBlock.getHash().toBigInteger();
if (blockHashBI.compareTo(target) <= 0) {
return true;
}
// No, so increment the nonce and try again.
bitcoinMergedMiningBlock.setNonce(bitcoinMergedMiningBlock.getNonce() + 1);
bitcoinMergedMiningBlock.setNonce(nextNonceToUse++);
if (bitcoinMergedMiningBlock.getNonce() % 100000 == 0) {
logger.debug("Solving block. Nonce: " + bitcoinMergedMiningBlock.getNonce());
}
Expand Down
19 changes: 15 additions & 4 deletions rskj-core/src/main/java/co/rsk/mine/MinerServerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,20 +151,26 @@ public void submitBitcoinBlock(String blockHashForMergedMining, co.rsk.bitcoinj.
Block newBlock;
Sha3Hash key = new Sha3Hash(TypeConverter.removeZeroX(blockHashForMergedMining));
synchronized (LOCK) {
newBlock = blocksWaitingforPoW.get(key);
if (newBlock == null) {
Block workingBlock = blocksWaitingforPoW.get(key);

if (workingBlock == null) {
logger.warn("Cannot publish block, could not find hash " + blockHashForMergedMining + " in the cache");
return;
}

// just in case, remove all references to this block.
if (latestBlock == newBlock) {
if (latestBlock == workingBlock) {
latestBlock = null;
latestblockHashWaitingforPoW = null;
currentWork = null;
}

// clone the block
newBlock = new Block(workingBlock.getEncoded());

logger.debug("blocksWaitingforPoW size " + blocksWaitingforPoW.size());
}

logger.info("Received block {} {}", newBlock.getNumber(), Hex.toHexString(newBlock.getHash()));

newBlock.setBitcoinMergedMiningHeader(bitcoinMergedMiningBlock.cloneAsHeader().bitcoinSerialize());
Expand Down Expand Up @@ -259,7 +265,7 @@ public MinerWork getWork() {
* currentWork, regardless of what it is.
*/
synchronized (LOCK) {
if (currentWork != work || currentWork == null) {
if (currentWork != work || currentWork == null) {
return currentWork;
}
currentWork = new MinerWork(currentWork.getBlockHashForMergedMining(), currentWork.getTarget(),
Expand All @@ -270,6 +276,11 @@ public MinerWork getWork() {
return work;
}

@VisibleForTesting
public void setWork(MinerWork work) {
this.currentWork = work;
}

public MinerWork updateGetWork(@Nonnull final Block block, @Nonnull final boolean notify) {
Sha3Hash blockMergedMiningHash = new Sha3Hash(block.getHashForMergedMining());

Expand Down
39 changes: 39 additions & 0 deletions rskj-core/src/test/java/co/rsk/mine/MinerManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import org.junit.Assert;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;

/**
Expand Down Expand Up @@ -98,6 +100,43 @@ public void refreshWorkRunTwice() {
Assert.assertEquals(2, blockchain.getBestBlock().getNumber());
}

@Test
public void mineBlockTwiceReusingTheSameWork() {
World world = new World();
Blockchain blockchain = world.getBlockChain();

Assert.assertEquals(0, blockchain.getBestBlock().getNumber());

MinerServerImpl minerServer = getMinerServer(blockchain);
MinerClientImpl minerClient = getMinerClient(minerServer);

minerServer.buildBlockToMine(blockchain.getBestBlock(), false);

MinerWork minerWork = minerServer.getWork();

Assert.assertNotNull(minerWork);

Assert.assertTrue(minerClient.mineBlock());

Block bestBlock = blockchain.getBestBlock();

Assert.assertNotNull(bestBlock);
Assert.assertEquals(1, bestBlock.getNumber());

// reuse the same work
Assert.assertNull(minerServer.getWork());
minerServer.setWork(minerWork);
Assert.assertNotNull(minerServer.getWork());

Assert.assertTrue(minerClient.mineBlock());

List<Block> blocks = blockchain.getBlocksByNumber(1);

Assert.assertNotNull(blocks);
Assert.assertEquals(2, blocks.size());
Assert.assertFalse(Arrays.equals(blocks.get(0).getHash(), blocks.get(1).getHash()));
}

@Test
public void mineBlockWhileSyncingBlocks() {
World world = new World();
Expand Down

0 comments on commit 1818932

Please sign in to comment.