diff --git a/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java b/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java index c00bcccc..8b06a31c 100644 --- a/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java +++ b/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java @@ -214,7 +214,7 @@ public class BitcoinSerializer { } else if (command.equals("tx")) { Transaction tx = new Transaction(params, payloadBytes, null, parseLazy, parseRetain, length); if (hash != null) - tx.setHash(Sha256Hash.wrap(Utils.reverseBytes(hash))); + tx.setHash(Sha256Hash.wrapReversed(hash)); message = tx; } else if (command.equals("addr")) { message = new AddressMessage(params, payloadBytes, parseLazy, parseRetain, length); diff --git a/core/src/main/java/org/bitcoinj/core/Block.java b/core/src/main/java/org/bitcoinj/core/Block.java index dbae8a2d..4a2b5891 100644 --- a/core/src/main/java/org/bitcoinj/core/Block.java +++ b/core/src/main/java/org/bitcoinj/core/Block.java @@ -191,7 +191,7 @@ public class Block extends Message { difficultyTarget = readUint32(); nonce = readUint32(); - hash = Sha256Hash.wrap(Utils.reverseBytes(Sha256Hash.hashTwice(payload, offset, cursor))); + hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(payload, offset, cursor)); headerParsed = true; headerBytesValid = parseRetain; @@ -385,8 +385,8 @@ public class Block extends Message { // fall back to manual write maybeParseHeader(); Utils.uint32ToByteStreamLE(version, stream); - stream.write(Utils.reverseBytes(prevBlockHash.getBytes())); - stream.write(Utils.reverseBytes(getMerkleRoot().getBytes())); + stream.write(prevBlockHash.getReversedBytes()); + stream.write(getMerkleRoot().getReversedBytes()); Utils.uint32ToByteStreamLE(time, stream); Utils.uint32ToByteStreamLE(difficultyTarget, stream); Utils.uint32ToByteStreamLE(nonce, stream); @@ -511,7 +511,7 @@ public class Block extends Message { try { ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(HEADER_SIZE); writeHeader(bos); - return Sha256Hash.wrap(Utils.reverseBytes(Sha256Hash.hashTwice(bos.toByteArray()))); + return Sha256Hash.wrapReversed(Sha256Hash.hashTwice(bos.toByteArray())); } catch (IOException e) { throw new RuntimeException(e); // Cannot happen. } diff --git a/core/src/main/java/org/bitcoinj/core/GetBlocksMessage.java b/core/src/main/java/org/bitcoinj/core/GetBlocksMessage.java index 0f3765fc..fc444cd5 100644 --- a/core/src/main/java/org/bitcoinj/core/GetBlocksMessage.java +++ b/core/src/main/java/org/bitcoinj/core/GetBlocksMessage.java @@ -95,10 +95,10 @@ public class GetBlocksMessage extends Message { stream.write(new VarInt(locator.size()).encode()); for (Sha256Hash hash : locator) { // Have to reverse as wire format is little endian. - stream.write(Utils.reverseBytes(hash.getBytes())); + stream.write(hash.getReversedBytes()); } // Next, a block ID to stop at. - stream.write(Utils.reverseBytes(stopHash.getBytes())); + stream.write(stopHash.getReversedBytes()); } @Override diff --git a/core/src/main/java/org/bitcoinj/core/ListMessage.java b/core/src/main/java/org/bitcoinj/core/ListMessage.java index 0ec4d959..e1a69952 100644 --- a/core/src/main/java/org/bitcoinj/core/ListMessage.java +++ b/core/src/main/java/org/bitcoinj/core/ListMessage.java @@ -116,7 +116,7 @@ public abstract class ListMessage extends Message { // Write out the type code. Utils.uint32ToByteStreamLE(i.type.ordinal(), stream); // And now the hash. - stream.write(Utils.reverseBytes(i.hash.getBytes())); + stream.write(i.hash.getReversedBytes()); } } diff --git a/core/src/main/java/org/bitcoinj/core/Message.java b/core/src/main/java/org/bitcoinj/core/Message.java index 7f328412..24f4c406 100644 --- a/core/src/main/java/org/bitcoinj/core/Message.java +++ b/core/src/main/java/org/bitcoinj/core/Message.java @@ -411,11 +411,10 @@ public abstract class Message implements Serializable { try { byte[] hash = new byte[32]; System.arraycopy(payload, cursor, hash, 0, 32); + cursor += 32; // We have to flip it around, as it's been read off the wire in little endian. // Not the most efficient way to do this but the clearest. - hash = Utils.reverseBytes(hash); - cursor += 32; - return Sha256Hash.wrap(hash); + return Sha256Hash.wrapReversed(hash); } catch (IndexOutOfBoundsException e) { throw new ProtocolException(e); } diff --git a/core/src/main/java/org/bitcoinj/core/PartialMerkleTree.java b/core/src/main/java/org/bitcoinj/core/PartialMerkleTree.java index ceb4db77..dadc6405 100644 --- a/core/src/main/java/org/bitcoinj/core/PartialMerkleTree.java +++ b/core/src/main/java/org/bitcoinj/core/PartialMerkleTree.java @@ -101,7 +101,7 @@ public class PartialMerkleTree extends Message { stream.write(new VarInt(hashes.size()).encode()); for (Sha256Hash hash : hashes) - stream.write(reverseBytes(hash.getBytes())); + stream.write(hash.getReversedBytes()); stream.write(new VarInt(matchedChildBits.length).encode()); stream.write(matchedChildBits); @@ -214,9 +214,9 @@ public class PartialMerkleTree extends Message { } private static Sha256Hash combineLeftRight(byte[] left, byte[] right) { - return Sha256Hash.wrap(reverseBytes(Sha256Hash.hashTwice( + return Sha256Hash.wrapReversed(Sha256Hash.hashTwice( reverseBytes(left), 0, 32, - reverseBytes(right), 0, 32))); + reverseBytes(right), 0, 32)); } /** diff --git a/core/src/main/java/org/bitcoinj/core/RejectMessage.java b/core/src/main/java/org/bitcoinj/core/RejectMessage.java index 8ac8d6dd..c90f9dc1 100644 --- a/core/src/main/java/org/bitcoinj/core/RejectMessage.java +++ b/core/src/main/java/org/bitcoinj/core/RejectMessage.java @@ -107,7 +107,7 @@ public class RejectMessage extends Message { stream.write(new VarInt(reasonBytes.length).encode()); stream.write(reasonBytes); if (message.equals("block") || message.equals("tx")) - stream.write(Utils.reverseBytes(messageHash.getBytes())); + stream.write(messageHash.getReversedBytes()); } /** diff --git a/core/src/main/java/org/bitcoinj/core/Sha256Hash.java b/core/src/main/java/org/bitcoinj/core/Sha256Hash.java index 669a48d4..70f96f67 100644 --- a/core/src/main/java/org/bitcoinj/core/Sha256Hash.java +++ b/core/src/main/java/org/bitcoinj/core/Sha256Hash.java @@ -81,6 +81,18 @@ public class Sha256Hash implements Serializable, Comparable { return wrap(Utils.HEX.decode(hexString)); } + /** + * Creates a new instance that wraps the given hash value, but with byte order reversed. + * + * @param rawHashBytes the raw hash bytes to wrap + * @return a new instance + * @throws IllegalArgumentException if the given array length is not exactly 32 + */ + @SuppressWarnings("deprecation") // the constructor will be made private in the future + public static Sha256Hash wrapReversed(byte[] rawHashBytes) { + return wrap(Utils.reverseBytes(rawHashBytes)); + } + /** Use {@link #of(byte[])} instead: this old name is ambiguous. */ @Deprecated public static Sha256Hash create(byte[] contents) { @@ -244,6 +256,13 @@ public class Sha256Hash implements Serializable, Comparable { return bytes; } + /** + * Returns a reversed copy of the internal byte array. + */ + public byte[] getReversedBytes() { + return Utils.reverseBytes(bytes); + } + @Override public int compareTo(Sha256Hash o) { return this.hashCode() - o.hashCode(); diff --git a/core/src/main/java/org/bitcoinj/core/Transaction.java b/core/src/main/java/org/bitcoinj/core/Transaction.java index 36833644..43f6a251 100644 --- a/core/src/main/java/org/bitcoinj/core/Transaction.java +++ b/core/src/main/java/org/bitcoinj/core/Transaction.java @@ -226,7 +226,7 @@ public class Transaction extends ChildMessage implements Serializable { public Sha256Hash getHash() { if (hash == null) { byte[] bits = bitcoinSerialize(); - hash = Sha256Hash.wrap(reverseBytes(Sha256Hash.hashTwice(bits))); + hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(bits)); } return hash; } diff --git a/core/src/main/java/org/bitcoinj/core/TransactionOutPoint.java b/core/src/main/java/org/bitcoinj/core/TransactionOutPoint.java index 0cf8ec20..4b9c51b0 100644 --- a/core/src/main/java/org/bitcoinj/core/TransactionOutPoint.java +++ b/core/src/main/java/org/bitcoinj/core/TransactionOutPoint.java @@ -112,7 +112,7 @@ public class TransactionOutPoint extends ChildMessage implements Serializable { @Override protected void bitcoinSerializeToStream(OutputStream stream) throws IOException { - stream.write(Utils.reverseBytes(hash.getBytes())); + stream.write(hash.getReversedBytes()); Utils.uint32ToByteStreamLE(index, stream); }