mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-13 18:55:52 +00:00
Modify data object serialization/deserialization to provide extension hooks
Make headerParsed, transactionParsed, headerBytesValid and transactionBytesValid protected so subclasses in the same package can access them. Add constructor for use when a block is contained within another object (i.e. AuxPoW header) Make headerParsed, transactionParsed, headerBytesValid and transactionBytesValid protected so subclasses in the same package can access them. Add constructor for use when a block is contained within another object (i.e. AuxPoW header) Add parseTransactions() method which takes in a payload offset, so block parsers can indicate that transactions do not start at byte 80. Extract common interface from BitcoinSerializer to support alternative serializers, as well as dummy serializer for message classes which do not have their network parameters. Thread BitcoinSerializer through messages in place of existing parseLazy and parseRetain properties. Insert dummy serializer into message subclasses when deserialized by Java. Replace calls to construct Block/Transaction classes from payloads, with calls to MessageSerializer, so alternative formats can be supported elegantly. Make headerParsed, transactionParsed, headerBytesValid and transactionBytesValid protected so subclasses in the same package can access them. Add constructor for use when a block is contained within another object (i.e. AuxPoW header) Add parseTransactions() method which takes in a payload offset, so block parsers can indicate that transactions do not start at byte 80.
This commit is contained in:
parent
16a5e1d64b
commit
12602650ce
@ -759,7 +759,7 @@ public abstract class AbstractBlockChain {
|
|||||||
try {
|
try {
|
||||||
falsePositives.remove(tx.getHash());
|
falsePositives.remove(tx.getHash());
|
||||||
if (clone)
|
if (clone)
|
||||||
tx = new Transaction(tx.params, tx.bitcoinSerialize());
|
tx = tx.params.getDefaultSerializer().makeTransaction(tx.bitcoinSerialize());
|
||||||
listener.receiveFromBlock(tx, block, blockType, relativityOffset++);
|
listener.receiveFromBlock(tx, block, blockType, relativityOffset++);
|
||||||
} catch (ScriptException e) {
|
} catch (ScriptException e) {
|
||||||
// We don't want scripts we don't understand to break the block chain so just note that this tx was
|
// We don't want scripts we don't understand to break the block chain so just note that this tx was
|
||||||
|
@ -28,31 +28,28 @@ public class AddressMessage extends Message {
|
|||||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
AddressMessage(NetworkParameters params, byte[] payload, int offset, boolean parseLazy, boolean parseRetain, int length) throws ProtocolException {
|
AddressMessage(NetworkParameters params, byte[] payload, int offset, MessageSerializer setSerializer, int length) throws ProtocolException {
|
||||||
super(params, payload, offset, parseLazy, parseRetain, length);
|
super(params, payload, offset, setSerializer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contruct a new 'addr' message.
|
* Contruct a new 'addr' message.
|
||||||
* @param params NetworkParameters object.
|
* @param params NetworkParameters object.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this block.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
* @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
|
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
AddressMessage(NetworkParameters params, byte[] payload, boolean parseLazy, boolean parseRetain, int length) throws ProtocolException {
|
AddressMessage(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length) throws ProtocolException {
|
||||||
super(params, payload, 0, parseLazy, parseRetain, length);
|
super(params, payload, 0, serializer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressMessage(NetworkParameters params, byte[] payload, int offset) throws ProtocolException {
|
AddressMessage(NetworkParameters params, byte[] payload, int offset) throws ProtocolException {
|
||||||
super(params, payload, offset, false, false, UNKNOWN_LENGTH);
|
super(params, payload, offset, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressMessage(NetworkParameters params, byte[] payload) throws ProtocolException {
|
AddressMessage(NetworkParameters params, byte[] payload) throws ProtocolException {
|
||||||
super(params, payload, 0, false, false, UNKNOWN_LENGTH);
|
super(params, payload, 0, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -67,7 +64,7 @@ public class AddressMessage extends Message {
|
|||||||
throw new ProtocolException("Address message too large.");
|
throw new ProtocolException("Address message too large.");
|
||||||
addresses = new ArrayList<PeerAddress>((int) numAddresses);
|
addresses = new ArrayList<PeerAddress>((int) numAddresses);
|
||||||
for (int i = 0; i < numAddresses; i++) {
|
for (int i = 0; i < numAddresses; i++) {
|
||||||
PeerAddress addr = new PeerAddress(params, payload, cursor, protocolVersion, this, parseLazy, parseRetain);
|
PeerAddress addr = new PeerAddress(params, payload, cursor, protocolVersion, this, serializer);
|
||||||
addresses.add(addr);
|
addresses.add(addr);
|
||||||
cursor += addr.getMessageSize();
|
cursor += addr.getMessageSize();
|
||||||
}
|
}
|
||||||
|
@ -41,15 +41,15 @@ import static org.bitcoinj.core.Utils.*;
|
|||||||
* <li>Message.bitcoinSerializeToStream() needs to be properly subclassed</li>
|
* <li>Message.bitcoinSerializeToStream() needs to be properly subclassed</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public class BitcoinSerializer {
|
public class BitcoinSerializer implements MessageSerializer {
|
||||||
private static final Logger log = LoggerFactory.getLogger(BitcoinSerializer.class);
|
private static final Logger log = LoggerFactory.getLogger(BitcoinSerializer.class);
|
||||||
private static final int COMMAND_LEN = 12;
|
private static final int COMMAND_LEN = 12;
|
||||||
|
|
||||||
private NetworkParameters params;
|
private final NetworkParameters params;
|
||||||
private boolean parseLazy = false;
|
private final boolean parseLazy;
|
||||||
private boolean parseRetain = false;
|
private final boolean parseRetain;
|
||||||
|
|
||||||
private static Map<Class<? extends Message>, String> names = new HashMap<Class<? extends Message>, String>();
|
private static final Map<Class<? extends Message>, String> names = new HashMap<Class<? extends Message>, String>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
names.put(VersionMessage.class, "version");
|
names.put(VersionMessage.class, "version");
|
||||||
@ -75,12 +75,19 @@ public class BitcoinSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a BitcoinSerializer with the given behavior.
|
* Constructs a partial BitcoinSerializer with the given behavior. This is
|
||||||
*
|
* intended for use by messages which do not understand the network they
|
||||||
* @param params networkParams used to create Messages instances and termining packetMagic
|
* belong to.
|
||||||
|
*
|
||||||
|
* @param parseLazy deserialize messages in lazy mode.
|
||||||
|
* @param parseRetain retain the backing byte array of a message for fast reserialization.
|
||||||
|
* @deprecated use BitcoinSerializer(NetworkParameters, boolean, boolean) instead.
|
||||||
*/
|
*/
|
||||||
public BitcoinSerializer(NetworkParameters params) {
|
@Deprecated
|
||||||
this(params, false, false);
|
BitcoinSerializer(boolean parseLazy, boolean parseRetain) {
|
||||||
|
this.params = null;
|
||||||
|
this.parseLazy = parseLazy;
|
||||||
|
this.parseRetain = parseRetain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,6 +106,7 @@ public class BitcoinSerializer {
|
|||||||
/**
|
/**
|
||||||
* Writes message to to the output stream.
|
* Writes message to to the output stream.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void serialize(String name, byte[] message, OutputStream out) throws IOException {
|
public void serialize(String name, byte[] message, OutputStream out) throws IOException {
|
||||||
byte[] header = new byte[4 + COMMAND_LEN + 4 + 4 /* checksum */];
|
byte[] header = new byte[4 + COMMAND_LEN + 4 + 4 /* checksum */];
|
||||||
uint32ToByteArrayBE(params.getPacketMagic(), header, 0);
|
uint32ToByteArrayBE(params.getPacketMagic(), header, 0);
|
||||||
@ -123,6 +131,7 @@ public class BitcoinSerializer {
|
|||||||
/**
|
/**
|
||||||
* Writes message to to the output stream.
|
* Writes message to to the output stream.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void serialize(Message message, OutputStream out) throws IOException {
|
public void serialize(Message message, OutputStream out) throws IOException {
|
||||||
String name = names.get(message.getClass());
|
String name = names.get(message.getClass());
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
@ -134,6 +143,7 @@ public class BitcoinSerializer {
|
|||||||
/**
|
/**
|
||||||
* Reads a message from the given ByteBuffer and returns it.
|
* Reads a message from the given ByteBuffer and returns it.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Message deserialize(ByteBuffer in) throws ProtocolException, IOException {
|
public Message deserialize(ByteBuffer in) throws ProtocolException, IOException {
|
||||||
// A Bitcoin protocol message has the following format.
|
// A Bitcoin protocol message has the following format.
|
||||||
//
|
//
|
||||||
@ -159,6 +169,7 @@ public class BitcoinSerializer {
|
|||||||
* Deserializes only the header in case packet meta data is needed before decoding
|
* Deserializes only the header in case packet meta data is needed before decoding
|
||||||
* the payload. This method assumes you have already called seekPastMagicBytes()
|
* the payload. This method assumes you have already called seekPastMagicBytes()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public BitcoinPacketHeader deserializeHeader(ByteBuffer in) throws ProtocolException, IOException {
|
public BitcoinPacketHeader deserializeHeader(ByteBuffer in) throws ProtocolException, IOException {
|
||||||
return new BitcoinPacketHeader(in);
|
return new BitcoinPacketHeader(in);
|
||||||
}
|
}
|
||||||
@ -167,6 +178,7 @@ public class BitcoinSerializer {
|
|||||||
* Deserialize payload only. You must provide a header, typically obtained by calling
|
* Deserialize payload only. You must provide a header, typically obtained by calling
|
||||||
* {@link BitcoinSerializer#deserializeHeader}.
|
* {@link BitcoinSerializer#deserializeHeader}.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Message deserializePayload(BitcoinPacketHeader header, ByteBuffer in) throws ProtocolException, BufferUnderflowException {
|
public Message deserializePayload(BitcoinPacketHeader header, ByteBuffer in) throws ProtocolException, BufferUnderflowException {
|
||||||
byte[] payloadBytes = new byte[header.size];
|
byte[] payloadBytes = new byte[header.size];
|
||||||
in.get(payloadBytes, 0, header.size);
|
in.get(payloadBytes, 0, header.size);
|
||||||
@ -198,25 +210,22 @@ public class BitcoinSerializer {
|
|||||||
Message message;
|
Message message;
|
||||||
if (command.equals("version")) {
|
if (command.equals("version")) {
|
||||||
return new VersionMessage(params, payloadBytes);
|
return new VersionMessage(params, payloadBytes);
|
||||||
} else if (command.equals("inv")) {
|
} else if (command.equals("inv")) {
|
||||||
message = new InventoryMessage(params, payloadBytes, parseLazy, parseRetain, length);
|
message = makeInventoryMessage(payloadBytes, length);
|
||||||
} else if (command.equals("block")) {
|
} else if (command.equals("block")) {
|
||||||
message = new Block(params, payloadBytes, parseLazy, parseRetain, length);
|
message = makeBlock(payloadBytes, length);
|
||||||
} else if (command.equals("merkleblock")) {
|
} else if (command.equals("merkleblock")) {
|
||||||
message = new FilteredBlock(params, payloadBytes);
|
message = makeFilteredBlock(payloadBytes);
|
||||||
} else if (command.equals("getdata")) {
|
} else if (command.equals("getdata")) {
|
||||||
message = new GetDataMessage(params, payloadBytes, parseLazy, parseRetain, length);
|
message = new GetDataMessage(params, payloadBytes, this, length);
|
||||||
} else if (command.equals("getblocks")) {
|
} else if (command.equals("getblocks")) {
|
||||||
message = new GetBlocksMessage(params, payloadBytes);
|
message = new GetBlocksMessage(params, payloadBytes);
|
||||||
} else if (command.equals("getheaders")) {
|
} else if (command.equals("getheaders")) {
|
||||||
message = new GetHeadersMessage(params, payloadBytes);
|
message = new GetHeadersMessage(params, payloadBytes);
|
||||||
} else if (command.equals("tx")) {
|
} else if (command.equals("tx")) {
|
||||||
Transaction tx = new Transaction(params, payloadBytes, null, parseLazy, parseRetain, length);
|
message = makeTransaction(payloadBytes, 0, length, hash);
|
||||||
if (hash != null)
|
|
||||||
tx.setHash(Sha256Hash.wrapReversed(hash));
|
|
||||||
message = tx;
|
|
||||||
} else if (command.equals("addr")) {
|
} else if (command.equals("addr")) {
|
||||||
message = new AddressMessage(params, payloadBytes, parseLazy, parseRetain, length);
|
message = makeAddressMessage(payloadBytes, length);
|
||||||
} else if (command.equals("ping")) {
|
} else if (command.equals("ping")) {
|
||||||
message = new Ping(params, payloadBytes);
|
message = new Ping(params, payloadBytes);
|
||||||
} else if (command.equals("pong")) {
|
} else if (command.equals("pong")) {
|
||||||
@ -226,9 +235,9 @@ public class BitcoinSerializer {
|
|||||||
} else if (command.equals("headers")) {
|
} else if (command.equals("headers")) {
|
||||||
return new HeadersMessage(params, payloadBytes);
|
return new HeadersMessage(params, payloadBytes);
|
||||||
} else if (command.equals("alert")) {
|
} else if (command.equals("alert")) {
|
||||||
return new AlertMessage(params, payloadBytes);
|
return makeAlertMessage(payloadBytes);
|
||||||
} else if (command.equals("filterload")) {
|
} else if (command.equals("filterload")) {
|
||||||
return new BloomFilter(params, payloadBytes);
|
return makeBloomFilter(payloadBytes);
|
||||||
} else if (command.equals("notfound")) {
|
} else if (command.equals("notfound")) {
|
||||||
return new NotFoundMessage(params, payloadBytes);
|
return new NotFoundMessage(params, payloadBytes);
|
||||||
} else if (command.equals("mempool")) {
|
} else if (command.equals("mempool")) {
|
||||||
@ -246,6 +255,100 @@ public class BitcoinSerializer {
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the network parameters for this serializer.
|
||||||
|
*/
|
||||||
|
public NetworkParameters getParameters() {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an address message from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AddressMessage makeAddressMessage(byte[] payloadBytes, int length) throws ProtocolException {
|
||||||
|
return new AddressMessage(params, payloadBytes, this, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an alert message from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Message makeAlertMessage(byte[] payloadBytes) throws ProtocolException {
|
||||||
|
return new AlertMessage(params, payloadBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a block from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Block makeBlock(byte[] payloadBytes) throws ProtocolException {
|
||||||
|
return new Block(params, payloadBytes, this, payloadBytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a block from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Block makeBlock(byte[] payloadBytes, int length) throws ProtocolException {
|
||||||
|
return new Block(params, payloadBytes, this, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an filter message from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Message makeBloomFilter(byte[] payloadBytes) throws ProtocolException {
|
||||||
|
return new BloomFilter(params, payloadBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a filtered block from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public FilteredBlock makeFilteredBlock(byte[] payloadBytes) throws ProtocolException {
|
||||||
|
return new FilteredBlock(params, payloadBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an inventory message from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public InventoryMessage makeInventoryMessage(byte[] payloadBytes, int length) throws ProtocolException {
|
||||||
|
return new InventoryMessage(params, payloadBytes, this, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a transaction from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Transaction makeTransaction(byte[] payloadBytes, int offset,
|
||||||
|
int length, byte[] hash) throws ProtocolException {
|
||||||
|
Transaction tx = new Transaction(params, payloadBytes, offset, null, this, length);
|
||||||
|
if (hash != null)
|
||||||
|
tx.setHash(Sha256Hash.wrapReversed(hash));
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Transaction makeTransaction(byte[] payloadBytes) throws ProtocolException {
|
||||||
|
return makeTransaction(payloadBytes, 0, payloadBytes.length, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Transaction makeTransaction(byte[] payloadBytes, int offset) throws ProtocolException {
|
||||||
|
return makeTransaction(payloadBytes, offset, payloadBytes.length, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void seekPastMagicBytes(ByteBuffer in) throws BufferUnderflowException {
|
public void seekPastMagicBytes(ByteBuffer in) throws BufferUnderflowException {
|
||||||
int magicCursor = 3; // Which byte of the magic we're looking for currently.
|
int magicCursor = 3; // Which byte of the magic we're looking for currently.
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -270,6 +373,7 @@ public class BitcoinSerializer {
|
|||||||
/**
|
/**
|
||||||
* Whether the serializer will produce lazy parse mode Messages
|
* Whether the serializer will produce lazy parse mode Messages
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean isParseLazyMode() {
|
public boolean isParseLazyMode() {
|
||||||
return parseLazy;
|
return parseLazy;
|
||||||
}
|
}
|
||||||
@ -277,6 +381,7 @@ public class BitcoinSerializer {
|
|||||||
/**
|
/**
|
||||||
* Whether the serializer will produce cached mode Messages
|
* Whether the serializer will produce cached mode Messages
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean isParseRetainMode() {
|
public boolean isParseRetainMode() {
|
||||||
return parseRetain;
|
return parseRetain;
|
||||||
}
|
}
|
||||||
|
@ -87,16 +87,16 @@ public class Block extends Message {
|
|||||||
/** Stores the hash of the block. If null, getHash() will recalculate it. */
|
/** Stores the hash of the block. If null, getHash() will recalculate it. */
|
||||||
private Sha256Hash hash;
|
private Sha256Hash hash;
|
||||||
|
|
||||||
private boolean headerParsed;
|
protected boolean headerParsed;
|
||||||
private boolean transactionsParsed;
|
protected boolean transactionsParsed;
|
||||||
|
|
||||||
private boolean headerBytesValid;
|
protected boolean headerBytesValid;
|
||||||
private boolean transactionBytesValid;
|
protected boolean transactionBytesValid;
|
||||||
|
|
||||||
// Blocks can be encoded in a way that will use more bytes than is optimal (due to VarInts having multiple encodings)
|
// Blocks can be encoded in a way that will use more bytes than is optimal (due to VarInts having multiple encodings)
|
||||||
// MAX_BLOCK_SIZE must be compared to the optimal encoding, not the actual encoding, so when parsing, we keep track
|
// MAX_BLOCK_SIZE must be compared to the optimal encoding, not the actual encoding, so when parsing, we keep track
|
||||||
// of the size of the ideal encoding in addition to the actual message size (which Message needs)
|
// of the size of the ideal encoding in addition to the actual message size (which Message needs)
|
||||||
private int optimalEncodingMessageSize;
|
protected int optimalEncodingMessageSize;
|
||||||
|
|
||||||
/** Special case constructor, used for the genesis node, cloneAsHeader and unit tests. */
|
/** Special case constructor, used for the genesis node, cloneAsHeader and unit tests. */
|
||||||
Block(NetworkParameters params) {
|
Block(NetworkParameters params) {
|
||||||
@ -110,27 +110,46 @@ public class Block extends Message {
|
|||||||
length = 80;
|
length = 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs a block object from the Bitcoin wire format. */
|
/**
|
||||||
|
* Constructs a block object from the Bitcoin wire format.
|
||||||
|
* @deprecated Use {@link BitcoinSerializer#makeBlock(byte[])} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public Block(NetworkParameters params, byte[] payloadBytes) throws ProtocolException {
|
public Block(NetworkParameters params, byte[] payloadBytes) throws ProtocolException {
|
||||||
super(params, payloadBytes, 0, false, false, payloadBytes.length);
|
super(params, payloadBytes, 0, params.getDefaultSerializer(), payloadBytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contruct a block object from the Bitcoin wire format.
|
* Contruct a block object from the Bitcoin wire format.
|
||||||
* @param params NetworkParameters object.
|
* @param params NetworkParameters object.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this message.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
* @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
|
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public Block(NetworkParameters params, byte[] payloadBytes, boolean parseLazy, boolean parseRetain, int length)
|
public Block(NetworkParameters params, byte[] payloadBytes, MessageSerializer serializer, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, payloadBytes, 0, parseLazy, parseRetain, length);
|
super(params, payloadBytes, 0, 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).
|
||||||
|
*
|
||||||
|
* @param params NetworkParameters object.
|
||||||
|
* @param payloadBytes Bitcoin protocol formatted byte array containing message content.
|
||||||
|
* @param offset The location of the first payload byte within the array.
|
||||||
|
* @param parent The message element which contains this block, maybe null for no parent.
|
||||||
|
* @param serializer the serializer to use for this block.
|
||||||
|
* @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, @Nullable Message parent, MessageSerializer serializer, int length)
|
||||||
|
throws ProtocolException {
|
||||||
|
// TODO: Keep the parent
|
||||||
|
super(params, payloadBytes, offset, serializer, length);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a block initialized with all the given fields.
|
* Construct a block initialized with all the given fields.
|
||||||
@ -185,14 +204,25 @@ public class Block extends Message {
|
|||||||
hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(payload, offset, cursor));
|
hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(payload, offset, cursor));
|
||||||
|
|
||||||
headerParsed = true;
|
headerParsed = true;
|
||||||
headerBytesValid = parseRetain;
|
headerBytesValid = serializer.isParseRetainMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseTransactions() throws ProtocolException {
|
protected void parseTransactions() throws ProtocolException {
|
||||||
|
parseTransactions(offset + HEADER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse transactions from the block.
|
||||||
|
*
|
||||||
|
* @param transactionsOffset Offset of the transactions within the block.
|
||||||
|
* Useful for non-Bitcoin chains where the block header may not be a fixed
|
||||||
|
* size.
|
||||||
|
*/
|
||||||
|
protected void parseTransactions(final int transactionsOffset) throws ProtocolException {
|
||||||
if (transactionsParsed)
|
if (transactionsParsed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cursor = offset + HEADER_SIZE;
|
cursor = transactionsOffset;
|
||||||
optimalEncodingMessageSize = HEADER_SIZE;
|
optimalEncodingMessageSize = HEADER_SIZE;
|
||||||
if (payload.length == cursor) {
|
if (payload.length == cursor) {
|
||||||
// This message is just a header, it has no transactions.
|
// This message is just a header, it has no transactions.
|
||||||
@ -205,7 +235,7 @@ public class Block extends Message {
|
|||||||
optimalEncodingMessageSize += VarInt.sizeOf(numTransactions);
|
optimalEncodingMessageSize += VarInt.sizeOf(numTransactions);
|
||||||
transactions = new ArrayList<Transaction>(numTransactions);
|
transactions = new ArrayList<Transaction>(numTransactions);
|
||||||
for (int i = 0; i < numTransactions; i++) {
|
for (int i = 0; i < numTransactions; i++) {
|
||||||
Transaction tx = new Transaction(params, payload, cursor, this, parseLazy, parseRetain, UNKNOWN_LENGTH);
|
Transaction tx = new Transaction(params, payload, cursor, this, serializer, UNKNOWN_LENGTH);
|
||||||
// Label the transaction as coming from the P2P network, so code that cares where we first saw it knows.
|
// 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);
|
tx.getConfidence().setSource(TransactionConfidence.Source.NETWORK);
|
||||||
transactions.add(tx);
|
transactions.add(tx);
|
||||||
@ -215,7 +245,7 @@ public class Block extends Message {
|
|||||||
// No need to set length here. If length was not provided then it should be set at the end of parseLight().
|
// No need to set length here. If length was not provided then it should be set at the end of parseLight().
|
||||||
// If this is a genuine lazy parse then length must have been provided to the constructor.
|
// If this is a genuine lazy parse then length must have been provided to the constructor.
|
||||||
transactionsParsed = true;
|
transactionsParsed = true;
|
||||||
transactionBytesValid = parseRetain;
|
transactionBytesValid = serializer.isParseRetainMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -240,15 +270,15 @@ public class Block extends Message {
|
|||||||
// Ignore the header since it has fixed length. If length is not provided we will have to
|
// Ignore the header since it has fixed length. If length is not provided we will have to
|
||||||
// invoke a light parse of transactions to calculate the length.
|
// invoke a light parse of transactions to calculate the length.
|
||||||
if (length == UNKNOWN_LENGTH) {
|
if (length == UNKNOWN_LENGTH) {
|
||||||
Preconditions.checkState(parseLazy,
|
Preconditions.checkState(serializer.isParseLazyMode(),
|
||||||
"Performing lite parse of block transaction as block was initialised from byte array " +
|
"Performing lite parse of block transaction as block was initialised from byte array " +
|
||||||
"without providing length. This should never need to happen.");
|
"without providing length. This should never need to happen.");
|
||||||
parseTransactions();
|
parseTransactions();
|
||||||
length = cursor - offset;
|
length = cursor - offset;
|
||||||
} else {
|
} else {
|
||||||
transactionBytesValid = !transactionsParsed || parseRetain && length > HEADER_SIZE;
|
transactionBytesValid = !transactionsParsed || serializer.isParseRetainMode() && length > HEADER_SIZE;
|
||||||
}
|
}
|
||||||
headerBytesValid = !headerParsed || parseRetain && length >= HEADER_SIZE;
|
headerBytesValid = !headerParsed || serializer.isParseRetainMode() && length >= HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -282,7 +312,7 @@ public class Block extends Message {
|
|||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
parseTransactions();
|
parseTransactions();
|
||||||
if (!parseRetain) {
|
if (!serializer.isParseRetainMode()) {
|
||||||
transactionBytesValid = false;
|
transactionBytesValid = false;
|
||||||
if (headerParsed)
|
if (headerParsed)
|
||||||
payload = null;
|
payload = null;
|
||||||
|
@ -25,6 +25,10 @@ public abstract class ChildMessage extends Message {
|
|||||||
|
|
||||||
@Nullable protected Message parent;
|
@Nullable protected Message parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #ChildMessage(NetworkParameters) instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
protected ChildMessage() {
|
protected ChildMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,9 +40,8 @@ public abstract class ChildMessage extends Message {
|
|||||||
super(params, payload, offset, protocolVersion);
|
super(params, payload, offset, protocolVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChildMessage(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, boolean parseLazy,
|
public ChildMessage(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, MessageSerializer setSerializer, int length) throws ProtocolException {
|
||||||
boolean parseRetain, int length) throws ProtocolException {
|
super(params, payload, offset, protocolVersion, setSerializer, length);
|
||||||
super(params, payload, offset, protocolVersion, parseLazy, parseRetain, length);
|
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,9 +49,9 @@ public abstract class ChildMessage extends Message {
|
|||||||
super(params, payload, offset);
|
super(params, payload, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChildMessage(NetworkParameters params, byte[] payload, int offset, @Nullable Message parent, boolean parseLazy, boolean parseRetain, int length)
|
public ChildMessage(NetworkParameters params, byte[] payload, int offset, @Nullable Message parent, MessageSerializer setSerializer, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, payload, offset, parseLazy, parseRetain, length);
|
super(params, payload, offset, setSerializer, length);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
125
core/src/main/java/org/bitcoinj/core/DummySerializer.java
Normal file
125
core/src/main/java/org/bitcoinj/core/DummySerializer.java
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 Ross Nicoll
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.bitcoinj.core;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.BufferUnderflowException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy serializer used ONLY for objects which do not have network parameters
|
||||||
|
* set.
|
||||||
|
*/
|
||||||
|
class DummySerializer implements MessageSerializer {
|
||||||
|
public static final DummySerializer DEFAULT = new DummySerializer();
|
||||||
|
|
||||||
|
private static final String DEFAULT_EXCEPTION_MESSAGE = "Dummy serializer cannot serialize/deserialize objects as it does not know which network they belong to.";
|
||||||
|
|
||||||
|
public DummySerializer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message deserialize(ByteBuffer in) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BitcoinSerializer.BitcoinPacketHeader deserializeHeader(ByteBuffer in) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message deserializePayload(BitcoinSerializer.BitcoinPacketHeader header, ByteBuffer in) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParseLazyMode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isParseRetainMode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddressMessage makeAddressMessage(byte[] payloadBytes, int length) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message makeAlertMessage(byte[] payloadBytes) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block makeBlock(byte[] payloadBytes) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block makeBlock(byte[] payloadBytes, int length) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message makeBloomFilter(byte[] payloadBytes) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FilteredBlock makeFilteredBlock(byte[] payloadBytes) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InventoryMessage makeInventoryMessage(byte[] payloadBytes, int length) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Transaction makeTransaction(byte[] payloadBytes, int offset, int length, byte[] hash) throws UnsupportedOperationException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Transaction makeTransaction(byte[] payloadBytes) throws UnsupportedOperationException {
|
||||||
|
return makeTransaction(payloadBytes, 0, payloadBytes.length, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Transaction makeTransaction(byte[] payloadBytes, int offset) throws UnsupportedOperationException {
|
||||||
|
return makeTransaction(payloadBytes, offset, payloadBytes.length, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void seekPastMagicBytes(ByteBuffer in) throws BufferUnderflowException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(String name, byte[] message, OutputStream out) throws IOException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(Message message, OutputStream out) throws IOException {
|
||||||
|
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -60,7 +60,7 @@ public class FilteredBlock extends Message {
|
|||||||
void parse() throws ProtocolException {
|
void parse() throws ProtocolException {
|
||||||
byte[] headerBytes = new byte[Block.HEADER_SIZE];
|
byte[] headerBytes = new byte[Block.HEADER_SIZE];
|
||||||
System.arraycopy(payload, 0, headerBytes, 0, Block.HEADER_SIZE);
|
System.arraycopy(payload, 0, headerBytes, 0, Block.HEADER_SIZE);
|
||||||
header = new Block(params, headerBytes);
|
header = params.getDefaultSerializer().makeBlock(headerBytes);
|
||||||
|
|
||||||
merkleTree = new PartialMerkleTree(params, payload, Block.HEADER_SIZE);
|
merkleTree = new PartialMerkleTree(params, payload, Block.HEADER_SIZE);
|
||||||
|
|
||||||
|
@ -30,17 +30,14 @@ public class GetDataMessage extends ListMessage {
|
|||||||
* Deserializes a 'getdata' message.
|
* Deserializes a 'getdata' message.
|
||||||
* @param params NetworkParameters object.
|
* @param params NetworkParameters object.
|
||||||
* @param payload Bitcoin protocol formatted byte array containing message content.
|
* @param payload Bitcoin protocol formatted byte array containing message content.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this message.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
* @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
|
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public GetDataMessage(NetworkParameters params, byte[] payload, boolean parseLazy, boolean parseRetain, int length)
|
public GetDataMessage(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, payload, parseLazy, parseRetain, length);
|
super(params, payload, serializer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GetDataMessage(NetworkParameters params) {
|
public GetDataMessage(NetworkParameters params) {
|
||||||
|
@ -88,7 +88,8 @@ public class HeadersMessage extends Message {
|
|||||||
byte[] blockHeader = readBytes(81);
|
byte[] blockHeader = readBytes(81);
|
||||||
if (blockHeader[80] != 0)
|
if (blockHeader[80] != 0)
|
||||||
throw new ProtocolException("Block header does not end with a null byte");
|
throw new ProtocolException("Block header does not end with a null byte");
|
||||||
Block newBlockHeader = new Block(this.params, blockHeader, true, true, 81);
|
Block newBlockHeader = this.params.getSerializer(true, true)
|
||||||
|
.makeBlock(blockHeader, 81);
|
||||||
blockHeaders.add(newBlockHeader);
|
blockHeaders.add(newBlockHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,17 +37,14 @@ public class InventoryMessage extends ListMessage {
|
|||||||
* Deserializes an 'inv' message.
|
* Deserializes an 'inv' message.
|
||||||
* @param params NetworkParameters object.
|
* @param params NetworkParameters object.
|
||||||
* @param payload Bitcoin protocol formatted byte array containing message content.
|
* @param payload Bitcoin protocol formatted byte array containing message content.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this message.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
* @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
|
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public InventoryMessage(NetworkParameters params, byte[] payload, boolean parseLazy, boolean parseRetain, int length)
|
public InventoryMessage(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, payload, parseLazy, parseRetain, length);
|
super(params, payload, serializer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InventoryMessage(NetworkParameters params) {
|
public InventoryMessage(NetworkParameters params) {
|
||||||
|
@ -37,9 +37,9 @@ public abstract class ListMessage extends Message {
|
|||||||
super(params, bytes, 0);
|
super(params, bytes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListMessage(NetworkParameters params, byte[] payload, boolean parseLazy, boolean parseRetain, int length)
|
public ListMessage(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, payload, 0, parseLazy, parseRetain, length);
|
super(params, payload, 0, serializer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListMessage(NetworkParameters params) {
|
public ListMessage(NetworkParameters params) {
|
||||||
|
@ -54,8 +54,7 @@ public abstract class Message {
|
|||||||
|
|
||||||
protected boolean parsed = false;
|
protected boolean parsed = false;
|
||||||
protected boolean recached = false;
|
protected boolean recached = false;
|
||||||
protected final boolean parseLazy;
|
protected MessageSerializer serializer;
|
||||||
protected final boolean parseRetain;
|
|
||||||
|
|
||||||
protected int protocolVersion;
|
protected int protocolVersion;
|
||||||
|
|
||||||
@ -63,19 +62,17 @@ public abstract class Message {
|
|||||||
|
|
||||||
protected Message() {
|
protected Message() {
|
||||||
parsed = true;
|
parsed = true;
|
||||||
parseLazy = false;
|
serializer = DummySerializer.DEFAULT;
|
||||||
parseRetain = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Message(NetworkParameters params) {
|
Message(NetworkParameters params) {
|
||||||
this.params = params;
|
this.params = params;
|
||||||
parsed = true;
|
parsed = true;
|
||||||
parseLazy = false;
|
serializer = params.getDefaultSerializer();
|
||||||
parseRetain = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Message(NetworkParameters params, byte[] payload, int offset, int protocolVersion) throws ProtocolException {
|
Message(NetworkParameters params, byte[] payload, int offset, int protocolVersion) throws ProtocolException {
|
||||||
this(params, payload, offset, protocolVersion, false, false, UNKNOWN_LENGTH);
|
this(params, payload, offset, protocolVersion, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,23 +81,19 @@ public abstract class Message {
|
|||||||
* @param payload Bitcoin protocol formatted byte array containing message content.
|
* @param payload Bitcoin protocol formatted byte array containing message content.
|
||||||
* @param offset The location of the first payload byte within the array.
|
* @param offset The location of the first payload byte within the array.
|
||||||
* @param protocolVersion Bitcoin protocol version.
|
* @param protocolVersion Bitcoin protocol version.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this message.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* @param length The length of message payload if known. Usually this is provided when deserializing of the wire
|
* @param length The length of message payload 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
|
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
Message(NetworkParameters params, byte[] payload, int offset, int protocolVersion, boolean parseLazy, boolean parseRetain, int length) throws ProtocolException {
|
Message(NetworkParameters params, byte[] payload, int offset, int protocolVersion, MessageSerializer serializer, int length) throws ProtocolException {
|
||||||
this.parseLazy = parseLazy;
|
this.serializer = serializer;
|
||||||
this.parseRetain = parseRetain;
|
|
||||||
this.protocolVersion = protocolVersion;
|
this.protocolVersion = protocolVersion;
|
||||||
this.params = params;
|
this.params = params;
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
this.cursor = this.offset = offset;
|
this.cursor = this.offset = offset;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
if (parseLazy) {
|
if (serializer.isParseLazyMode()) {
|
||||||
parseLite();
|
parseLite();
|
||||||
} else {
|
} else {
|
||||||
parseLite();
|
parseLite();
|
||||||
@ -111,13 +104,13 @@ public abstract class Message {
|
|||||||
if (this.length == UNKNOWN_LENGTH)
|
if (this.length == UNKNOWN_LENGTH)
|
||||||
checkState(false, "Length field has not been set in constructor for %s after %s parse. " +
|
checkState(false, "Length field has not been set in constructor for %s after %s parse. " +
|
||||||
"Refer to Message.parseLite() for detail of required Length field contract.",
|
"Refer to Message.parseLite() for detail of required Length field contract.",
|
||||||
getClass().getSimpleName(), parseLazy ? "lite" : "full");
|
getClass().getSimpleName(), serializer.isParseLazyMode() ? "lite" : "full");
|
||||||
|
|
||||||
if (SELF_CHECK) {
|
if (SELF_CHECK) {
|
||||||
selfCheck(payload, offset);
|
selfCheck(payload, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseRetain || !parsed)
|
if (serializer.isParseRetainMode() || !parsed)
|
||||||
return;
|
return;
|
||||||
this.payload = null;
|
this.payload = null;
|
||||||
}
|
}
|
||||||
@ -136,11 +129,11 @@ public abstract class Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Message(NetworkParameters params, byte[] payload, int offset) throws ProtocolException {
|
Message(NetworkParameters params, byte[] payload, int offset) throws ProtocolException {
|
||||||
this(params, payload, offset, NetworkParameters.PROTOCOL_VERSION, false, false, UNKNOWN_LENGTH);
|
this(params, payload, offset, NetworkParameters.PROTOCOL_VERSION, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
Message(NetworkParameters params, byte[] payload, int offset, boolean parseLazy, boolean parseRetain, int length) throws ProtocolException {
|
Message(NetworkParameters params, byte[] payload, int offset, MessageSerializer serializer, int length) throws ProtocolException {
|
||||||
this(params, payload, offset, NetworkParameters.PROTOCOL_VERSION, parseLazy, parseRetain, length);
|
this(params, payload, offset, NetworkParameters.PROTOCOL_VERSION, serializer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These methods handle the serialization/deserialization using the custom Bitcoin protocol.
|
// These methods handle the serialization/deserialization using the custom Bitcoin protocol.
|
||||||
@ -172,7 +165,7 @@ public abstract class Message {
|
|||||||
try {
|
try {
|
||||||
parse();
|
parse();
|
||||||
parsed = true;
|
parsed = true;
|
||||||
if (!parseRetain)
|
if (!serializer.isParseRetainMode())
|
||||||
payload = null;
|
payload = null;
|
||||||
} catch (ProtocolException e) {
|
} catch (ProtocolException e) {
|
||||||
throw new LazyParseException("ProtocolException caught during lazy parse. For safe access to fields call ensureParsed before attempting read or write access", e);
|
throw new LazyParseException("ProtocolException caught during lazy parse. For safe access to fields call ensureParsed before attempting read or write access", e);
|
||||||
@ -297,7 +290,7 @@ public abstract class Message {
|
|||||||
// Cannot happen, we are serializing to a memory stream.
|
// Cannot happen, we are serializing to a memory stream.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseRetain) {
|
if (serializer.isParseRetainMode()) {
|
||||||
// A free set of steak knives!
|
// A free set of steak knives!
|
||||||
// If there happens to be a call to this method we gain an opportunity to recache
|
// If there happens to be a call to this method we gain an opportunity to recache
|
||||||
// the byte array and in this case it contains no bytes from parent messages.
|
// the byte array and in this case it contains no bytes from parent messages.
|
||||||
@ -445,6 +438,17 @@ public abstract class Message {
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the serializer for this message when deserialized by Java.
|
||||||
|
*/
|
||||||
|
private void readObject(java.io.ObjectInputStream in)
|
||||||
|
throws IOException, ClassNotFoundException {
|
||||||
|
in.defaultReadObject();
|
||||||
|
if (null != params) {
|
||||||
|
this.serializer = params.getDefaultSerializer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class LazyParseException extends RuntimeException {
|
public static class LazyParseException extends RuntimeException {
|
||||||
|
|
||||||
public LazyParseException(String message, Throwable cause) {
|
public LazyParseException(String message, Throwable cause) {
|
||||||
|
155
core/src/main/java/org/bitcoinj/core/MessageSerializer.java
Normal file
155
core/src/main/java/org/bitcoinj/core/MessageSerializer.java
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 Google Inc.
|
||||||
|
* Copyright 2014 Andreas Schildbach
|
||||||
|
* Copyright 2015 Ross Nicoll
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.bitcoinj.core;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.BufferUnderflowException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic interface for classes which serialize/deserialize messages. Implementing
|
||||||
|
* classes should be immutable.
|
||||||
|
*/
|
||||||
|
public interface MessageSerializer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a message from the given ByteBuffer and returns it.
|
||||||
|
*/
|
||||||
|
Message deserialize(ByteBuffer in) throws ProtocolException, IOException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes only the header in case packet meta data is needed before decoding
|
||||||
|
* the payload. This method assumes you have already called seekPastMagicBytes()
|
||||||
|
*/
|
||||||
|
BitcoinSerializer.BitcoinPacketHeader deserializeHeader(ByteBuffer in) throws ProtocolException, IOException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize payload only. You must provide a header, typically obtained by calling
|
||||||
|
* {@link BitcoinSerializer#deserializeHeader}.
|
||||||
|
*/
|
||||||
|
Message deserializePayload(BitcoinSerializer.BitcoinPacketHeader header, ByteBuffer in) throws ProtocolException, BufferUnderflowException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the serializer will produce lazy parse mode Messages
|
||||||
|
*/
|
||||||
|
boolean isParseLazyMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the serializer will produce cached mode Messages
|
||||||
|
*/
|
||||||
|
boolean isParseRetainMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an address message from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
AddressMessage makeAddressMessage(byte[] payloadBytes, int length) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an alert message from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
Message makeAlertMessage(byte[] payloadBytes) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a block from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
Block makeBlock(byte[] payloadBytes) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a block from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
Block makeBlock(byte[] payloadBytes, int length) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an filter message from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
Message makeBloomFilter(byte[] payloadBytes) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a filtered block from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
FilteredBlock makeFilteredBlock(byte[] payloadBytes) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an inventory message from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*/
|
||||||
|
InventoryMessage makeInventoryMessage(byte[] payloadBytes, int length) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a transaction from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if this serializer/deserializer
|
||||||
|
* does not support deserialization. This can occur either because it's a dummy
|
||||||
|
* serializer (i.e. for messages with no network parameters), or because
|
||||||
|
* it does not support deserializing transactions.
|
||||||
|
*/
|
||||||
|
Transaction makeTransaction(byte[] payloadBytes, int offset, int length, byte[] hash) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a transaction from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if this serializer/deserializer
|
||||||
|
* does not support deserialization. This can occur either because it's a dummy
|
||||||
|
* serializer (i.e. for messages with no network parameters), or because
|
||||||
|
* it does not support deserializing transactions.
|
||||||
|
*/
|
||||||
|
Transaction makeTransaction(byte[] payloadBytes) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a transaction from the payload. Extension point for alternative
|
||||||
|
* serialization format support.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if this serializer/deserializer
|
||||||
|
* does not support deserialization. This can occur either because it's a dummy
|
||||||
|
* serializer (i.e. for messages with no network parameters), or because
|
||||||
|
* it does not support deserializing transactions.
|
||||||
|
*/
|
||||||
|
Transaction makeTransaction(byte[] payloadBytes, int offset) throws ProtocolException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
void seekPastMagicBytes(ByteBuffer in) throws BufferUnderflowException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes message to to the output stream.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if this serializer/deserializer
|
||||||
|
* does not support serialization. This can occur either because it's a dummy
|
||||||
|
* serializer (i.e. for messages with no network parameters), or because
|
||||||
|
* it does not support serializing the given message.
|
||||||
|
*/
|
||||||
|
void serialize(String name, byte[] message, OutputStream out) throws IOException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes message to to the output stream.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if this serializer/deserializer
|
||||||
|
* does not support serialization. This can occur either because it's a dummy
|
||||||
|
* serializer (i.e. for messages with no network parameters), or because
|
||||||
|
* it does not support serializing the given message.
|
||||||
|
*/
|
||||||
|
void serialize(Message message, OutputStream out) throws IOException, UnsupportedOperationException;
|
||||||
|
|
||||||
|
}
|
@ -104,6 +104,7 @@ public abstract class NetworkParameters {
|
|||||||
protected int[] addrSeeds;
|
protected int[] addrSeeds;
|
||||||
protected HttpDiscovery.Details[] httpSeeds = {};
|
protected HttpDiscovery.Details[] httpSeeds = {};
|
||||||
protected Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>();
|
protected Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>();
|
||||||
|
protected transient MessageSerializer defaultSerializer = null;
|
||||||
|
|
||||||
protected NetworkParameters() {
|
protected NetworkParameters() {
|
||||||
alertSigningKey = SATOSHI_KEY;
|
alertSigningKey = SATOSHI_KEY;
|
||||||
@ -417,4 +418,31 @@ public abstract class NetworkParameters {
|
|||||||
* networks.
|
* networks.
|
||||||
*/
|
*/
|
||||||
public abstract boolean hasMaxMoney();
|
public abstract boolean hasMaxMoney();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the default serializer for this network. This is a shared serializer.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public final MessageSerializer getDefaultSerializer() {
|
||||||
|
// Construct a default serializer if we don't have one
|
||||||
|
if (null == this.defaultSerializer) {
|
||||||
|
// Don't grab a lock unless we absolutely need it
|
||||||
|
synchronized(this) {
|
||||||
|
// Now we have a lock, double check there's still no serializer
|
||||||
|
// and create one if so.
|
||||||
|
if (null == this.defaultSerializer) {
|
||||||
|
// As the serializers are intended to be immutable, creating
|
||||||
|
// two due to a race condition should not be a problem, however
|
||||||
|
// to be safe we ensure only one exists for each network.
|
||||||
|
this.defaultSerializer = getSerializer(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct and return a custom serializer.
|
||||||
|
*/
|
||||||
|
public abstract BitcoinSerializer getSerializer(boolean parseLazy, boolean parseRetain);
|
||||||
}
|
}
|
||||||
|
@ -58,15 +58,11 @@ public class PeerAddress extends ChildMessage {
|
|||||||
* @param payload Bitcoin protocol formatted byte array containing message content.
|
* @param payload Bitcoin protocol formatted byte array containing message content.
|
||||||
* @param offset The location of the first payload byte within the array.
|
* @param offset The location of the first payload byte within the array.
|
||||||
* @param protocolVersion Bitcoin protocol version.
|
* @param protocolVersion Bitcoin protocol version.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this message.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public PeerAddress(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, boolean parseLazy,
|
public PeerAddress(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, MessageSerializer serializer) throws ProtocolException {
|
||||||
boolean parseRetain) throws ProtocolException {
|
super(params, payload, offset, protocolVersion, parent, serializer, UNKNOWN_LENGTH);
|
||||||
super(params, payload, offset, protocolVersion, parent, parseLazy, parseRetain, UNKNOWN_LENGTH);
|
|
||||||
// Message length is calculated in parseLite which is guaranteed to be called before it is ever read.
|
// Message length is calculated in parseLite which is guaranteed to be called before it is ever read.
|
||||||
// Even though message length is static for a PeerAddress it is safer to leave it there
|
// Even though message length is static for a PeerAddress it is safer to leave it there
|
||||||
// as it will be set regardless of which constructor was used.
|
// as it will be set regardless of which constructor was used.
|
||||||
|
@ -42,7 +42,7 @@ import static com.google.common.base.Preconditions.*;
|
|||||||
public abstract class PeerSocketHandler extends AbstractTimeoutHandler implements StreamParser {
|
public abstract class PeerSocketHandler extends AbstractTimeoutHandler implements StreamParser {
|
||||||
private static final Logger log = LoggerFactory.getLogger(PeerSocketHandler.class);
|
private static final Logger log = LoggerFactory.getLogger(PeerSocketHandler.class);
|
||||||
|
|
||||||
private final BitcoinSerializer serializer;
|
private final MessageSerializer serializer;
|
||||||
protected PeerAddress peerAddress;
|
protected PeerAddress peerAddress;
|
||||||
// If we close() before we know our writeTarget, set this to true to call writeTarget.closeConnection() right away.
|
// If we close() before we know our writeTarget, set this to true to call writeTarget.closeConnection() right away.
|
||||||
private boolean closePending = false;
|
private boolean closePending = false;
|
||||||
@ -59,12 +59,14 @@ public abstract class PeerSocketHandler extends AbstractTimeoutHandler implement
|
|||||||
private Lock lock = Threading.lock("PeerSocketHandler");
|
private Lock lock = Threading.lock("PeerSocketHandler");
|
||||||
|
|
||||||
public PeerSocketHandler(NetworkParameters params, InetSocketAddress remoteIp) {
|
public PeerSocketHandler(NetworkParameters params, InetSocketAddress remoteIp) {
|
||||||
serializer = new BitcoinSerializer(checkNotNull(params));
|
checkNotNull(params);
|
||||||
|
serializer = params.getDefaultSerializer();
|
||||||
this.peerAddress = new PeerAddress(remoteIp);
|
this.peerAddress = new PeerAddress(remoteIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PeerSocketHandler(NetworkParameters params, PeerAddress peerAddress) {
|
public PeerSocketHandler(NetworkParameters params, PeerAddress peerAddress) {
|
||||||
serializer = new BitcoinSerializer(checkNotNull(params));
|
checkNotNull(params);
|
||||||
|
serializer = params.getDefaultSerializer();
|
||||||
this.peerAddress = checkNotNull(peerAddress);
|
this.peerAddress = checkNotNull(peerAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ public class StoredBlock {
|
|||||||
int height = buffer.getInt(); // +4 bytes
|
int height = buffer.getInt(); // +4 bytes
|
||||||
byte[] header = new byte[Block.HEADER_SIZE + 1]; // Extra byte for the 00 transactions length.
|
byte[] header = new byte[Block.HEADER_SIZE + 1]; // Extra byte for the 00 transactions length.
|
||||||
buffer.get(header, 0, Block.HEADER_SIZE);
|
buffer.get(header, 0, Block.HEADER_SIZE);
|
||||||
return new StoredBlock(new Block(params, header), chainWork, height);
|
return new StoredBlock(params.getDefaultSerializer().makeBlock(header), chainWork, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -209,17 +209,17 @@ public class Transaction extends ChildMessage {
|
|||||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public Transaction(NetworkParameters params, byte[] payload, int offset, @Nullable Message parent, boolean parseLazy, boolean parseRetain, int length)
|
public Transaction(NetworkParameters params, byte[] payload, int offset, @Nullable Message parent, MessageSerializer setSerializer, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, payload, offset, parent, parseLazy, parseRetain, length);
|
super(params, payload, offset, parent, setSerializer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a transaction by reading payload. Length of a transaction is fixed.
|
* Creates a transaction by reading payload. Length of a transaction is fixed.
|
||||||
*/
|
*/
|
||||||
public Transaction(NetworkParameters params, byte[] payload, @Nullable Message parent, boolean parseLazy, boolean parseRetain, int length)
|
public Transaction(NetworkParameters params, byte[] payload, @Nullable Message parent, MessageSerializer setSerializer, int length)
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, payload, 0, parent, parseLazy, parseRetain, length);
|
super(params, payload, 0, parent, setSerializer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -483,7 +483,7 @@ public class Transaction extends ChildMessage {
|
|||||||
protected void parseLite() throws ProtocolException {
|
protected void parseLite() throws ProtocolException {
|
||||||
|
|
||||||
//skip this if the length has been provided i.e. the tx is not part of a block
|
//skip this if the length has been provided i.e. the tx is not part of a block
|
||||||
if (parseLazy && length == UNKNOWN_LENGTH) {
|
if (serializer.isParseLazyMode() && length == UNKNOWN_LENGTH) {
|
||||||
//If length hasn't been provided this tx is probably contained within a block.
|
//If length hasn't been provided this tx is probably contained within a block.
|
||||||
//In parseRetain mode the block needs to know how long the transaction is
|
//In parseRetain mode the block needs to know how long the transaction is
|
||||||
//unfortunately this requires a fairly deep (though not total) parse.
|
//unfortunately this requires a fairly deep (though not total) parse.
|
||||||
@ -554,7 +554,7 @@ public class Transaction extends ChildMessage {
|
|||||||
optimalEncodingMessageSize += VarInt.sizeOf(numInputs);
|
optimalEncodingMessageSize += VarInt.sizeOf(numInputs);
|
||||||
inputs = new ArrayList<TransactionInput>((int) numInputs);
|
inputs = new ArrayList<TransactionInput>((int) numInputs);
|
||||||
for (long i = 0; i < numInputs; i++) {
|
for (long i = 0; i < numInputs; i++) {
|
||||||
TransactionInput input = new TransactionInput(params, this, payload, cursor, parseLazy, parseRetain);
|
TransactionInput input = new TransactionInput(params, this, payload, cursor, serializer);
|
||||||
inputs.add(input);
|
inputs.add(input);
|
||||||
long scriptLen = readVarInt(TransactionOutPoint.MESSAGE_LENGTH);
|
long scriptLen = readVarInt(TransactionOutPoint.MESSAGE_LENGTH);
|
||||||
optimalEncodingMessageSize += TransactionOutPoint.MESSAGE_LENGTH + VarInt.sizeOf(scriptLen) + scriptLen + 4;
|
optimalEncodingMessageSize += TransactionOutPoint.MESSAGE_LENGTH + VarInt.sizeOf(scriptLen) + scriptLen + 4;
|
||||||
@ -565,7 +565,7 @@ public class Transaction extends ChildMessage {
|
|||||||
optimalEncodingMessageSize += VarInt.sizeOf(numOutputs);
|
optimalEncodingMessageSize += VarInt.sizeOf(numOutputs);
|
||||||
outputs = new ArrayList<TransactionOutput>((int) numOutputs);
|
outputs = new ArrayList<TransactionOutput>((int) numOutputs);
|
||||||
for (long i = 0; i < numOutputs; i++) {
|
for (long i = 0; i < numOutputs; i++) {
|
||||||
TransactionOutput output = new TransactionOutput(params, this, payload, cursor, parseLazy, parseRetain);
|
TransactionOutput output = new TransactionOutput(params, this, payload, cursor, serializer);
|
||||||
outputs.add(output);
|
outputs.add(output);
|
||||||
long scriptLen = readVarInt(8);
|
long scriptLen = readVarInt(8);
|
||||||
optimalEncodingMessageSize += 8 + VarInt.sizeOf(scriptLen) + scriptLen;
|
optimalEncodingMessageSize += 8 + VarInt.sizeOf(scriptLen) + scriptLen;
|
||||||
|
@ -116,17 +116,12 @@ public class TransactionInput extends ChildMessage {
|
|||||||
* @param params NetworkParameters object.
|
* @param params NetworkParameters object.
|
||||||
* @param payload Bitcoin protocol formatted byte array containing message content.
|
* @param payload Bitcoin protocol formatted byte array containing message content.
|
||||||
* @param offset The location of the first payload byte within the array.
|
* @param offset The location of the first payload byte within the array.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this message.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public TransactionInput(NetworkParameters params, Transaction parentTransaction, byte[] payload, int offset,
|
public TransactionInput(NetworkParameters params, Transaction parentTransaction, byte[] payload, int offset, MessageSerializer serializer)
|
||||||
boolean parseLazy, boolean parseRetain)
|
|
||||||
throws ProtocolException {
|
throws ProtocolException {
|
||||||
super(params, payload, offset, parentTransaction, parseLazy, parseRetain, UNKNOWN_LENGTH);
|
super(params, payload, offset, parentTransaction, serializer, UNKNOWN_LENGTH);
|
||||||
this.value = null;
|
this.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +135,7 @@ public class TransactionInput extends ChildMessage {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void parse() throws ProtocolException {
|
void parse() throws ProtocolException {
|
||||||
outpoint = new TransactionOutPoint(params, payload, cursor, this, parseLazy, parseRetain);
|
outpoint = new TransactionOutPoint(params, payload, cursor, this, serializer);
|
||||||
cursor += outpoint.getMessageSize();
|
cursor += outpoint.getMessageSize();
|
||||||
int scriptLen = (int) readVarInt();
|
int scriptLen = (int) readVarInt();
|
||||||
scriptBytes = readBytes(scriptLen);
|
scriptBytes = readBytes(scriptLen);
|
||||||
|
@ -80,14 +80,11 @@ public class TransactionOutPoint extends ChildMessage {
|
|||||||
* Deserializes the message. This is usually part of a transaction message.
|
* Deserializes the message. This is usually part of a transaction message.
|
||||||
* @param params NetworkParameters object.
|
* @param params NetworkParameters object.
|
||||||
* @param offset The location of the first payload byte within the array.
|
* @param offset The location of the first payload byte within the array.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this message.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public TransactionOutPoint(NetworkParameters params, byte[] payload, int offset, Message parent, boolean parseLazy, boolean parseRetain) throws ProtocolException {
|
public TransactionOutPoint(NetworkParameters params, byte[] payload, int offset, Message parent, MessageSerializer serializer) throws ProtocolException {
|
||||||
super(params, payload, offset, parent, parseLazy, parseRetain, MESSAGE_LENGTH);
|
super(params, payload, offset, parent, serializer, MESSAGE_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,15 +69,11 @@ public class TransactionOutput extends ChildMessage {
|
|||||||
* @param params NetworkParameters object.
|
* @param params NetworkParameters object.
|
||||||
* @param payload Bitcoin protocol formatted byte array containing message content.
|
* @param payload Bitcoin protocol formatted byte array containing message content.
|
||||||
* @param offset The location of the first payload byte within the array.
|
* @param offset The location of the first payload byte within the array.
|
||||||
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
|
* @param serializer the serializer to use for this message.
|
||||||
* @param parseRetain Whether to retain the backing byte array for quick reserialization.
|
|
||||||
* If true and the backing byte array is invalidated due to modification of a field then
|
|
||||||
* the cached bytes may be repopulated and retained if the message is serialized again in the future.
|
|
||||||
* @throws ProtocolException
|
* @throws ProtocolException
|
||||||
*/
|
*/
|
||||||
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, byte[] payload, int offset,
|
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, byte[] payload, int offset, MessageSerializer serializer) throws ProtocolException {
|
||||||
boolean parseLazy, boolean parseRetain) throws ProtocolException {
|
super(params, payload, offset, parent, serializer, UNKNOWN_LENGTH);
|
||||||
super(params, payload, offset, parent, parseLazy, parseRetain, UNKNOWN_LENGTH);
|
|
||||||
availableForSpending = true;
|
availableForSpending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,9 @@ import org.bitcoinj.store.BlockStoreException;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
import org.bitcoinj.core.BitcoinSerializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters for Bitcoin-like networks.
|
* Parameters for Bitcoin-like networks.
|
||||||
*/
|
*/
|
||||||
@ -133,6 +136,11 @@ public abstract class AbstractBitcoinNetParams extends NetworkParameters {
|
|||||||
return new MonetaryFormat();
|
return new MonetaryFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BitcoinSerializer getSerializer(boolean parseLazy, boolean parseRetain) {
|
||||||
|
return new BitcoinSerializer(this, parseLazy, parseRetain);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUriScheme() {
|
public String getUriScheme() {
|
||||||
return BITCOIN_SCHEME;
|
return BITCOIN_SCHEME;
|
||||||
|
@ -373,7 +373,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
|
|||||||
private void receiveClose(Protos.TwoWayChannelMessage msg) throws VerificationException {
|
private void receiveClose(Protos.TwoWayChannelMessage msg) throws VerificationException {
|
||||||
checkState(lock.isHeldByCurrentThread());
|
checkState(lock.isHeldByCurrentThread());
|
||||||
if (msg.hasSettlement()) {
|
if (msg.hasSettlement()) {
|
||||||
Transaction settleTx = new Transaction(wallet.getParams(), msg.getSettlement().getTx().toByteArray());
|
Transaction settleTx = wallet.getParams().getDefaultSerializer().makeTransaction(msg.getSettlement().getTx().toByteArray());
|
||||||
log.info("CLOSE message received with settlement tx {}", settleTx.getHash());
|
log.info("CLOSE message received with settlement tx {}", settleTx.getHash());
|
||||||
// TODO: set source
|
// TODO: set source
|
||||||
if (state != null && state().isSettlementTransaction(settleTx)) {
|
if (state != null && state().isSettlementTransaction(settleTx)) {
|
||||||
|
@ -295,7 +295,7 @@ public class PaymentChannelServer {
|
|||||||
|
|
||||||
Protos.ProvideRefund providedRefund = msg.getProvideRefund();
|
Protos.ProvideRefund providedRefund = msg.getProvideRefund();
|
||||||
state = new PaymentChannelServerState(broadcaster, wallet, myKey, expireTime);
|
state = new PaymentChannelServerState(broadcaster, wallet, myKey, expireTime);
|
||||||
byte[] signature = state.provideRefundTransaction(new Transaction(wallet.getParams(), providedRefund.getTx().toByteArray()),
|
byte[] signature = state.provideRefundTransaction(wallet.getParams().getDefaultSerializer().makeTransaction(providedRefund.getTx().toByteArray()),
|
||||||
providedRefund.getMultisigKey().toByteArray());
|
providedRefund.getMultisigKey().toByteArray());
|
||||||
|
|
||||||
step = InitStep.WAITING_ON_CONTRACT;
|
step = InitStep.WAITING_ON_CONTRACT;
|
||||||
@ -349,7 +349,7 @@ public class PaymentChannelServer {
|
|||||||
final Protos.ProvideContract providedContract = msg.getProvideContract();
|
final Protos.ProvideContract providedContract = msg.getProvideContract();
|
||||||
|
|
||||||
//TODO notify connection handler that timeout should be significantly extended as we wait for network propagation?
|
//TODO notify connection handler that timeout should be significantly extended as we wait for network propagation?
|
||||||
final Transaction multisigContract = new Transaction(wallet.getParams(), providedContract.getTx().toByteArray());
|
final Transaction multisigContract = wallet.getParams().getDefaultSerializer().makeTransaction(providedContract.getTx().toByteArray());
|
||||||
step = InitStep.WAITING_ON_MULTISIG_ACCEPTANCE;
|
step = InitStep.WAITING_ON_MULTISIG_ACCEPTANCE;
|
||||||
state.provideMultiSigContract(multisigContract)
|
state.provideMultiSigContract(multisigContract)
|
||||||
.addListener(new Runnable() {
|
.addListener(new Runnable() {
|
||||||
|
@ -302,13 +302,13 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
|
|||||||
NetworkParameters params = containingWallet.getParams();
|
NetworkParameters params = containingWallet.getParams();
|
||||||
ClientState.StoredClientPaymentChannels states = ClientState.StoredClientPaymentChannels.parseFrom(data);
|
ClientState.StoredClientPaymentChannels states = ClientState.StoredClientPaymentChannels.parseFrom(data);
|
||||||
for (ClientState.StoredClientPaymentChannel storedState : states.getChannelsList()) {
|
for (ClientState.StoredClientPaymentChannel storedState : states.getChannelsList()) {
|
||||||
Transaction refundTransaction = new Transaction(params, storedState.getRefundTransaction().toByteArray());
|
Transaction refundTransaction = params.getDefaultSerializer().makeTransaction(storedState.getRefundTransaction().toByteArray());
|
||||||
refundTransaction.getConfidence().setSource(TransactionConfidence.Source.SELF);
|
refundTransaction.getConfidence().setSource(TransactionConfidence.Source.SELF);
|
||||||
ECKey myKey = (storedState.getMyKey().isEmpty()) ?
|
ECKey myKey = (storedState.getMyKey().isEmpty()) ?
|
||||||
containingWallet.findKeyFromPubKey(storedState.getMyPublicKey().toByteArray()) :
|
containingWallet.findKeyFromPubKey(storedState.getMyPublicKey().toByteArray()) :
|
||||||
ECKey.fromPrivate(storedState.getMyKey().toByteArray());
|
ECKey.fromPrivate(storedState.getMyKey().toByteArray());
|
||||||
StoredClientChannel channel = new StoredClientChannel(Sha256Hash.wrap(storedState.getId().toByteArray()),
|
StoredClientChannel channel = new StoredClientChannel(Sha256Hash.wrap(storedState.getId().toByteArray()),
|
||||||
new Transaction(params, storedState.getContractTransaction().toByteArray()),
|
params.getDefaultSerializer().makeTransaction(storedState.getContractTransaction().toByteArray()),
|
||||||
refundTransaction,
|
refundTransaction,
|
||||||
myKey,
|
myKey,
|
||||||
Coin.valueOf(storedState.getValueToMe()),
|
Coin.valueOf(storedState.getValueToMe()),
|
||||||
|
@ -232,7 +232,7 @@ public class StoredPaymentChannelServerStates implements WalletExtension {
|
|||||||
NetworkParameters params = containingWallet.getParams();
|
NetworkParameters params = containingWallet.getParams();
|
||||||
for (ServerState.StoredServerPaymentChannel storedState : states.getChannelsList()) {
|
for (ServerState.StoredServerPaymentChannel storedState : states.getChannelsList()) {
|
||||||
StoredServerChannel channel = new StoredServerChannel(null,
|
StoredServerChannel channel = new StoredServerChannel(null,
|
||||||
new Transaction(params, storedState.getContractTransaction().toByteArray()),
|
params.getDefaultSerializer().makeTransaction(storedState.getContractTransaction().toByteArray()),
|
||||||
new TransactionOutput(params, null, storedState.getClientOutput().toByteArray(), 0),
|
new TransactionOutput(params, null, storedState.getClientOutput().toByteArray(), 0),
|
||||||
storedState.getRefundTransactionUnlockTimeSecs(),
|
storedState.getRefundTransactionUnlockTimeSecs(),
|
||||||
ECKey.fromPrivate(storedState.getMyKey().toByteArray()),
|
ECKey.fromPrivate(storedState.getMyKey().toByteArray()),
|
||||||
|
@ -342,7 +342,7 @@ public class PaymentProtocol {
|
|||||||
Protos.Payment paymentMessage) {
|
Protos.Payment paymentMessage) {
|
||||||
final List<Transaction> transactions = new ArrayList<Transaction>(paymentMessage.getTransactionsCount());
|
final List<Transaction> transactions = new ArrayList<Transaction>(paymentMessage.getTransactionsCount());
|
||||||
for (final ByteString transaction : paymentMessage.getTransactionsList())
|
for (final ByteString transaction : paymentMessage.getTransactionsList())
|
||||||
transactions.add(new Transaction(params, transaction.toByteArray()));
|
transactions.add(params.getDefaultSerializer().makeTransaction(transaction.toByteArray()));
|
||||||
return transactions;
|
return transactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1413,7 +1413,7 @@ public class Script {
|
|||||||
// Clone the transaction because executing the script involves editing it, and if we die, we'll leave
|
// Clone the transaction because executing the script involves editing it, and if we die, we'll leave
|
||||||
// the tx half broken (also it's not so thread safe to work on it directly.
|
// the tx half broken (also it's not so thread safe to work on it directly.
|
||||||
try {
|
try {
|
||||||
txContainingThis = new Transaction(txContainingThis.getParams(), txContainingThis.bitcoinSerialize());
|
txContainingThis = txContainingThis.getParams().getDefaultSerializer().makeTransaction(txContainingThis.bitcoinSerialize());
|
||||||
} catch (ProtocolException e) {
|
} catch (ProtocolException e) {
|
||||||
throw new RuntimeException(e); // Should not happen unless we were given a totally broken transaction.
|
throw new RuntimeException(e); // Should not happen unless we were given a totally broken transaction.
|
||||||
}
|
}
|
||||||
|
@ -749,7 +749,7 @@ public abstract class DatabaseFullPrunedBlockStore implements FullPrunedBlockSto
|
|||||||
|
|
||||||
BigInteger chainWork = new BigInteger(results.getBytes(1));
|
BigInteger chainWork = new BigInteger(results.getBytes(1));
|
||||||
int height = results.getInt(2);
|
int height = results.getInt(2);
|
||||||
Block b = new Block(params, results.getBytes(3));
|
Block b = params.getDefaultSerializer().makeBlock(results.getBytes(3));
|
||||||
b.verifyHeader();
|
b.verifyHeader();
|
||||||
StoredBlock stored = new StoredBlock(b, chainWork, height);
|
StoredBlock stored = new StoredBlock(b, chainWork, height);
|
||||||
return stored;
|
return stored;
|
||||||
@ -811,7 +811,7 @@ public abstract class DatabaseFullPrunedBlockStore implements FullPrunedBlockSto
|
|||||||
((transactions[offset++] & 0xFF) << 24);
|
((transactions[offset++] & 0xFF) << 24);
|
||||||
List<Transaction> transactionList = new LinkedList<Transaction>();
|
List<Transaction> transactionList = new LinkedList<Transaction>();
|
||||||
for (int i = 0; i < numTxn; i++) {
|
for (int i = 0; i < numTxn; i++) {
|
||||||
Transaction tx = new Transaction(params, transactions, offset);
|
Transaction tx = params.getDefaultSerializer().makeTransaction(transactions, offset);
|
||||||
transactionList.add(tx);
|
transactionList.add(tx);
|
||||||
offset += tx.getMessageSize();
|
offset += tx.getMessageSize();
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ public class FakeTxBuilder {
|
|||||||
*/
|
*/
|
||||||
public static Transaction roundTripTransaction(NetworkParameters params, Transaction tx) {
|
public static Transaction roundTripTransaction(NetworkParameters params, Transaction tx) {
|
||||||
try {
|
try {
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(params);
|
MessageSerializer bs = params.getDefaultSerializer();
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
bs.serialize(tx, bos);
|
bs.serialize(tx, bos);
|
||||||
return (Transaction) bs.deserialize(ByteBuffer.wrap(bos.toByteArray()));
|
return (Transaction) bs.deserialize(ByteBuffer.wrap(bos.toByteArray()));
|
||||||
@ -153,8 +153,8 @@ public class FakeTxBuilder {
|
|||||||
doubleSpends.t2.addOutput(o2);
|
doubleSpends.t2.addOutput(o2);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
doubleSpends.t1 = new Transaction(params, doubleSpends.t1.bitcoinSerialize());
|
doubleSpends.t1 = params.getDefaultSerializer().makeTransaction(doubleSpends.t1.bitcoinSerialize());
|
||||||
doubleSpends.t2 = new Transaction(params, doubleSpends.t2.bitcoinSerialize());
|
doubleSpends.t2 = params.getDefaultSerializer().makeTransaction(doubleSpends.t2.bitcoinSerialize());
|
||||||
} catch (ProtocolException e) {
|
} catch (ProtocolException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ public class BlockFileLoader implements Iterable<Block>, Iterator<Block> {
|
|||||||
bytes = new byte[(int) size];
|
bytes = new byte[(int) size];
|
||||||
currentFileStream.read(bytes, 0, (int) size);
|
currentFileStream.read(bytes, 0, (int) size);
|
||||||
try {
|
try {
|
||||||
nextBlock = new Block(params, bytes);
|
nextBlock = params.getDefaultSerializer().makeBlock(bytes);
|
||||||
} catch (ProtocolException e) {
|
} catch (ProtocolException e) {
|
||||||
nextBlock = null;
|
nextBlock = null;
|
||||||
continue;
|
continue;
|
||||||
|
@ -55,7 +55,7 @@ public class BitcoinSerializerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddr() throws Exception {
|
public void testAddr() throws Exception {
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
|
MessageSerializer bs = MainNetParams.get().getDefaultSerializer();
|
||||||
// the actual data from https://en.bitcoin.it/wiki/Protocol_specification#addr
|
// the actual data from https://en.bitcoin.it/wiki/Protocol_specification#addr
|
||||||
AddressMessage a = (AddressMessage)bs.deserialize(ByteBuffer.wrap(addrMessage));
|
AddressMessage a = (AddressMessage)bs.deserialize(ByteBuffer.wrap(addrMessage));
|
||||||
assertEquals(1, a.getAddresses().size());
|
assertEquals(1, a.getAddresses().size());
|
||||||
@ -77,7 +77,7 @@ public class BitcoinSerializerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLazyParsing() throws Exception {
|
public void testLazyParsing() throws Exception {
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get(), true, false);
|
MessageSerializer bs = MainNetParams.get().getSerializer(true, false);
|
||||||
|
|
||||||
Transaction tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
|
Transaction tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
|
||||||
assertNotNull(tx);
|
assertNotNull(tx);
|
||||||
@ -98,7 +98,7 @@ public class BitcoinSerializerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void testCachedParsing(boolean lazy) throws Exception {
|
private void testCachedParsing(boolean lazy) throws Exception {
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get(), lazy, true);
|
MessageSerializer bs = MainNetParams.get().getSerializer(lazy, true);
|
||||||
|
|
||||||
//first try writing to a fields to ensure uncaching and children are not affected
|
//first try writing to a fields to ensure uncaching and children are not affected
|
||||||
Transaction tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
|
Transaction tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
|
||||||
@ -161,7 +161,7 @@ public class BitcoinSerializerTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testHeaders1() throws Exception {
|
public void testHeaders1() throws Exception {
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
|
MessageSerializer bs = MainNetParams.get().getDefaultSerializer();
|
||||||
|
|
||||||
String headersMessageBytesHex = "f9beb4d9686561" +
|
String headersMessageBytesHex = "f9beb4d9686561" +
|
||||||
"646572730000000000520000005d4fab8101010000006fe28c0ab6f1b372c1a6a246ae6" +
|
"646572730000000000520000005d4fab8101010000006fe28c0ab6f1b372c1a6a246ae6" +
|
||||||
@ -195,7 +195,7 @@ public class BitcoinSerializerTest {
|
|||||||
* Get 6 headers of blocks 1-6 in the chain
|
* Get 6 headers of blocks 1-6 in the chain
|
||||||
*/
|
*/
|
||||||
public void testHeaders2() throws Exception {
|
public void testHeaders2() throws Exception {
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
|
MessageSerializer bs = MainNetParams.get().getDefaultSerializer();
|
||||||
|
|
||||||
String headersMessageBytesHex = "f9beb4d96865616465" +
|
String headersMessageBytesHex = "f9beb4d96865616465" +
|
||||||
"72730000000000e701000085acd4ea06010000006fe28c0ab6f1b372c1a6a246ae63f74f931e" +
|
"72730000000000e701000085acd4ea06010000006fe28c0ab6f1b372c1a6a246ae63f74f931e" +
|
||||||
@ -266,7 +266,7 @@ public class BitcoinSerializerTest {
|
|||||||
// Fail in another way, there is data in the stream but no magic bytes.
|
// Fail in another way, there is data in the stream but no magic bytes.
|
||||||
byte[] brokenMessage = HEX.decode("000000");
|
byte[] brokenMessage = HEX.decode("000000");
|
||||||
try {
|
try {
|
||||||
new BitcoinSerializer(MainNetParams.get()).seekPastMagicBytes(ByteBuffer.wrap(brokenMessage));
|
MainNetParams.get().getDefaultSerializer().seekPastMagicBytes(ByteBuffer.wrap(brokenMessage));
|
||||||
fail();
|
fail();
|
||||||
} catch (BufferUnderflowException e) {
|
} catch (BufferUnderflowException e) {
|
||||||
// expected
|
// expected
|
||||||
@ -278,7 +278,7 @@ public class BitcoinSerializerTest {
|
|||||||
* Tests serialization of an unknown message.
|
* Tests serialization of an unknown message.
|
||||||
*/
|
*/
|
||||||
public void testSerializeUnknownMessage() {
|
public void testSerializeUnknownMessage() {
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
|
MessageSerializer bs = MainNetParams.get().getDefaultSerializer();
|
||||||
|
|
||||||
UnknownMessage a = new UnknownMessage();
|
UnknownMessage a = new UnknownMessage();
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(addrMessage.length);
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(addrMessage.length);
|
||||||
|
@ -56,7 +56,7 @@ public class BlockTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBlockVerification() throws Exception {
|
public void testBlockVerification() throws Exception {
|
||||||
Block block = new Block(params, blockBytes);
|
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
|
||||||
block.verify();
|
block.verify();
|
||||||
assertEquals("00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935", block.getHashAsString());
|
assertEquals("00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935", block.getHashAsString());
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ public class BlockTest {
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Test
|
@Test
|
||||||
public void testDate() throws Exception {
|
public void testDate() throws Exception {
|
||||||
Block block = new Block(params, blockBytes);
|
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
|
||||||
assertEquals("4 Nov 2010 16:06:04 GMT", block.getTime().toGMTString());
|
assertEquals("4 Nov 2010 16:06:04 GMT", block.getTime().toGMTString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ public class BlockTest {
|
|||||||
public void testProofOfWork() throws Exception {
|
public void testProofOfWork() throws Exception {
|
||||||
// This params accepts any difficulty target.
|
// This params accepts any difficulty target.
|
||||||
NetworkParameters params = UnitTestParams.get();
|
NetworkParameters params = UnitTestParams.get();
|
||||||
Block block = new Block(params, blockBytes);
|
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
|
||||||
block.setNonce(12346);
|
block.setNonce(12346);
|
||||||
try {
|
try {
|
||||||
block.verify();
|
block.verify();
|
||||||
@ -101,7 +101,7 @@ public class BlockTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadTransactions() throws Exception {
|
public void testBadTransactions() throws Exception {
|
||||||
Block block = new Block(params, blockBytes);
|
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
|
||||||
// Re-arrange so the coinbase transaction is not first.
|
// Re-arrange so the coinbase transaction is not first.
|
||||||
Transaction tx1 = block.transactions.get(0);
|
Transaction tx1 = block.transactions.get(0);
|
||||||
Transaction tx2 = block.transactions.get(1);
|
Transaction tx2 = block.transactions.get(1);
|
||||||
@ -117,9 +117,9 @@ public class BlockTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHeaderParse() throws Exception {
|
public void testHeaderParse() throws Exception {
|
||||||
Block block = new Block(params, blockBytes);
|
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
|
||||||
Block header = block.cloneAsHeader();
|
Block header = block.cloneAsHeader();
|
||||||
Block reparsed = new Block(params, header.bitcoinSerialize());
|
Block reparsed = params.getDefaultSerializer().makeBlock(header.bitcoinSerialize());
|
||||||
assertEquals(reparsed, header);
|
assertEquals(reparsed, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ public class BlockTest {
|
|||||||
// proves that transaction serialization works, along with all its subobjects like scripts and in/outpoints.
|
// proves that transaction serialization works, along with all its subobjects like scripts and in/outpoints.
|
||||||
//
|
//
|
||||||
// NB: This tests the bitcoin serialization protocol.
|
// NB: This tests the bitcoin serialization protocol.
|
||||||
Block block = new Block(params, blockBytes);
|
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
|
||||||
assertTrue(Arrays.equals(blockBytes, block.bitcoinSerialize()));
|
assertTrue(Arrays.equals(blockBytes, block.bitcoinSerialize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ public class ChainSplitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Block roundtrip(Block b2) throws ProtocolException {
|
private Block roundtrip(Block b2) throws ProtocolException {
|
||||||
return new Block(unitTestParams, b2.bitcoinSerialize());
|
return unitTestParams.getDefaultSerializer().makeBlock(b2.bitcoinSerialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -59,7 +59,7 @@ public class CoinbaseBlockTest {
|
|||||||
byte[] blockAsBytes = getBytes(getClass().getResourceAsStream("block169482.dat"));
|
byte[] blockAsBytes = getBytes(getClass().getResourceAsStream("block169482.dat"));
|
||||||
|
|
||||||
// Create block 169482.
|
// Create block 169482.
|
||||||
Block block = new Block(params, blockAsBytes);
|
Block block = params.getDefaultSerializer().makeBlock(blockAsBytes);
|
||||||
|
|
||||||
// Check block.
|
// Check block.
|
||||||
assertNotNull(block);
|
assertNotNull(block);
|
||||||
|
@ -139,20 +139,20 @@ public class FilteredBlockAndPartialMerkleTreeTests extends TestWithPeerGroup {
|
|||||||
List<Sha256Hash> txHashList = filteredBlock.getTransactionHashes();
|
List<Sha256Hash> txHashList = filteredBlock.getTransactionHashes();
|
||||||
assertTrue(txHashList.size() == 4);
|
assertTrue(txHashList.size() == 4);
|
||||||
// Four transactions (0, 1, 2, 6) from block 100001
|
// Four transactions (0, 1, 2, 6) from block 100001
|
||||||
Transaction tx0 = new Transaction(params, HEX.decode("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b010dffffffff0100f2052a01000000434104b27f7e9475ccf5d9a431cb86d665b8302c140144ec2397fce792f4a4e7765fecf8128534eaa71df04f93c74676ae8279195128a1506ebf7379d23dab8fca0f63ac00000000"));
|
Transaction tx0 = params.getDefaultSerializer().makeTransaction(HEX.decode("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b010dffffffff0100f2052a01000000434104b27f7e9475ccf5d9a431cb86d665b8302c140144ec2397fce792f4a4e7765fecf8128534eaa71df04f93c74676ae8279195128a1506ebf7379d23dab8fca0f63ac00000000"));
|
||||||
assertTrue(tx0.getHash().equals(Sha256Hash.wrap("bb28a1a5b3a02e7657a81c38355d56c6f05e80b9219432e3352ddcfc3cb6304c")));
|
assertTrue(tx0.getHash().equals(Sha256Hash.wrap("bb28a1a5b3a02e7657a81c38355d56c6f05e80b9219432e3352ddcfc3cb6304c")));
|
||||||
assertEquals(tx0.getHash(), txHashList.get(0));
|
assertEquals(tx0.getHash(), txHashList.get(0));
|
||||||
|
|
||||||
Transaction tx1 = new Transaction(params, HEX.decode("0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000"));
|
Transaction tx1 = params.getDefaultSerializer().makeTransaction(HEX.decode("0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000"));
|
||||||
assertTrue(tx1.getHash().equals(Sha256Hash.wrap("fbde5d03b027d2b9ba4cf5d4fecab9a99864df2637b25ea4cbcb1796ff6550ca")));
|
assertTrue(tx1.getHash().equals(Sha256Hash.wrap("fbde5d03b027d2b9ba4cf5d4fecab9a99864df2637b25ea4cbcb1796ff6550ca")));
|
||||||
assertEquals(tx1.getHash(), txHashList.get(1));
|
assertEquals(tx1.getHash(), txHashList.get(1));
|
||||||
|
|
||||||
Transaction tx2 = new Transaction(params, HEX.decode("01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000"));
|
Transaction tx2 = params.getDefaultSerializer().makeTransaction(HEX.decode("01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000"));
|
||||||
assertTrue(tx2.getHash().equals(Sha256Hash.wrap("8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb")));
|
assertTrue(tx2.getHash().equals(Sha256Hash.wrap("8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb")));
|
||||||
assertEquals(tx2.getHash(), txHashList.get(2));
|
assertEquals(tx2.getHash(), txHashList.get(2));
|
||||||
|
|
||||||
|
|
||||||
Transaction tx3 = new Transaction(params, HEX.decode("01000000011b56cf3aab3286d582c055a42af3a911ee08423f276da702bb67f1222ac1a5b6000000008c4930460221009e9fba682e162c9627b96b7df272006a727988680b956c61baff869f0907b8fb022100a9c19adc7c36144bafe526630783845e5cb9554d30d3edfb56f0740274d507f30141046e0efbfac7b1615ad553a6f097615bc63b7cdb3b8e1cb3263b619ba63740012f51c7c5b09390e3577e377b7537e61226e315f95f926444fc5e5f2978c112e448ffffffff02c0072b11010000001976a914b73e9e01933351ca076faf8e0d94dd58079d0b1f88ac80b63908000000001976a9141aca0bdf0d2cee63db19aa4a484f45a4e26a880c88ac00000000"));
|
Transaction tx3 = params.getDefaultSerializer().makeTransaction(HEX.decode("01000000011b56cf3aab3286d582c055a42af3a911ee08423f276da702bb67f1222ac1a5b6000000008c4930460221009e9fba682e162c9627b96b7df272006a727988680b956c61baff869f0907b8fb022100a9c19adc7c36144bafe526630783845e5cb9554d30d3edfb56f0740274d507f30141046e0efbfac7b1615ad553a6f097615bc63b7cdb3b8e1cb3263b619ba63740012f51c7c5b09390e3577e377b7537e61226e315f95f926444fc5e5f2978c112e448ffffffff02c0072b11010000001976a914b73e9e01933351ca076faf8e0d94dd58079d0b1f88ac80b63908000000001976a9141aca0bdf0d2cee63db19aa4a484f45a4e26a880c88ac00000000"));
|
||||||
assertTrue(tx3.getHash().equals(Sha256Hash.wrap("c5abc61566dbb1c4bce5e1fda7b66bed22eb2130cea4b721690bc1488465abc9")));
|
assertTrue(tx3.getHash().equals(Sha256Hash.wrap("c5abc61566dbb1c4bce5e1fda7b66bed22eb2130cea4b721690bc1488465abc9")));
|
||||||
assertEquals(tx3.getHash(),txHashList.get(3));
|
assertEquals(tx3.getHash(),txHashList.get(3));
|
||||||
|
|
||||||
|
@ -1058,7 +1058,7 @@ public class FullBlockTestGenerator {
|
|||||||
|
|
||||||
Block b56;
|
Block b56;
|
||||||
try {
|
try {
|
||||||
b56 = new Block(params, b57.block.bitcoinSerialize());
|
b56 = params.getDefaultSerializer().makeBlock(b57.block.bitcoinSerialize());
|
||||||
} catch (ProtocolException e) {
|
} catch (ProtocolException e) {
|
||||||
throw new RuntimeException(e); // Cannot happen.
|
throw new RuntimeException(e); // Cannot happen.
|
||||||
}
|
}
|
||||||
@ -1099,7 +1099,7 @@ public class FullBlockTestGenerator {
|
|||||||
|
|
||||||
Block b56p2;
|
Block b56p2;
|
||||||
try {
|
try {
|
||||||
b56p2 = new Block(params, b57p2.block.bitcoinSerialize());
|
b56p2 = params.getDefaultSerializer().makeBlock(b57p2.block.bitcoinSerialize());
|
||||||
} catch (ProtocolException e) {
|
} catch (ProtocolException e) {
|
||||||
throw new RuntimeException(e); // Cannot happen.
|
throw new RuntimeException(e); // Cannot happen.
|
||||||
}
|
}
|
||||||
@ -1218,7 +1218,7 @@ public class FullBlockTestGenerator {
|
|||||||
|
|
||||||
for (Transaction transaction : b64Original.block.getTransactions())
|
for (Transaction transaction : b64Original.block.getTransactions())
|
||||||
transaction.bitcoinSerialize(stream);
|
transaction.bitcoinSerialize(stream);
|
||||||
b64 = new Block(params, stream.toByteArray(), false, true, stream.size());
|
b64 = params.getSerializer(false, true).makeBlock(stream.toByteArray(), stream.size());
|
||||||
|
|
||||||
// The following checks are checking to ensure block serialization functions in the way needed for this test
|
// The following checks are checking to ensure block serialization functions in the way needed for this test
|
||||||
// If they fail, it is likely not an indication of error, but an indication that this test needs rewritten
|
// If they fail, it is likely not an indication of error, but an indication that this test needs rewritten
|
||||||
@ -1346,7 +1346,7 @@ public class FullBlockTestGenerator {
|
|||||||
}
|
}
|
||||||
b72.solve();
|
b72.solve();
|
||||||
|
|
||||||
Block b71 = new Block(params, b72.block.bitcoinSerialize());
|
Block b71 = params.getDefaultSerializer().makeBlock(b72.block.bitcoinSerialize());
|
||||||
b71.addTransaction(b72.block.getTransactions().get(2));
|
b71.addTransaction(b72.block.getTransactions().get(2));
|
||||||
checkState(b71.getHash().equals(b72.getHash()));
|
checkState(b71.getHash().equals(b72.getHash()));
|
||||||
blocks.add(new BlockAndValidity(b71, false, true, b69.getHash(), chainHeadHeight + 21, "b71"));
|
blocks.add(new BlockAndValidity(b71, false, true, b69.getHash(), chainHeadHeight + 21, "b71"));
|
||||||
|
@ -103,7 +103,7 @@ public class LazyParseByteCacheTest {
|
|||||||
|
|
||||||
Block b1 = createFakeBlock(blockStore, tx1, tx2).block;
|
Block b1 = createFakeBlock(blockStore, tx1, tx2).block;
|
||||||
|
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(unitTestParams);
|
MessageSerializer bs = unitTestParams.getDefaultSerializer();
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
bs.serialize(tx1, bos);
|
bs.serialize(tx1, bos);
|
||||||
@ -175,10 +175,10 @@ public class LazyParseByteCacheTest {
|
|||||||
public void testBlock(byte[] blockBytes, boolean isChild, boolean lazy, boolean retain) throws Exception {
|
public void testBlock(byte[] blockBytes, boolean isChild, boolean lazy, boolean retain) throws Exception {
|
||||||
//reference serializer to produce comparison serialization output after changes to
|
//reference serializer to produce comparison serialization output after changes to
|
||||||
//message structure.
|
//message structure.
|
||||||
BitcoinSerializer bsRef = new BitcoinSerializer(unitTestParams, false, false);
|
MessageSerializer bsRef = unitTestParams.getSerializer(false, false);
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(unitTestParams, lazy, retain);
|
BitcoinSerializer bs = unitTestParams.getSerializer(lazy, retain);
|
||||||
Block b1;
|
Block b1;
|
||||||
Block bRef;
|
Block bRef;
|
||||||
b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
|
b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
|
||||||
@ -411,10 +411,10 @@ public class LazyParseByteCacheTest {
|
|||||||
|
|
||||||
//reference serializer to produce comparison serialization output after changes to
|
//reference serializer to produce comparison serialization output after changes to
|
||||||
//message structure.
|
//message structure.
|
||||||
BitcoinSerializer bsRef = new BitcoinSerializer(params, false, false);
|
MessageSerializer bsRef = params.getSerializer(false, false);
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(params, lazy, retain);
|
BitcoinSerializer bs = params.getSerializer(lazy, retain);
|
||||||
Transaction t1;
|
Transaction t1;
|
||||||
Transaction tRef;
|
Transaction tRef;
|
||||||
t1 = (Transaction) bs.deserialize(ByteBuffer.wrap(txBytes));
|
t1 = (Transaction) bs.deserialize(ByteBuffer.wrap(txBytes));
|
||||||
@ -479,7 +479,7 @@ public class LazyParseByteCacheTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void serDeser(BitcoinSerializer bs, Message message, byte[] sourceBytes, byte[] containedBytes, byte[] containingBytes) throws Exception {
|
private void serDeser(MessageSerializer bs, Message message, byte[] sourceBytes, byte[] containedBytes, byte[] containingBytes) throws Exception {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
bs.serialize(message, bos);
|
bs.serialize(message, bos);
|
||||||
byte[] b1 = bos.toByteArray();
|
byte[] b1 = bos.toByteArray();
|
||||||
|
@ -863,7 +863,7 @@ public class PeerTest extends TestWithNetworkConnections {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
final NetworkParameters params = TestNet3Params.get();
|
final NetworkParameters params = TestNet3Params.get();
|
||||||
BitcoinSerializer serializer = new BitcoinSerializer(params);
|
MessageSerializer serializer = params.getDefaultSerializer();
|
||||||
// Now write some bogus truncated message.
|
// Now write some bogus truncated message.
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
serializer.serialize("inv", new InventoryMessage(params) {
|
serializer.serialize("inv", new InventoryMessage(params) {
|
||||||
|
@ -52,7 +52,7 @@ public class TxConfidenceTableTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void pinHandlers() throws Exception {
|
public void pinHandlers() throws Exception {
|
||||||
Transaction tx = new Transaction(params, tx1.bitcoinSerialize());
|
Transaction tx = params.getDefaultSerializer().makeTransaction(tx1.bitcoinSerialize());
|
||||||
Sha256Hash hash = tx.getHash();
|
Sha256Hash hash = tx.getHash();
|
||||||
table.seen(hash, address1);
|
table.seen(hash, address1);
|
||||||
assertEquals(1, tx.getConfidence().numBroadcastPeers());
|
assertEquals(1, tx.getConfidence().numBroadcastPeers());
|
||||||
|
@ -624,7 +624,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
// Send 0.10 to somebody else.
|
// Send 0.10 to somebody else.
|
||||||
Transaction send1 = wallet.createSend(new ECKey().toAddress(params), valueOf(0, 10));
|
Transaction send1 = wallet.createSend(new ECKey().toAddress(params), valueOf(0, 10));
|
||||||
// Reserialize.
|
// Reserialize.
|
||||||
Transaction send2 = new Transaction(params, send1.bitcoinSerialize());
|
Transaction send2 = params.getDefaultSerializer().makeTransaction(send1.bitcoinSerialize());
|
||||||
assertEquals(nanos, send2.getValueSentFromMe(wallet));
|
assertEquals(nanos, send2.getValueSentFromMe(wallet));
|
||||||
assertEquals(ZERO.subtract(valueOf(0, 10)), send2.getValue(wallet));
|
assertEquals(ZERO.subtract(valueOf(0, 10)), send2.getValue(wallet));
|
||||||
}
|
}
|
||||||
@ -641,7 +641,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
|
|
||||||
assertTrue("Wallet is not consistent", wallet.isConsistent());
|
assertTrue("Wallet is not consistent", wallet.isConsistent());
|
||||||
|
|
||||||
Transaction txClone = new Transaction(params, tx.bitcoinSerialize());
|
Transaction txClone = params.getDefaultSerializer().makeTransaction(tx.bitcoinSerialize());
|
||||||
try {
|
try {
|
||||||
wallet.receiveFromBlock(txClone, null, BlockChain.NewBlockType.BEST_CHAIN, 0);
|
wallet.receiveFromBlock(txClone, null, BlockChain.NewBlockType.BEST_CHAIN, 0);
|
||||||
fail("Illegal argument not thrown when it should have been.");
|
fail("Illegal argument not thrown when it should have been.");
|
||||||
@ -737,7 +737,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Transaction send1 = wallet.createSend(new ECKey().toAddress(params), valueOf(2, 90));
|
Transaction send1 = wallet.createSend(new ECKey().toAddress(params), valueOf(2, 90));
|
||||||
// Create a double spend of just the first one.
|
// Create a double spend of just the first one.
|
||||||
Transaction send2 = wallet.createSend(new ECKey().toAddress(params), COIN);
|
Transaction send2 = wallet.createSend(new ECKey().toAddress(params), COIN);
|
||||||
send2 = new Transaction(params, send2.bitcoinSerialize());
|
send2 = params.getDefaultSerializer().makeTransaction(send2.bitcoinSerialize());
|
||||||
// Broadcast send1, it's now pending.
|
// Broadcast send1, it's now pending.
|
||||||
wallet.commitTx(send1);
|
wallet.commitTx(send1);
|
||||||
assertEquals(ZERO, wallet.getBalance());
|
assertEquals(ZERO, wallet.getBalance());
|
||||||
@ -765,7 +765,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Transaction send2 = checkNotNull(wallet.createSend(address, value2));
|
Transaction send2 = checkNotNull(wallet.createSend(address, value2));
|
||||||
byte[] buf = send1.bitcoinSerialize();
|
byte[] buf = send1.bitcoinSerialize();
|
||||||
buf[43] = 0; // Break the signature: bitcoinj won't check in SPV mode and this is easier than other mutations.
|
buf[43] = 0; // Break the signature: bitcoinj won't check in SPV mode and this is easier than other mutations.
|
||||||
send1 = new Transaction(params, buf);
|
send1 = params.getDefaultSerializer().makeTransaction(buf);
|
||||||
wallet.commitTx(send2);
|
wallet.commitTx(send2);
|
||||||
wallet.allowSpendingUnconfirmedTransactions();
|
wallet.allowSpendingUnconfirmedTransactions();
|
||||||
assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
|
assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
|
||||||
@ -830,7 +830,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Transaction send1 = wallet.createSend(new ECKey().toAddress(params), valueOf(0, 50));
|
Transaction send1 = wallet.createSend(new ECKey().toAddress(params), valueOf(0, 50));
|
||||||
// Create a double spend.
|
// Create a double spend.
|
||||||
Transaction send2 = wallet.createSend(new ECKey().toAddress(params), valueOf(0, 50));
|
Transaction send2 = wallet.createSend(new ECKey().toAddress(params), valueOf(0, 50));
|
||||||
send2 = new Transaction(params, send2.bitcoinSerialize());
|
send2 = params.getDefaultSerializer().makeTransaction(send2.bitcoinSerialize());
|
||||||
// Broadcast send1.
|
// Broadcast send1.
|
||||||
wallet.commitTx(send1);
|
wallet.commitTx(send1);
|
||||||
assertEquals(send1, received.getOutput(0).getSpentBy().getParentTransaction());
|
assertEquals(send1, received.getOutput(0).getSpentBy().getParentTransaction());
|
||||||
@ -912,7 +912,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
|
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
|
||||||
Threading.waitForUserCode();
|
Threading.waitForUserCode();
|
||||||
assertNull(reasons[0]);
|
assertNull(reasons[0]);
|
||||||
final Transaction t1Copy = new Transaction(params, t1.bitcoinSerialize());
|
final Transaction t1Copy = params.getDefaultSerializer().makeTransaction(t1.bitcoinSerialize());
|
||||||
sendMoneyToWallet(t1Copy, AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
sendMoneyToWallet(t1Copy, AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||||
Threading.waitForUserCode();
|
Threading.waitForUserCode();
|
||||||
assertFalse(flags[0]);
|
assertFalse(flags[0]);
|
||||||
|
@ -125,7 +125,7 @@ public class ScriptTest {
|
|||||||
ECKey key3 = DumpedPrivateKey.fromBase58(params, "cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg").getKey();
|
ECKey key3 = DumpedPrivateKey.fromBase58(params, "cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg").getKey();
|
||||||
Script multisigScript = ScriptBuilder.createMultiSigOutputScript(2, Arrays.asList(key1, key2, key3));
|
Script multisigScript = ScriptBuilder.createMultiSigOutputScript(2, Arrays.asList(key1, key2, key3));
|
||||||
byte[] bytes = HEX.decode("01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000");
|
byte[] bytes = HEX.decode("01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000");
|
||||||
Transaction transaction = new Transaction(params, bytes);
|
Transaction transaction = params.getDefaultSerializer().makeTransaction(bytes);
|
||||||
TransactionOutput output = transaction.getOutput(1);
|
TransactionOutput output = transaction.getOutput(1);
|
||||||
Transaction spendTx = new Transaction(params);
|
Transaction spendTx = new Transaction(params);
|
||||||
Address address = Address.fromBase58(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H");
|
Address address = Address.fromBase58(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H");
|
||||||
@ -324,7 +324,7 @@ public class ScriptTest {
|
|||||||
Transaction transaction = null;
|
Transaction transaction = null;
|
||||||
try {
|
try {
|
||||||
Map<TransactionOutPoint, Script> scriptPubKeys = parseScriptPubKeys(test.get(0));
|
Map<TransactionOutPoint, Script> scriptPubKeys = parseScriptPubKeys(test.get(0));
|
||||||
transaction = new Transaction(params, HEX.decode(test.get(1).asText().toLowerCase()));
|
transaction = params.getDefaultSerializer().makeTransaction(HEX.decode(test.get(1).asText().toLowerCase()));
|
||||||
transaction.verify();
|
transaction.verify();
|
||||||
Set<VerifyFlag> verifyFlags = parseVerifyFlags(test.get(2).asText());
|
Set<VerifyFlag> verifyFlags = parseVerifyFlags(test.get(2).asText());
|
||||||
|
|
||||||
@ -353,7 +353,7 @@ public class ScriptTest {
|
|||||||
if (test.isArray() && test.size() == 1 && test.get(0).isTextual())
|
if (test.isArray() && test.size() == 1 && test.get(0).isTextual())
|
||||||
continue; // This is a comment.
|
continue; // This is a comment.
|
||||||
Map<TransactionOutPoint, Script> scriptPubKeys = parseScriptPubKeys(test.get(0));
|
Map<TransactionOutPoint, Script> scriptPubKeys = parseScriptPubKeys(test.get(0));
|
||||||
Transaction transaction = new Transaction(params, HEX.decode(test.get(1).asText().toLowerCase()));
|
Transaction transaction = params.getDefaultSerializer().makeTransaction(HEX.decode(test.get(1).asText().toLowerCase()));
|
||||||
Set<VerifyFlag> verifyFlags = parseVerifyFlags(test.get(2).asText());
|
Set<VerifyFlag> verifyFlags = parseVerifyFlags(test.get(2).asText());
|
||||||
|
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
|
@ -188,7 +188,7 @@ public class WalletProtobufSerializerTest {
|
|||||||
assertTrue(lastSeenBlockHash.isEmpty());
|
assertTrue(lastSeenBlockHash.isEmpty());
|
||||||
|
|
||||||
// Create a block.
|
// Create a block.
|
||||||
Block block = new Block(params, BlockTest.blockBytes);
|
Block block = params.getDefaultSerializer().makeBlock(BlockTest.blockBytes);
|
||||||
Sha256Hash blockHash = block.getHash();
|
Sha256Hash blockHash = block.getHash();
|
||||||
wallet.setLastBlockSeenHash(blockHash);
|
wallet.setLastBlockSeenHash(blockHash);
|
||||||
wallet.setLastBlockSeenHeight(1);
|
wallet.setLastBlockSeenHeight(1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user