diff --git a/pom.xml b/pom.xml
index 63e33906..92a8b14d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
org.altcoinj
altcoinj
- 1.0-SNAPSHOT
+ 0.13-SNAPSHOT
jar
@@ -11,11 +11,6 @@
slf4j-api
1.7.7
-
- org.bitcoinj
- bitcoinj-core
- 0.13-SNAPSHOT
-
junit
junit
@@ -33,10 +28,15 @@
scrypt
1.4.0
+
+ org.bitcoinj
+ bitcoinj-core
+ 0.14-SNAPSHOT
+
UTF-8
1.6
1.6
-
\ No newline at end of file
+
diff --git a/src/main/java/org/bitcoinj/core/MerkleBranch.java b/src/main/java/org/bitcoinj/core/MerkleBranch.java
index 22625c39..9c7f9e9b 100644
--- a/src/main/java/org/bitcoinj/core/MerkleBranch.java
+++ b/src/main/java/org/bitcoinj/core/MerkleBranch.java
@@ -17,17 +17,16 @@
package org.bitcoinj.core;
-import static org.bitcoinj.core.Utils.doubleDigestTwoBuffers;
-import static org.bitcoinj.core.Utils.reverseBytes;
-
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
+import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import static org.bitcoinj.core.Sha256Hash.newDigest;
/**
* A Merkle branch contains the hashes from a leaf of a Merkle tree
@@ -134,16 +133,26 @@ public class MerkleBranch extends ChildMessage implements Serializable {
* Used to verify that the given leaf and root are part of the same tree.
*/
public Sha256Hash calculateMerkleRoot(final Sha256Hash leaf) {
- byte[] target = reverseBytes(leaf.getBytes());
+ byte[] target = leaf.getReversedBytes();
long mask = index;
+ MessageDigest digest = Sha256Hash.newDigest();
for (Sha256Hash hash: hashes) {
- target = (mask & 1) == 0
- ? doubleDigestTwoBuffers(target, 0, 32, reverseBytes(hash.getBytes()), 0, 32)
- : doubleDigestTwoBuffers(reverseBytes(hash.getBytes()), 0, 32, target, 0, 32);
+ digest.reset();
+ if ((mask & 1) == 0) { // 0 means it goes on the right
+ digest.update(target);
+ digest.update(hash.getReversedBytes());
+ } else {
+ digest.update(hash.getReversedBytes());
+ digest.update(target);
+ }
+ // Double-digest the values
+ target = digest.digest();
+ digest.reset();
+ target = digest.digest(target);
mask >>= 1;
}
- return new Sha256Hash(reverseBytes(target));
+ return Sha256Hash.wrapReversed(target);
}
/**
diff --git a/src/test/java/org/bitcoinj/core/AuxPoWTest.java b/src/test/java/org/bitcoinj/core/AuxPoWTest.java
index ea2aaa6a..55936276 100644
--- a/src/test/java/org/bitcoinj/core/AuxPoWTest.java
+++ b/src/test/java/org/bitcoinj/core/AuxPoWTest.java
@@ -7,7 +7,6 @@ import org.altcoinj.params.DogecoinMainNetParams;
import org.junit.Test;
import static org.bitcoinj.core.Util.getBytes;
-import static org.bitcoinj.core.Utils.doubleDigestTwoBuffers;
import static org.bitcoinj.core.Utils.reverseBytes;
import static org.junit.Assert.assertArrayEquals;
@@ -36,14 +35,16 @@ public class AuxPoWTest {
byte[] auxpowAsBytes = getBytes(getClass().getResourceAsStream("auxpow_header.bin"));
AuxPoW auxpow = new AuxPoW(params, auxpowAsBytes, (ChildMessage) null, params.getDefaultSerializer());
MerkleBranch branch = auxpow.getCoinbaseBranch();
- Sha256Hash expected = new Sha256Hash("089b911f5e471c0e1800f3384281ebec5b372fbb6f358790a92747ade271ccdf");
+ Sha256Hash expected = Sha256Hash.wrap("089b911f5e471c0e1800f3384281ebec5b372fbb6f358790a92747ade271ccdf");
assertEquals(expected, auxpow.getCoinbase().getHash());
assertEquals(3, auxpow.getCoinbaseBranch().size());
assertEquals(6, auxpow.getChainMerkleBranch().size());
- expected = new Sha256Hash("a22a9b01671d639fa6389f62ecf8ce69204c8ed41d5f1a745e0c5ba7116d5b4c");
+ expected = Sha256Hash.wrap("a22a9b01671d639fa6389f62ecf8ce69204c8ed41d5f1a745e0c5ba7116d5b4c");
assertEquals(expected, auxpow.getParentBlockHeader().getHash());
+ expected = Sha256Hash.wrap("f29cd14243ed542d9a0b495efcb9feca1b208bb5b717dc5ac04f068d2fef595a");
+ assertEquals(expected, auxpow.getParentBlockHeader().getMerkleRoot());
}
/**
@@ -66,7 +67,7 @@ public class AuxPoWTest {
public void checkAuxPoWHeader() throws Exception {
byte[] auxpowAsBytes = getBytes(getClass().getResourceAsStream("auxpow_header.bin"));
AuxPoW auxpow = new AuxPoW(params, auxpowAsBytes, (ChildMessage) null, params.getDefaultSerializer());
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -83,7 +84,7 @@ public class AuxPoWTest {
auxpow.getCoinbaseBranch().setIndex(0x01);
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("AuxPow is not a generate");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -100,7 +101,7 @@ public class AuxPoWTest {
auxpow.setParentBlockHeader((AltcoinBlock)block.cloneAsHeader());
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Aux POW parent has our chain ID");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -114,7 +115,7 @@ public class AuxPoWTest {
auxpow.getChainMerkleBranch().setHashes(Arrays.asList(new Sha256Hash[32]));
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Aux POW chain merkle branch too long");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -132,7 +133,7 @@ public class AuxPoWTest {
auxpow.getCoinbase().clearOutputs();
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Aux POW merkle root incorrect");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -152,7 +153,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Coinbase transaction has no inputs");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -173,7 +174,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("MergedMiningHeader missing from parent coinbase");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -198,7 +199,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Multiple merged mining headers in coinbase");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -221,7 +222,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Aux POW missing chain merkle root in parent coinbase");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -251,7 +252,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Merged mining header is not just before chain merkle root");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -274,7 +275,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Aux POW missing chain merkle tree size and nonce in parent coinbase");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -295,7 +296,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Aux POW merkle branch size does not match parent coinbase");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -316,7 +317,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Aux POW wrong index");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x1b06f8f0), true);
}
@@ -332,7 +333,7 @@ public class AuxPoWTest {
expectedEx.expect(org.bitcoinj.core.VerificationException.class);
expectedEx.expectMessage("Hash is higher than target: a22a9b01671d639fa6389f62ecf8ce69204c8ed41d5f1a745e0c5ba7116d5b4c vs 0");
- auxpow.checkProofOfWork(new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
+ auxpow.checkProofOfWork(Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609"),
Utils.decodeCompactBits(0x00), true);
}
@@ -347,10 +348,9 @@ public class AuxPoWTest {
// The coinbase hash is the single leaf node in the merkle tree,
// so to get the root we need to hash it with itself.
// Note that bytes are reversed for hashing
- final byte[] revisedMerkleRootBytes = doubleDigestTwoBuffers(
- reverseBytes(revisedCoinbaseHash.getBytes()), 0, 32,
- reverseBytes(revisedCoinbaseHash.getBytes()), 0, 32);
- final Sha256Hash revisedMerkleRoot = new Sha256Hash(reverseBytes(revisedMerkleRootBytes));
+ final Sha256Hash revisedMerkleRoot = Sha256Hash.wrapReversed(
+ Sha256Hash.hashTwice(revisedCoinbaseHash.getReversedBytes(), 0, 32, revisedCoinbaseHash.getReversedBytes(), 0, 32)
+ );
auxpow.getParentBlockHeader().setMerkleRoot(revisedMerkleRoot);
auxpow.setCoinbaseBranch(new MerkleBranch(params, auxpow,
Collections.singletonList(revisedCoinbaseHash), MERKLE_ROOT_COINBASE_INDEX));
diff --git a/src/test/java/org/bitcoinj/core/MerkleBranchTest.java b/src/test/java/org/bitcoinj/core/MerkleBranchTest.java
index b968b550..49b16d75 100644
--- a/src/test/java/org/bitcoinj/core/MerkleBranchTest.java
+++ b/src/test/java/org/bitcoinj/core/MerkleBranchTest.java
@@ -24,9 +24,9 @@ public class MerkleBranchTest {
byte[] branchAsBytes = getBytes(getClass().getResourceAsStream("auxpow_merkle_branch.bin"));
MerkleBranch branch = new MerkleBranch(params, (ChildMessage) null, branchAsBytes, 0);
Sha256Hash[] expected = new Sha256Hash[] {
- new Sha256Hash("be079078869399faccaa764c10e9df6e9981701759ad18e13724d9ca58831348"),
- new Sha256Hash("5f5bfb2c79541778499cab956a103887147f2ab5d4a717f32f9eeebd29e1f894"),
- new Sha256Hash("d8c6fe42ca25076159cd121a5e20c48c1bc53ab90730083e44a334566ea6bbcb")
+ Sha256Hash.wrap("be079078869399faccaa764c10e9df6e9981701759ad18e13724d9ca58831348"),
+ Sha256Hash.wrap("5f5bfb2c79541778499cab956a103887147f2ab5d4a717f32f9eeebd29e1f894"),
+ Sha256Hash.wrap("d8c6fe42ca25076159cd121a5e20c48c1bc53ab90730083e44a334566ea6bbcb")
};
assertArrayEquals(expected, branch.getHashes().toArray(new Sha256Hash[branch.size()]));
@@ -53,8 +53,8 @@ public class MerkleBranchTest {
public void calculateRootBranch() throws Exception {
byte[] branchAsBytes = getBytes(getClass().getResourceAsStream("auxpow_merkle_branch2.bin"));
MerkleBranch branch = new MerkleBranch(params, (ChildMessage) null, branchAsBytes, 0);
- Sha256Hash txId = new Sha256Hash("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609");
- Sha256Hash expected = new Sha256Hash("ce3040fdb7e37484f6a1ca4f8f5da81e6b7e404ec91102315a233e03a0c39c95");
+ Sha256Hash txId = Sha256Hash.wrap("0c836b86991631d34a8a68054e2f62db919b39d1ee43c27ab3344d6aa82fa609");
+ Sha256Hash expected = Sha256Hash.wrap("ce3040fdb7e37484f6a1ca4f8f5da81e6b7e404ec91102315a233e03a0c39c95");
assertEquals(expected, branch.calculateMerkleRoot(txId));
}