mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-01-18 21:32:35 +01:00
Block: move parse()
to static constructor read()
This commit is contained in:
parent
3cf9e89893
commit
8a819c761c
@ -298,7 +298,7 @@ public class BitcoinSerializer extends MessageSerializer {
|
||||
*/
|
||||
@Override
|
||||
public Block makeBlock(ByteBuffer payload) throws ProtocolException {
|
||||
return new Block(payload);
|
||||
return Block.read(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,9 +134,54 @@ public class Block extends BaseMessage {
|
||||
/** Stores the hash of the block. If null, getHash() will recalculate it. */
|
||||
private Sha256Hash hash;
|
||||
|
||||
/**
|
||||
* Deserialize this message from a given payload.
|
||||
*
|
||||
* @param payload payload to deserialize from
|
||||
* @return read message
|
||||
* @throws BufferUnderflowException if the read message extends beyond the remaining bytes of the payload
|
||||
*/
|
||||
public static Block read(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
// header
|
||||
payload.mark();
|
||||
long version = ByteUtils.readUint32(payload);
|
||||
Sha256Hash prevBlockHash = Sha256Hash.read(payload);
|
||||
Sha256Hash merkleRoot = Sha256Hash.read(payload);
|
||||
Instant time = Instant.ofEpochSecond(ByteUtils.readUint32(payload));
|
||||
long difficultyTarget = ByteUtils.readUint32(payload);
|
||||
long nonce = ByteUtils.readUint32(payload);
|
||||
payload.reset(); // read again from the mark for the hash
|
||||
Sha256Hash hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(Buffers.readBytes(payload, HEADER_SIZE)));
|
||||
// transactions
|
||||
List<Transaction> transactions = payload.hasRemaining() ? // otherwise this message is just a header
|
||||
readTransactions(payload) :
|
||||
null;
|
||||
Block block = new Block(version, prevBlockHash, merkleRoot, time, difficultyTarget, nonce, transactions);
|
||||
block.hash = hash;
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse transactions from the block.
|
||||
*/
|
||||
private static List<Transaction> readTransactions(ByteBuffer payload) throws BufferUnderflowException,
|
||||
ProtocolException {
|
||||
VarInt numTransactionsVarInt = VarInt.read(payload);
|
||||
check(numTransactionsVarInt.fitsInt(), BufferUnderflowException::new);
|
||||
int numTransactions = numTransactionsVarInt.intValue();
|
||||
List<Transaction> transactions = new ArrayList<>(Math.min(numTransactions, Utils.MAX_INITIAL_ARRAY_LENGTH));
|
||||
MessageSerializer serializer = new DummySerializer(ProtocolVersion.CURRENT.intValue());
|
||||
for (int i = 0; i < numTransactions; i++) {
|
||||
Transaction tx = new Transaction(payload, serializer);
|
||||
// Label the transaction as coming from the P2P network, so code that cares where we first saw it knows.
|
||||
tx.getConfidence().setSource(TransactionConfidence.Source.NETWORK);
|
||||
transactions.add(tx);
|
||||
}
|
||||
return transactions;
|
||||
}
|
||||
|
||||
/** Special case constructor, used for the genesis node, cloneAsHeader and unit tests. */
|
||||
Block(long setVersion) {
|
||||
super(new DummySerializer(ProtocolVersion.CURRENT.intValue()));
|
||||
// Set up a few basic things. We are not complete after this though.
|
||||
version = setVersion;
|
||||
difficultyTarget = 0x1d07fff8L;
|
||||
@ -144,15 +189,6 @@ public class Block extends BaseMessage {
|
||||
prevBlockHash = Sha256Hash.ZERO_HASH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a block object from the Bitcoin wire format.
|
||||
* @param payload the payload to extract the block from.
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
public Block(ByteBuffer payload) throws ProtocolException {
|
||||
super(payload, new DummySerializer(ProtocolVersion.CURRENT.intValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a block initialized with all the given fields.
|
||||
* @param version This should usually be set to 1 or 2, depending on if the height is in the coinbase input.
|
||||
@ -172,8 +208,9 @@ public class Block extends BaseMessage {
|
||||
this.time = time;
|
||||
this.difficultyTarget = difficultyTarget;
|
||||
this.nonce = nonce;
|
||||
this.transactions = new LinkedList<>();
|
||||
this.transactions.addAll(transactions);
|
||||
if (transactions != null)
|
||||
transactions = new LinkedList<>(transactions);
|
||||
this.transactions = transactions;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -194,38 +231,9 @@ public class Block extends BaseMessage {
|
||||
transactions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse transactions from the block.
|
||||
*/
|
||||
protected void parseTransactions(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
VarInt numTransactionsVarInt = VarInt.read(payload);
|
||||
check(numTransactionsVarInt.fitsInt(), BufferUnderflowException::new);
|
||||
int numTransactions = numTransactionsVarInt.intValue();
|
||||
transactions = new ArrayList<>(Math.min(numTransactions, Utils.MAX_INITIAL_ARRAY_LENGTH));
|
||||
for (int i = 0; i < numTransactions; i++) {
|
||||
Transaction tx = new Transaction(payload, serializer);
|
||||
// Label the transaction as coming from the P2P network, so code that cares where we first saw it knows.
|
||||
tx.getConfidence().setSource(TransactionConfidence.Source.NETWORK);
|
||||
transactions.add(tx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
// header
|
||||
payload.mark();
|
||||
version = ByteUtils.readUint32(payload);
|
||||
prevBlockHash = Sha256Hash.read(payload);
|
||||
merkleRoot = Sha256Hash.read(payload);
|
||||
time = Instant.ofEpochSecond(ByteUtils.readUint32(payload));
|
||||
difficultyTarget = ByteUtils.readUint32(payload);
|
||||
nonce = ByteUtils.readUint32(payload);
|
||||
payload.reset(); // read again from the mark for the hash
|
||||
hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(Buffers.readBytes(payload, HEADER_SIZE)));
|
||||
|
||||
// transactions
|
||||
if (payload.hasRemaining()) // otherwise this message is just a header
|
||||
parseTransactions(payload);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static Block createGenesis() {
|
||||
|
@ -56,7 +56,7 @@ public class FilteredBlock extends BaseMessage {
|
||||
*/
|
||||
public static FilteredBlock read(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
byte[] headerBytes = Buffers.readBytes(payload, Block.HEADER_SIZE);
|
||||
Block header = new Block(ByteBuffer.wrap(headerBytes));
|
||||
Block header = Block.read(ByteBuffer.wrap(headerBytes));
|
||||
PartialMerkleTree merkleTree = PartialMerkleTree.read(payload);
|
||||
return new FilteredBlock(header, merkleTree);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class HeadersMessage extends BaseMessage {
|
||||
|
||||
List<Block> blockHeaders = new ArrayList<>();
|
||||
for (int i = 0; i < numHeaders; ++i) {
|
||||
final Block newBlockHeader = new Block(payload);
|
||||
final Block newBlockHeader = Block.read(payload);
|
||||
if (newBlockHeader.hasTransactions()) {
|
||||
throw new ProtocolException("Block header does not end with a null byte");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user