3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-13 10:45:51 +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:
Ross Nicoll 2015-05-30 12:01:01 +01:00 committed by Andreas Schildbach
parent 16a5e1d64b
commit 12602650ce
43 changed files with 630 additions and 194 deletions

View File

@ -759,7 +759,7 @@ public abstract class AbstractBlockChain {
try {
falsePositives.remove(tx.getHash());
if (clone)
tx = new Transaction(tx.params, tx.bitcoinSerialize());
tx = tx.params.getDefaultSerializer().makeTransaction(tx.bitcoinSerialize());
listener.receiveFromBlock(tx, block, blockType, relativityOffset++);
} catch (ScriptException e) {
// We don't want scripts we don't understand to break the block chain so just note that this tx was

View File

@ -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
* @throws ProtocolException
*/
AddressMessage(NetworkParameters params, byte[] payload, int offset, boolean parseLazy, boolean parseRetain, int length) throws ProtocolException {
super(params, payload, offset, parseLazy, parseRetain, length);
AddressMessage(NetworkParameters params, byte[] payload, int offset, MessageSerializer setSerializer, int length) throws ProtocolException {
super(params, payload, offset, setSerializer, length);
}
/**
* Contruct a new 'addr' message.
* @param params NetworkParameters object.
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
* @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 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
*/
AddressMessage(NetworkParameters params, byte[] payload, boolean parseLazy, boolean parseRetain, int length) throws ProtocolException {
super(params, payload, 0, parseLazy, parseRetain, length);
AddressMessage(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length) throws ProtocolException {
super(params, payload, 0, serializer, length);
}
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 {
super(params, payload, 0, false, false, UNKNOWN_LENGTH);
super(params, payload, 0, params.getDefaultSerializer(), UNKNOWN_LENGTH);
}
@Override
@ -67,7 +64,7 @@ public class AddressMessage extends Message {
throw new ProtocolException("Address message too large.");
addresses = new ArrayList<PeerAddress>((int) numAddresses);
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);
cursor += addr.getMessageSize();
}

View File

@ -41,15 +41,15 @@ import static org.bitcoinj.core.Utils.*;
* <li>Message.bitcoinSerializeToStream() needs to be properly subclassed</li>
* </ul>
*/
public class BitcoinSerializer {
public class BitcoinSerializer implements MessageSerializer {
private static final Logger log = LoggerFactory.getLogger(BitcoinSerializer.class);
private static final int COMMAND_LEN = 12;
private NetworkParameters params;
private boolean parseLazy = false;
private boolean parseRetain = false;
private final NetworkParameters params;
private final boolean parseLazy;
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 {
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
* belong to.
*
* @param params networkParams used to create Messages instances and termining packetMagic
* @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) {
this(params, false, false);
@Deprecated
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.
*/
@Override
public void serialize(String name, byte[] message, OutputStream out) throws IOException {
byte[] header = new byte[4 + COMMAND_LEN + 4 + 4 /* checksum */];
uint32ToByteArrayBE(params.getPacketMagic(), header, 0);
@ -123,6 +131,7 @@ public class BitcoinSerializer {
/**
* Writes message to to the output stream.
*/
@Override
public void serialize(Message message, OutputStream out) throws IOException {
String name = names.get(message.getClass());
if (name == null) {
@ -134,6 +143,7 @@ public class BitcoinSerializer {
/**
* Reads a message from the given ByteBuffer and returns it.
*/
@Override
public Message deserialize(ByteBuffer in) throws ProtocolException, IOException {
// 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
* the payload. This method assumes you have already called seekPastMagicBytes()
*/
@Override
public BitcoinPacketHeader deserializeHeader(ByteBuffer in) throws ProtocolException, IOException {
return new BitcoinPacketHeader(in);
}
@ -167,6 +178,7 @@ public class BitcoinSerializer {
* Deserialize payload only. You must provide a header, typically obtained by calling
* {@link BitcoinSerializer#deserializeHeader}.
*/
@Override
public Message deserializePayload(BitcoinPacketHeader header, ByteBuffer in) throws ProtocolException, BufferUnderflowException {
byte[] payloadBytes = new byte[header.size];
in.get(payloadBytes, 0, header.size);
@ -199,24 +211,21 @@ public class BitcoinSerializer {
if (command.equals("version")) {
return new VersionMessage(params, payloadBytes);
} else if (command.equals("inv")) {
message = new InventoryMessage(params, payloadBytes, parseLazy, parseRetain, length);
message = makeInventoryMessage(payloadBytes, length);
} else if (command.equals("block")) {
message = new Block(params, payloadBytes, parseLazy, parseRetain, length);
message = makeBlock(payloadBytes, length);
} else if (command.equals("merkleblock")) {
message = new FilteredBlock(params, payloadBytes);
message = makeFilteredBlock(payloadBytes);
} 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")) {
message = new GetBlocksMessage(params, payloadBytes);
} else if (command.equals("getheaders")) {
message = new GetHeadersMessage(params, payloadBytes);
} else if (command.equals("tx")) {
Transaction tx = new Transaction(params, payloadBytes, null, parseLazy, parseRetain, length);
if (hash != null)
tx.setHash(Sha256Hash.wrapReversed(hash));
message = tx;
message = makeTransaction(payloadBytes, 0, length, hash);
} else if (command.equals("addr")) {
message = new AddressMessage(params, payloadBytes, parseLazy, parseRetain, length);
message = makeAddressMessage(payloadBytes, length);
} else if (command.equals("ping")) {
message = new Ping(params, payloadBytes);
} else if (command.equals("pong")) {
@ -226,9 +235,9 @@ public class BitcoinSerializer {
} else if (command.equals("headers")) {
return new HeadersMessage(params, payloadBytes);
} else if (command.equals("alert")) {
return new AlertMessage(params, payloadBytes);
return makeAlertMessage(payloadBytes);
} else if (command.equals("filterload")) {
return new BloomFilter(params, payloadBytes);
return makeBloomFilter(payloadBytes);
} else if (command.equals("notfound")) {
return new NotFoundMessage(params, payloadBytes);
} else if (command.equals("mempool")) {
@ -246,6 +255,100 @@ public class BitcoinSerializer {
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 {
int magicCursor = 3; // Which byte of the magic we're looking for currently.
while (true) {
@ -270,6 +373,7 @@ public class BitcoinSerializer {
/**
* Whether the serializer will produce lazy parse mode Messages
*/
@Override
public boolean isParseLazyMode() {
return parseLazy;
}
@ -277,6 +381,7 @@ public class BitcoinSerializer {
/**
* Whether the serializer will produce cached mode Messages
*/
@Override
public boolean isParseRetainMode() {
return parseRetain;
}

View File

@ -87,16 +87,16 @@ public class Block extends Message {
/** Stores the hash of the block. If null, getHash() will recalculate it. */
private Sha256Hash hash;
private boolean headerParsed;
private boolean transactionsParsed;
protected boolean headerParsed;
protected boolean transactionsParsed;
private boolean headerBytesValid;
private boolean transactionBytesValid;
protected boolean headerBytesValid;
protected boolean transactionBytesValid;
// 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
// 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. */
Block(NetworkParameters params) {
@ -110,27 +110,46 @@ public class Block extends Message {
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 {
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.
* @param params NetworkParameters object.
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
* @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 serializer the serializer to use for this message.
* @param length The length of message if known. Usually this is provided when deserializing of the wire
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
* @throws ProtocolException
*/
public Block(NetworkParameters params, byte[] payloadBytes, boolean parseLazy, boolean parseRetain, int length)
public Block(NetworkParameters params, byte[] payloadBytes, MessageSerializer serializer, int length)
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.
@ -185,14 +204,25 @@ public class Block extends Message {
hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(payload, offset, cursor));
headerParsed = true;
headerBytesValid = parseRetain;
headerBytesValid = serializer.isParseRetainMode();
}
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)
return;
cursor = offset + HEADER_SIZE;
cursor = transactionsOffset;
optimalEncodingMessageSize = HEADER_SIZE;
if (payload.length == cursor) {
// This message is just a header, it has no transactions.
@ -205,7 +235,7 @@ public class Block extends Message {
optimalEncodingMessageSize += VarInt.sizeOf(numTransactions);
transactions = new ArrayList<Transaction>(numTransactions);
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.
tx.getConfidence().setSource(TransactionConfidence.Source.NETWORK);
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().
// If this is a genuine lazy parse then length must have been provided to the constructor.
transactionsParsed = true;
transactionBytesValid = parseRetain;
transactionBytesValid = serializer.isParseRetainMode();
}
@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
// invoke a light parse of transactions to calculate the 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 " +
"without providing length. This should never need to happen.");
parseTransactions();
length = cursor - offset;
} 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;
try {
parseTransactions();
if (!parseRetain) {
if (!serializer.isParseRetainMode()) {
transactionBytesValid = false;
if (headerParsed)
payload = null;

View File

@ -25,6 +25,10 @@ public abstract class ChildMessage extends Message {
@Nullable protected Message parent;
/**
* @deprecated Use {@link #ChildMessage(NetworkParameters) instead.
*/
@Deprecated
protected ChildMessage() {
}
@ -36,9 +40,8 @@ public abstract class ChildMessage extends Message {
super(params, payload, offset, protocolVersion);
}
public ChildMessage(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, boolean parseLazy,
boolean parseRetain, int length) throws ProtocolException {
super(params, payload, offset, protocolVersion, parseLazy, parseRetain, length);
public ChildMessage(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, MessageSerializer setSerializer, int length) throws ProtocolException {
super(params, payload, offset, protocolVersion, setSerializer, length);
this.parent = parent;
}
@ -46,9 +49,9 @@ public abstract class ChildMessage extends Message {
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 {
super(params, payload, offset, parseLazy, parseRetain, length);
super(params, payload, offset, setSerializer, length);
this.parent = parent;
}

View 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);
}
}

View File

@ -60,7 +60,7 @@ public class FilteredBlock extends Message {
void parse() throws ProtocolException {
byte[] headerBytes = new byte[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);

View File

@ -30,17 +30,14 @@ public class GetDataMessage extends ListMessage {
* Deserializes a 'getdata' message.
* @param params NetworkParameters object.
* @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 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 serializer the serializer to use for this message.
* @param length The length of message if known. Usually this is provided when deserializing of the wire
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
* @throws ProtocolException
*/
public GetDataMessage(NetworkParameters params, byte[] payload, boolean parseLazy, boolean parseRetain, int length)
public GetDataMessage(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length)
throws ProtocolException {
super(params, payload, parseLazy, parseRetain, length);
super(params, payload, serializer, length);
}
public GetDataMessage(NetworkParameters params) {

View File

@ -88,7 +88,8 @@ public class HeadersMessage extends Message {
byte[] blockHeader = readBytes(81);
if (blockHeader[80] != 0)
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);
}

View File

@ -37,17 +37,14 @@ public class InventoryMessage extends ListMessage {
* Deserializes an 'inv' message.
* @param params NetworkParameters object.
* @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 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 serializer the serializer to use for this message.
* @param length The length of message if known. Usually this is provided when deserializing of the wire
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
* @throws ProtocolException
*/
public InventoryMessage(NetworkParameters params, byte[] payload, boolean parseLazy, boolean parseRetain, int length)
public InventoryMessage(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length)
throws ProtocolException {
super(params, payload, parseLazy, parseRetain, length);
super(params, payload, serializer, length);
}
public InventoryMessage(NetworkParameters params) {

View File

@ -37,9 +37,9 @@ public abstract class ListMessage extends Message {
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 {
super(params, payload, 0, parseLazy, parseRetain, length);
super(params, payload, 0, serializer, length);
}
public ListMessage(NetworkParameters params) {

View File

@ -54,8 +54,7 @@ public abstract class Message {
protected boolean parsed = false;
protected boolean recached = false;
protected final boolean parseLazy;
protected final boolean parseRetain;
protected MessageSerializer serializer;
protected int protocolVersion;
@ -63,19 +62,17 @@ public abstract class Message {
protected Message() {
parsed = true;
parseLazy = false;
parseRetain = false;
serializer = DummySerializer.DEFAULT;
}
Message(NetworkParameters params) {
this.params = params;
parsed = true;
parseLazy = false;
parseRetain = false;
serializer = params.getDefaultSerializer();
}
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 offset The location of the first payload byte within the array.
* @param protocolVersion Bitcoin protocol version.
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
* @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 serializer the serializer to use for this message.
* @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
* @throws ProtocolException
*/
Message(NetworkParameters params, byte[] payload, int offset, int protocolVersion, boolean parseLazy, boolean parseRetain, int length) throws ProtocolException {
this.parseLazy = parseLazy;
this.parseRetain = parseRetain;
Message(NetworkParameters params, byte[] payload, int offset, int protocolVersion, MessageSerializer serializer, int length) throws ProtocolException {
this.serializer = serializer;
this.protocolVersion = protocolVersion;
this.params = params;
this.payload = payload;
this.cursor = this.offset = offset;
this.length = length;
if (parseLazy) {
if (serializer.isParseLazyMode()) {
parseLite();
} else {
parseLite();
@ -111,13 +104,13 @@ public abstract class Message {
if (this.length == UNKNOWN_LENGTH)
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.",
getClass().getSimpleName(), parseLazy ? "lite" : "full");
getClass().getSimpleName(), serializer.isParseLazyMode() ? "lite" : "full");
if (SELF_CHECK) {
selfCheck(payload, offset);
}
if (parseRetain || !parsed)
if (serializer.isParseRetainMode() || !parsed)
return;
this.payload = null;
}
@ -136,11 +129,11 @@ public abstract class Message {
}
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 {
this(params, payload, offset, NetworkParameters.PROTOCOL_VERSION, parseLazy, parseRetain, length);
Message(NetworkParameters params, byte[] payload, int offset, MessageSerializer serializer, int length) throws ProtocolException {
this(params, payload, offset, NetworkParameters.PROTOCOL_VERSION, serializer, length);
}
// These methods handle the serialization/deserialization using the custom Bitcoin protocol.
@ -172,7 +165,7 @@ public abstract class Message {
try {
parse();
parsed = true;
if (!parseRetain)
if (!serializer.isParseRetainMode())
payload = null;
} 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);
@ -297,7 +290,7 @@ public abstract class Message {
// Cannot happen, we are serializing to a memory stream.
}
if (parseRetain) {
if (serializer.isParseRetainMode()) {
// A free set of steak knives!
// 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.
@ -445,6 +438,17 @@ public abstract class Message {
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 LazyParseException(String message, Throwable cause) {

View 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;
}

View File

@ -104,6 +104,7 @@ public abstract class NetworkParameters {
protected int[] addrSeeds;
protected HttpDiscovery.Details[] httpSeeds = {};
protected Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>();
protected transient MessageSerializer defaultSerializer = null;
protected NetworkParameters() {
alertSigningKey = SATOSHI_KEY;
@ -417,4 +418,31 @@ public abstract class NetworkParameters {
* networks.
*/
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);
}

View File

@ -58,15 +58,11 @@ public class PeerAddress extends ChildMessage {
* @param payload Bitcoin protocol formatted byte array containing message content.
* @param offset The location of the first payload byte within the array.
* @param protocolVersion Bitcoin protocol version.
* @param parseLazy Whether to perform a full parse immediately or delay until a read is requested.
* @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 serializer the serializer to use for this message.
* @throws ProtocolException
*/
public PeerAddress(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, boolean parseLazy,
boolean parseRetain) throws ProtocolException {
super(params, payload, offset, protocolVersion, parent, parseLazy, parseRetain, UNKNOWN_LENGTH);
public PeerAddress(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, MessageSerializer serializer) throws ProtocolException {
super(params, payload, offset, protocolVersion, parent, serializer, UNKNOWN_LENGTH);
// 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
// as it will be set regardless of which constructor was used.

View File

@ -42,7 +42,7 @@ import static com.google.common.base.Preconditions.*;
public abstract class PeerSocketHandler extends AbstractTimeoutHandler implements StreamParser {
private static final Logger log = LoggerFactory.getLogger(PeerSocketHandler.class);
private final BitcoinSerializer serializer;
private final MessageSerializer serializer;
protected PeerAddress peerAddress;
// If we close() before we know our writeTarget, set this to true to call writeTarget.closeConnection() right away.
private boolean closePending = false;
@ -59,12 +59,14 @@ public abstract class PeerSocketHandler extends AbstractTimeoutHandler implement
private Lock lock = Threading.lock("PeerSocketHandler");
public PeerSocketHandler(NetworkParameters params, InetSocketAddress remoteIp) {
serializer = new BitcoinSerializer(checkNotNull(params));
checkNotNull(params);
serializer = params.getDefaultSerializer();
this.peerAddress = new PeerAddress(remoteIp);
}
public PeerSocketHandler(NetworkParameters params, PeerAddress peerAddress) {
serializer = new BitcoinSerializer(checkNotNull(params));
checkNotNull(params);
serializer = params.getDefaultSerializer();
this.peerAddress = checkNotNull(peerAddress);
}

View File

@ -138,7 +138,7 @@ public class StoredBlock {
int height = buffer.getInt(); // +4 bytes
byte[] header = new byte[Block.HEADER_SIZE + 1]; // Extra byte for the 00 transactions length.
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

View File

@ -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
* @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 {
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.
*/
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 {
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 {
//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.
//In parseRetain mode the block needs to know how long the transaction is
//unfortunately this requires a fairly deep (though not total) parse.
@ -554,7 +554,7 @@ public class Transaction extends ChildMessage {
optimalEncodingMessageSize += VarInt.sizeOf(numInputs);
inputs = new ArrayList<TransactionInput>((int) numInputs);
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);
long scriptLen = readVarInt(TransactionOutPoint.MESSAGE_LENGTH);
optimalEncodingMessageSize += TransactionOutPoint.MESSAGE_LENGTH + VarInt.sizeOf(scriptLen) + scriptLen + 4;
@ -565,7 +565,7 @@ public class Transaction extends ChildMessage {
optimalEncodingMessageSize += VarInt.sizeOf(numOutputs);
outputs = new ArrayList<TransactionOutput>((int) numOutputs);
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);
long scriptLen = readVarInt(8);
optimalEncodingMessageSize += 8 + VarInt.sizeOf(scriptLen) + scriptLen;

View File

@ -116,17 +116,12 @@ public class TransactionInput extends ChildMessage {
* @param params NetworkParameters object.
* @param payload Bitcoin protocol formatted byte array containing message content.
* @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 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
* @param serializer the serializer to use for this message.
* @throws ProtocolException
*/
public TransactionInput(NetworkParameters params, Transaction parentTransaction, byte[] payload, int offset,
boolean parseLazy, boolean parseRetain)
public TransactionInput(NetworkParameters params, Transaction parentTransaction, byte[] payload, int offset, MessageSerializer serializer)
throws ProtocolException {
super(params, payload, offset, parentTransaction, parseLazy, parseRetain, UNKNOWN_LENGTH);
super(params, payload, offset, parentTransaction, serializer, UNKNOWN_LENGTH);
this.value = null;
}
@ -140,7 +135,7 @@ public class TransactionInput extends ChildMessage {
@Override
void parse() throws ProtocolException {
outpoint = new TransactionOutPoint(params, payload, cursor, this, parseLazy, parseRetain);
outpoint = new TransactionOutPoint(params, payload, cursor, this, serializer);
cursor += outpoint.getMessageSize();
int scriptLen = (int) readVarInt();
scriptBytes = readBytes(scriptLen);

View File

@ -80,14 +80,11 @@ public class TransactionOutPoint extends ChildMessage {
* Deserializes the message. This is usually part of a transaction message.
* @param params NetworkParameters object.
* @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 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 serializer the serializer to use for this message.
* @throws ProtocolException
*/
public TransactionOutPoint(NetworkParameters params, byte[] payload, int offset, Message parent, boolean parseLazy, boolean parseRetain) throws ProtocolException {
super(params, payload, offset, parent, parseLazy, parseRetain, MESSAGE_LENGTH);
public TransactionOutPoint(NetworkParameters params, byte[] payload, int offset, Message parent, MessageSerializer serializer) throws ProtocolException {
super(params, payload, offset, parent, serializer, MESSAGE_LENGTH);
}
@Override

View File

@ -69,15 +69,11 @@ public class TransactionOutput extends ChildMessage {
* @param params NetworkParameters object.
* @param payload Bitcoin protocol formatted byte array containing message content.
* @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 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 serializer the serializer to use for this message.
* @throws ProtocolException
*/
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, byte[] payload, int offset,
boolean parseLazy, boolean parseRetain) throws ProtocolException {
super(params, payload, offset, parent, parseLazy, parseRetain, UNKNOWN_LENGTH);
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, byte[] payload, int offset, MessageSerializer serializer) throws ProtocolException {
super(params, payload, offset, parent, serializer, UNKNOWN_LENGTH);
availableForSpending = true;
}

View File

@ -31,6 +31,9 @@ import org.bitcoinj.store.BlockStoreException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkState;
import org.bitcoinj.core.BitcoinSerializer;
/**
* Parameters for Bitcoin-like networks.
*/
@ -133,6 +136,11 @@ public abstract class AbstractBitcoinNetParams extends NetworkParameters {
return new MonetaryFormat();
}
@Override
public BitcoinSerializer getSerializer(boolean parseLazy, boolean parseRetain) {
return new BitcoinSerializer(this, parseLazy, parseRetain);
}
@Override
public String getUriScheme() {
return BITCOIN_SCHEME;

View File

@ -373,7 +373,7 @@ public class PaymentChannelClient implements IPaymentChannelClient {
private void receiveClose(Protos.TwoWayChannelMessage msg) throws VerificationException {
checkState(lock.isHeldByCurrentThread());
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());
// TODO: set source
if (state != null && state().isSettlementTransaction(settleTx)) {

View File

@ -295,7 +295,7 @@ public class PaymentChannelServer {
Protos.ProvideRefund providedRefund = msg.getProvideRefund();
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());
step = InitStep.WAITING_ON_CONTRACT;
@ -349,7 +349,7 @@ public class PaymentChannelServer {
final Protos.ProvideContract providedContract = msg.getProvideContract();
//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;
state.provideMultiSigContract(multisigContract)
.addListener(new Runnable() {

View File

@ -302,13 +302,13 @@ public class StoredPaymentChannelClientStates implements WalletExtension {
NetworkParameters params = containingWallet.getParams();
ClientState.StoredClientPaymentChannels states = ClientState.StoredClientPaymentChannels.parseFrom(data);
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);
ECKey myKey = (storedState.getMyKey().isEmpty()) ?
containingWallet.findKeyFromPubKey(storedState.getMyPublicKey().toByteArray()) :
ECKey.fromPrivate(storedState.getMyKey().toByteArray());
StoredClientChannel channel = new StoredClientChannel(Sha256Hash.wrap(storedState.getId().toByteArray()),
new Transaction(params, storedState.getContractTransaction().toByteArray()),
params.getDefaultSerializer().makeTransaction(storedState.getContractTransaction().toByteArray()),
refundTransaction,
myKey,
Coin.valueOf(storedState.getValueToMe()),

View File

@ -232,7 +232,7 @@ public class StoredPaymentChannelServerStates implements WalletExtension {
NetworkParameters params = containingWallet.getParams();
for (ServerState.StoredServerPaymentChannel storedState : states.getChannelsList()) {
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),
storedState.getRefundTransactionUnlockTimeSecs(),
ECKey.fromPrivate(storedState.getMyKey().toByteArray()),

View File

@ -342,7 +342,7 @@ public class PaymentProtocol {
Protos.Payment paymentMessage) {
final List<Transaction> transactions = new ArrayList<Transaction>(paymentMessage.getTransactionsCount());
for (final ByteString transaction : paymentMessage.getTransactionsList())
transactions.add(new Transaction(params, transaction.toByteArray()));
transactions.add(params.getDefaultSerializer().makeTransaction(transaction.toByteArray()));
return transactions;
}

View File

@ -1413,7 +1413,7 @@ public class Script {
// 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.
try {
txContainingThis = new Transaction(txContainingThis.getParams(), txContainingThis.bitcoinSerialize());
txContainingThis = txContainingThis.getParams().getDefaultSerializer().makeTransaction(txContainingThis.bitcoinSerialize());
} catch (ProtocolException e) {
throw new RuntimeException(e); // Should not happen unless we were given a totally broken transaction.
}

View File

@ -749,7 +749,7 @@ public abstract class DatabaseFullPrunedBlockStore implements FullPrunedBlockSto
BigInteger chainWork = new BigInteger(results.getBytes(1));
int height = results.getInt(2);
Block b = new Block(params, results.getBytes(3));
Block b = params.getDefaultSerializer().makeBlock(results.getBytes(3));
b.verifyHeader();
StoredBlock stored = new StoredBlock(b, chainWork, height);
return stored;
@ -811,7 +811,7 @@ public abstract class DatabaseFullPrunedBlockStore implements FullPrunedBlockSto
((transactions[offset++] & 0xFF) << 24);
List<Transaction> transactionList = new LinkedList<Transaction>();
for (int i = 0; i < numTxn; i++) {
Transaction tx = new Transaction(params, transactions, offset);
Transaction tx = params.getDefaultSerializer().makeTransaction(transactions, offset);
transactionList.add(tx);
offset += tx.getMessageSize();
}

View File

@ -116,7 +116,7 @@ public class FakeTxBuilder {
*/
public static Transaction roundTripTransaction(NetworkParameters params, Transaction tx) {
try {
BitcoinSerializer bs = new BitcoinSerializer(params);
MessageSerializer bs = params.getDefaultSerializer();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bs.serialize(tx, bos);
return (Transaction) bs.deserialize(ByteBuffer.wrap(bos.toByteArray()));
@ -153,8 +153,8 @@ public class FakeTxBuilder {
doubleSpends.t2.addOutput(o2);
try {
doubleSpends.t1 = new Transaction(params, doubleSpends.t1.bitcoinSerialize());
doubleSpends.t2 = new Transaction(params, doubleSpends.t2.bitcoinSerialize());
doubleSpends.t1 = params.getDefaultSerializer().makeTransaction(doubleSpends.t1.bitcoinSerialize());
doubleSpends.t2 = params.getDefaultSerializer().makeTransaction(doubleSpends.t2.bitcoinSerialize());
} catch (ProtocolException e) {
throw new RuntimeException(e);
}

View File

@ -150,7 +150,7 @@ public class BlockFileLoader implements Iterable<Block>, Iterator<Block> {
bytes = new byte[(int) size];
currentFileStream.read(bytes, 0, (int) size);
try {
nextBlock = new Block(params, bytes);
nextBlock = params.getDefaultSerializer().makeBlock(bytes);
} catch (ProtocolException e) {
nextBlock = null;
continue;

View File

@ -55,7 +55,7 @@ public class BitcoinSerializerTest {
@Test
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
AddressMessage a = (AddressMessage)bs.deserialize(ByteBuffer.wrap(addrMessage));
assertEquals(1, a.getAddresses().size());
@ -77,7 +77,7 @@ public class BitcoinSerializerTest {
@Test
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));
assertNotNull(tx);
@ -98,7 +98,7 @@ public class BitcoinSerializerTest {
}
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
Transaction tx = (Transaction)bs.deserialize(ByteBuffer.wrap(txMessage));
@ -161,7 +161,7 @@ public class BitcoinSerializerTest {
*/
@Test
public void testHeaders1() throws Exception {
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
MessageSerializer bs = MainNetParams.get().getDefaultSerializer();
String headersMessageBytesHex = "f9beb4d9686561" +
"646572730000000000520000005d4fab8101010000006fe28c0ab6f1b372c1a6a246ae6" +
@ -195,7 +195,7 @@ public class BitcoinSerializerTest {
* Get 6 headers of blocks 1-6 in the chain
*/
public void testHeaders2() throws Exception {
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
MessageSerializer bs = MainNetParams.get().getDefaultSerializer();
String headersMessageBytesHex = "f9beb4d96865616465" +
"72730000000000e701000085acd4ea06010000006fe28c0ab6f1b372c1a6a246ae63f74f931e" +
@ -266,7 +266,7 @@ public class BitcoinSerializerTest {
// Fail in another way, there is data in the stream but no magic bytes.
byte[] brokenMessage = HEX.decode("000000");
try {
new BitcoinSerializer(MainNetParams.get()).seekPastMagicBytes(ByteBuffer.wrap(brokenMessage));
MainNetParams.get().getDefaultSerializer().seekPastMagicBytes(ByteBuffer.wrap(brokenMessage));
fail();
} catch (BufferUnderflowException e) {
// expected
@ -278,7 +278,7 @@ public class BitcoinSerializerTest {
* Tests serialization of an unknown message.
*/
public void testSerializeUnknownMessage() {
BitcoinSerializer bs = new BitcoinSerializer(MainNetParams.get());
MessageSerializer bs = MainNetParams.get().getDefaultSerializer();
UnknownMessage a = new UnknownMessage();
ByteArrayOutputStream bos = new ByteArrayOutputStream(addrMessage.length);

View File

@ -56,7 +56,7 @@ public class BlockTest {
@Test
public void testBlockVerification() throws Exception {
Block block = new Block(params, blockBytes);
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
block.verify();
assertEquals("00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935", block.getHashAsString());
}
@ -64,7 +64,7 @@ public class BlockTest {
@SuppressWarnings("deprecation")
@Test
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());
}
@ -72,7 +72,7 @@ public class BlockTest {
public void testProofOfWork() throws Exception {
// This params accepts any difficulty target.
NetworkParameters params = UnitTestParams.get();
Block block = new Block(params, blockBytes);
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
block.setNonce(12346);
try {
block.verify();
@ -101,7 +101,7 @@ public class BlockTest {
@Test
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.
Transaction tx1 = block.transactions.get(0);
Transaction tx2 = block.transactions.get(1);
@ -117,9 +117,9 @@ public class BlockTest {
@Test
public void testHeaderParse() throws Exception {
Block block = new Block(params, blockBytes);
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
Block header = block.cloneAsHeader();
Block reparsed = new Block(params, header.bitcoinSerialize());
Block reparsed = params.getDefaultSerializer().makeBlock(header.bitcoinSerialize());
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.
//
// 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()));
}

View File

@ -267,7 +267,7 @@ public class ChainSplitTest {
}
private Block roundtrip(Block b2) throws ProtocolException {
return new Block(unitTestParams, b2.bitcoinSerialize());
return unitTestParams.getDefaultSerializer().makeBlock(b2.bitcoinSerialize());
}
@Test

View File

@ -59,7 +59,7 @@ public class CoinbaseBlockTest {
byte[] blockAsBytes = getBytes(getClass().getResourceAsStream("block169482.dat"));
// Create block 169482.
Block block = new Block(params, blockAsBytes);
Block block = params.getDefaultSerializer().makeBlock(blockAsBytes);
// Check block.
assertNotNull(block);

View File

@ -139,20 +139,20 @@ public class FilteredBlockAndPartialMerkleTreeTests extends TestWithPeerGroup {
List<Sha256Hash> txHashList = filteredBlock.getTransactionHashes();
assertTrue(txHashList.size() == 4);
// 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")));
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")));
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")));
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")));
assertEquals(tx3.getHash(),txHashList.get(3));

View File

@ -1058,7 +1058,7 @@ public class FullBlockTestGenerator {
Block b56;
try {
b56 = new Block(params, b57.block.bitcoinSerialize());
b56 = params.getDefaultSerializer().makeBlock(b57.block.bitcoinSerialize());
} catch (ProtocolException e) {
throw new RuntimeException(e); // Cannot happen.
}
@ -1099,7 +1099,7 @@ public class FullBlockTestGenerator {
Block b56p2;
try {
b56p2 = new Block(params, b57p2.block.bitcoinSerialize());
b56p2 = params.getDefaultSerializer().makeBlock(b57p2.block.bitcoinSerialize());
} catch (ProtocolException e) {
throw new RuntimeException(e); // Cannot happen.
}
@ -1218,7 +1218,7 @@ public class FullBlockTestGenerator {
for (Transaction transaction : b64Original.block.getTransactions())
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
// 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();
Block b71 = new Block(params, b72.block.bitcoinSerialize());
Block b71 = params.getDefaultSerializer().makeBlock(b72.block.bitcoinSerialize());
b71.addTransaction(b72.block.getTransactions().get(2));
checkState(b71.getHash().equals(b72.getHash()));
blocks.add(new BlockAndValidity(b71, false, true, b69.getHash(), chainHeadHeight + 21, "b71"));

View File

@ -103,7 +103,7 @@ public class LazyParseByteCacheTest {
Block b1 = createFakeBlock(blockStore, tx1, tx2).block;
BitcoinSerializer bs = new BitcoinSerializer(unitTestParams);
MessageSerializer bs = unitTestParams.getDefaultSerializer();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bs.serialize(tx1, bos);
@ -175,10 +175,10 @@ public class LazyParseByteCacheTest {
public void testBlock(byte[] blockBytes, boolean isChild, boolean lazy, boolean retain) throws Exception {
//reference serializer to produce comparison serialization output after changes to
//message structure.
BitcoinSerializer bsRef = new BitcoinSerializer(unitTestParams, false, false);
MessageSerializer bsRef = unitTestParams.getSerializer(false, false);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BitcoinSerializer bs = new BitcoinSerializer(unitTestParams, lazy, retain);
BitcoinSerializer bs = unitTestParams.getSerializer(lazy, retain);
Block b1;
Block bRef;
b1 = (Block) bs.deserialize(ByteBuffer.wrap(blockBytes));
@ -411,10 +411,10 @@ public class LazyParseByteCacheTest {
//reference serializer to produce comparison serialization output after changes to
//message structure.
BitcoinSerializer bsRef = new BitcoinSerializer(params, false, false);
MessageSerializer bsRef = params.getSerializer(false, false);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BitcoinSerializer bs = new BitcoinSerializer(params, lazy, retain);
BitcoinSerializer bs = params.getSerializer(lazy, retain);
Transaction t1;
Transaction tRef;
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();
bs.serialize(message, bos);
byte[] b1 = bos.toByteArray();

View File

@ -863,7 +863,7 @@ public class PeerTest extends TestWithNetworkConnections {
}
});
final NetworkParameters params = TestNet3Params.get();
BitcoinSerializer serializer = new BitcoinSerializer(params);
MessageSerializer serializer = params.getDefaultSerializer();
// Now write some bogus truncated message.
ByteArrayOutputStream out = new ByteArrayOutputStream();
serializer.serialize("inv", new InventoryMessage(params) {

View File

@ -52,7 +52,7 @@ public class TxConfidenceTableTest {
@Test
public void pinHandlers() throws Exception {
Transaction tx = new Transaction(params, tx1.bitcoinSerialize());
Transaction tx = params.getDefaultSerializer().makeTransaction(tx1.bitcoinSerialize());
Sha256Hash hash = tx.getHash();
table.seen(hash, address1);
assertEquals(1, tx.getConfidence().numBroadcastPeers());

View File

@ -624,7 +624,7 @@ public class WalletTest extends TestWithWallet {
// Send 0.10 to somebody else.
Transaction send1 = wallet.createSend(new ECKey().toAddress(params), valueOf(0, 10));
// Reserialize.
Transaction send2 = new Transaction(params, send1.bitcoinSerialize());
Transaction send2 = params.getDefaultSerializer().makeTransaction(send1.bitcoinSerialize());
assertEquals(nanos, send2.getValueSentFromMe(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());
Transaction txClone = new Transaction(params, tx.bitcoinSerialize());
Transaction txClone = params.getDefaultSerializer().makeTransaction(tx.bitcoinSerialize());
try {
wallet.receiveFromBlock(txClone, null, BlockChain.NewBlockType.BEST_CHAIN, 0);
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));
// Create a double spend of just the first one.
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.
wallet.commitTx(send1);
assertEquals(ZERO, wallet.getBalance());
@ -765,7 +765,7 @@ public class WalletTest extends TestWithWallet {
Transaction send2 = checkNotNull(wallet.createSend(address, value2));
byte[] buf = send1.bitcoinSerialize();
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.allowSpendingUnconfirmedTransactions();
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));
// Create a double spend.
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.
wallet.commitTx(send1);
assertEquals(send1, received.getOutput(0).getSpentBy().getParentTransaction());
@ -912,7 +912,7 @@ public class WalletTest extends TestWithWallet {
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
Threading.waitForUserCode();
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);
Threading.waitForUserCode();
assertFalse(flags[0]);

View File

@ -125,7 +125,7 @@ public class ScriptTest {
ECKey key3 = DumpedPrivateKey.fromBase58(params, "cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg").getKey();
Script multisigScript = ScriptBuilder.createMultiSigOutputScript(2, Arrays.asList(key1, key2, key3));
byte[] bytes = HEX.decode("01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000");
Transaction transaction = new Transaction(params, bytes);
Transaction transaction = params.getDefaultSerializer().makeTransaction(bytes);
TransactionOutput output = transaction.getOutput(1);
Transaction spendTx = new Transaction(params);
Address address = Address.fromBase58(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H");
@ -324,7 +324,7 @@ public class ScriptTest {
Transaction transaction = null;
try {
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();
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())
continue; // This is a comment.
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());
boolean valid = true;

View File

@ -188,7 +188,7 @@ public class WalletProtobufSerializerTest {
assertTrue(lastSeenBlockHash.isEmpty());
// Create a block.
Block block = new Block(params, BlockTest.blockBytes);
Block block = params.getDefaultSerializer().makeBlock(BlockTest.blockBytes);
Sha256Hash blockHash = block.getHash();
wallet.setLastBlockSeenHash(blockHash);
wallet.setLastBlockSeenHeight(1);