diff --git a/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java b/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java index 1296c15c..347485fd 100644 --- a/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java +++ b/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java @@ -266,8 +266,8 @@ public class BitcoinSerializer extends MessageSerializer { * serialization format support. */ @Override - public Block makeBlock(final byte[] payloadBytes, final int length) throws ProtocolException { - return new Block(params, payloadBytes, this, length); + public Block makeBlock(final byte[] payloadBytes, final int offset, final int length) throws ProtocolException { + return new Block(params, payloadBytes, offset, this, length); } /** diff --git a/core/src/main/java/org/bitcoinj/core/Block.java b/core/src/main/java/org/bitcoinj/core/Block.java index b92793a7..fb253ba5 100644 --- a/core/src/main/java/org/bitcoinj/core/Block.java +++ b/core/src/main/java/org/bitcoinj/core/Block.java @@ -134,6 +134,21 @@ public class Block extends Message { super(params, payloadBytes, 0, serializer, length); } + /** + * Construct a block object from the Bitcoin wire format. + * @param params NetworkParameters object. + * @param payloadBytes the payload to extract the block from. + * @param offset The location of the first payload byte within the array. + * @param serializer the serializer to use for this message. + * @param length The length of message if known. Usually this is provided when deserializing of the wire + * as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH + * @throws ProtocolException + */ + public Block(NetworkParameters params, byte[] payloadBytes, int offset, MessageSerializer serializer, int length) + throws ProtocolException { + super(params, payloadBytes, offset, serializer, length); + } + /** * Construct a block object from the Bitcoin wire format. Used in the case of a block * contained within another message (i.e. for AuxPoW header). diff --git a/core/src/main/java/org/bitcoinj/core/DummySerializer.java b/core/src/main/java/org/bitcoinj/core/DummySerializer.java index 6243c6af..68121e70 100644 --- a/core/src/main/java/org/bitcoinj/core/DummySerializer.java +++ b/core/src/main/java/org/bitcoinj/core/DummySerializer.java @@ -64,7 +64,7 @@ class DummySerializer extends MessageSerializer { } @Override - public Block makeBlock(byte[] payloadBytes, int length) throws UnsupportedOperationException { + public Block makeBlock(byte[] payloadBytes, int offset, int length) throws UnsupportedOperationException { throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE); } diff --git a/core/src/main/java/org/bitcoinj/core/HeadersMessage.java b/core/src/main/java/org/bitcoinj/core/HeadersMessage.java index 9a7a5602..8f2d02d2 100644 --- a/core/src/main/java/org/bitcoinj/core/HeadersMessage.java +++ b/core/src/main/java/org/bitcoinj/core/HeadersMessage.java @@ -64,33 +64,27 @@ public class HeadersMessage extends Message { @Override protected void parse() throws ProtocolException { - if (length == UNKNOWN_LENGTH) { - int saveCursor = cursor; - long numHeaders = readVarInt(); - cursor = saveCursor; - - // Each header has 80 bytes and one more byte for transactions number which is 00. - length = (Block.HEADER_SIZE + 1) * (int)numHeaders; - } - long numHeaders = readVarInt(); if (numHeaders > MAX_HEADERS) throw new ProtocolException("Too many headers: got " + numHeaders + " which is larger than " + MAX_HEADERS); blockHeaders = new ArrayList(); + final BitcoinSerializer serializer = this.params.getSerializer(true); for (int i = 0; i < numHeaders; ++i) { - // Read 80 bytes of the header and one more byte for the transaction list, which is always a 00 because the - // transaction list is empty. - byte[] blockHeader = readBytes(Block.HEADER_SIZE + 1); - if (blockHeader[Block.HEADER_SIZE] != 0) + final Block newBlockHeader = serializer.makeBlock(payload, cursor, UNKNOWN_LENGTH); + if (newBlockHeader.hasTransactions()) { throw new ProtocolException("Block header does not end with a null byte"); - Block newBlockHeader = this.params.getSerializer(true) - .makeBlock(blockHeader, Block.HEADER_SIZE + 1); + } + cursor += newBlockHeader.optimalEncodingMessageSize; blockHeaders.add(newBlockHeader); } + if (length == UNKNOWN_LENGTH) { + length = cursor - offset; + } + if (log.isDebugEnabled()) { for (int i = 0; i < numHeaders; ++i) { log.debug(this.blockHeaders.get(i).toString()); diff --git a/core/src/main/java/org/bitcoinj/core/MessageSerializer.java b/core/src/main/java/org/bitcoinj/core/MessageSerializer.java index e4fbfa11..2e962eef 100644 --- a/core/src/main/java/org/bitcoinj/core/MessageSerializer.java +++ b/core/src/main/java/org/bitcoinj/core/MessageSerializer.java @@ -69,7 +69,15 @@ public abstract class MessageSerializer { * length as block length. */ public final Block makeBlock(byte[] payloadBytes) throws ProtocolException { - return makeBlock(payloadBytes, payloadBytes.length); + return makeBlock(payloadBytes, 0, payloadBytes.length); + } + + /** + * Make a block from the payload, using an offset of zero and the provided + * length as block length. + */ + public final Block makeBlock(byte[] payloadBytes, int length) throws ProtocolException { + return makeBlock(payloadBytes, 0, length); } /** @@ -77,7 +85,7 @@ public abstract class MessageSerializer { * length as block length. Extension point for alternative * serialization format support. */ - public abstract Block makeBlock(byte[] payloadBytes, int length) throws ProtocolException; + public abstract Block makeBlock(final byte[] payloadBytes, final int offset, final int length) throws ProtocolException, UnsupportedOperationException; /** * Make an filter message from the payload. Extension point for alternative