Skip to content

Commit

Permalink
Correct AuxPoW index calculation to match unsigned integer maths used…
Browse files Browse the repository at this point in the history
… by reference client.

Add unit tests for AuxPoW index calculation.
  • Loading branch information
Ross Nicoll committed Nov 7, 2015
1 parent 95060fa commit 1dcdff9
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 6 deletions.
17 changes: 14 additions & 3 deletions src/main/java/org/bitcoinj/core/AuxPoW.java
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,10 @@ protected boolean checkProofOfWork(Sha256Hash hashAuxBlock,

if (getChainMerkleBranch().getIndex() != getExpectedIndex(nonce, ((AuxPoWNetworkParameters) params).getChainID(), getChainMerkleBranch().size())) {
if (throwException) {
throw new VerificationException("Aux POW wrong index");
throw new VerificationException("Aux POW wrong index in chain merkle branch for chain ID "
+ ((AuxPoWNetworkParameters) params).getChainID() + ". Was "
+ getChainMerkleBranch().getIndex() + ", expected "
+ getExpectedIndex(nonce, ((AuxPoWNetworkParameters) params).getChainID(), getChainMerkleBranch().size()));
}
return false;
}
Expand Down Expand Up @@ -402,12 +405,20 @@ protected static int getExpectedIndex(final long nonce, final int chainId, final
// Choose a pseudo-random slot in the chain merkle tree
// but have it be fixed for a size/nonce/chain combination.

long rand = nonce;
// We do most of the maths with a signed 32 bit integer, as the operation is
// the same as the 32 unsigned integer that the reference version uses
int rand = (int) nonce;
rand = rand * 1103515245 + 12345;
rand += chainId;
rand = rand * 1103515245 + 12345;

return (int) (rand % (1L << merkleHeight));
// At this point, we need to flip the value to its positive version,
// so we switch to a 64 bit signed integer for the last calculations
long longRand = rand & 0xffffffffl;

longRand %= (1 << merkleHeight);

return (int) longRand;
}

public Transaction getTransaction() {
Expand Down
25 changes: 25 additions & 0 deletions src/test/java/org/bitcoinj/core/DogecoinBlockTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,31 @@ public void shouldParseBlock371337() throws IOException {
assertTrue(auxpow.checkProofOfWork(block.getHash(), block.getDifficultyTargetAsInteger(), false));
}

/**
* Confirm parsing of block with a nonce value above Integer.MAX_VALUE.
* See https://github.com/rnicoll/libdohj/pull/7
*
* @throws IOException
*/
@Test
public void shouldParseBlock748634() throws IOException {
byte[] payload = Util.getBytes(getClass().getResourceAsStream("dogecoin_block748634.bin"));
AltcoinSerializer serializer = (AltcoinSerializer)params.getDefaultSerializer();
final AltcoinBlock block = (AltcoinBlock)serializer.makeBlock(payload);
assertEquals("bd98a06391115285265c04984e8505229739f6ffa5d498929a91fbe7c281ea7b", block.getHashAsString());
assertEquals(0, block.getNonce());

// Check block version values
assertEquals(2, block.getVersion());
assertEquals(98, block.getChainID());
assertTrue(block.getVersionFlags().get(0));

final AuxPoW auxpow = block.getAuxPoW();
assertNotNull(auxpow);

assertTrue(auxpow.checkProofOfWork(block.getHash(), block.getDifficultyTargetAsInteger(), true));
}

/**
* Confirm parsing of block with a nonce value above Integer.MAX_VALUE.
* See https://github.com/rnicoll/libdohj/issues/5
Expand Down

This file was deleted.

This file was deleted.

Binary file not shown.
Loading

0 comments on commit 1dcdff9

Please sign in to comment.