diff --git a/core/src/main/java/org/bitcoinj/core/AddressMessage.java b/core/src/main/java/org/bitcoinj/core/AddressMessage.java
index 380e980c..e9ef386f 100644
--- a/core/src/main/java/org/bitcoinj/core/AddressMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/AddressMessage.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright 2011 Google Inc.
+ * Copyright 2014 Andreas Schildbach
+ *
+ * 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;
@@ -20,7 +37,6 @@ public class AddressMessage extends Message {
* Contruct a new 'addr' 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.
@@ -53,11 +69,7 @@ public class AddressMessage extends Message {
}
@Override
- protected void parseLite() throws ProtocolException {
- }
-
- @Override
- void parse() throws ProtocolException {
+ protected void parse() throws ProtocolException {
long numAddresses = readVarInt();
// Guard against ultra large messages that will crash us.
if (numAddresses > MAX_ADDRESSES)
@@ -68,7 +80,9 @@ public class AddressMessage extends Message {
addresses.add(addr);
cursor += addr.getMessageSize();
}
- length = cursor - offset;
+ length = new VarInt(addresses.size()).getSizeInBytes();
+ // The 4 byte difference is the uint32 timestamp that was introduced in version 31402
+ length += addresses.size() * (protocolVersion > 31402 ? PeerAddress.MESSAGE_SIZE : PeerAddress.MESSAGE_SIZE - 4);
}
/* (non-Javadoc)
@@ -84,29 +98,15 @@ public class AddressMessage extends Message {
}
}
- @Override
- public int getMessageSize() {
- if (length != UNKNOWN_LENGTH)
- return length;
- if (addresses != null) {
- length = new VarInt(addresses.size()).getSizeInBytes();
- // The 4 byte difference is the uint32 timestamp that was introduced in version 31402
- length += addresses.size() * (protocolVersion > 31402 ? PeerAddress.MESSAGE_SIZE : PeerAddress.MESSAGE_SIZE - 4);
- }
- return length;
- }
-
/**
* @return An unmodifiableList view of the backing List of addresses. Addresses contained within the list may be safely modified.
*/
public List getAddresses() {
- maybeParse();
return Collections.unmodifiableList(addresses);
}
public void addAddress(PeerAddress address) {
unCache();
- maybeParse();
address.setParent(this);
addresses.add(address);
if (length == UNKNOWN_LENGTH)
@@ -129,5 +129,4 @@ public class AddressMessage extends Message {
public String toString() {
return "addr: " + Utils.join(addresses);
}
-
}
diff --git a/core/src/main/java/org/bitcoinj/core/AlertMessage.java b/core/src/main/java/org/bitcoinj/core/AlertMessage.java
index 3418680b..23d8e43e 100644
--- a/core/src/main/java/org/bitcoinj/core/AlertMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/AlertMessage.java
@@ -1,5 +1,6 @@
/*
* Copyright 2011 Google Inc.
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,7 +62,7 @@ public class AlertMessage extends Message {
}
@Override
- void parse() throws ProtocolException {
+ protected void parse() throws ProtocolException {
// Alerts are formatted in two levels. The top level contains two byte arrays: a signature, and a serialized
// data structure containing the actual alert data.
int startPos = cursor;
@@ -115,11 +116,6 @@ public class AlertMessage extends Message {
return ECKey.verify(Sha256Hash.hashTwice(content), signature, params.getAlertSigningKey());
}
- @Override
- protected void parseLite() throws ProtocolException {
- // Do nothing, lazy parsing isn't useful for alerts.
- }
-
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Field accessors.
diff --git a/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java b/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java
index 19fb58fb..aa93681d 100644
--- a/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java
+++ b/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java
@@ -46,7 +46,6 @@ public class BitcoinSerializer implements MessageSerializer {
private static final int COMMAND_LEN = 12;
private final NetworkParameters params;
- private final boolean parseLazy;
private final boolean parseRetain;
private static final Map, String> names = new HashMap, String>();
@@ -74,32 +73,14 @@ public class BitcoinSerializer implements MessageSerializer {
names.put(UTXOsMessage.class, "utxos");
}
- /**
- * 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 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.
- */
- @Deprecated
- BitcoinSerializer(boolean parseLazy, boolean parseRetain) {
- this.params = null;
- this.parseLazy = parseLazy;
- this.parseRetain = parseRetain;
- }
-
/**
* Constructs a BitcoinSerializer with the given behavior.
*
* @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.
*/
- public BitcoinSerializer(NetworkParameters params, boolean parseLazy, boolean parseRetain) {
+ public BitcoinSerializer(NetworkParameters params, boolean parseRetain) {
this.params = params;
- this.parseLazy = parseLazy;
this.parseRetain = parseRetain;
}
@@ -370,14 +351,6 @@ public class BitcoinSerializer implements MessageSerializer {
}
}
- /**
- * Whether the serializer will produce lazy parse mode Messages
- */
- @Override
- public boolean isParseLazyMode() {
- return parseLazy;
- }
-
/**
* Whether the serializer will produce cached mode Messages
*/
diff --git a/core/src/main/java/org/bitcoinj/core/Block.java b/core/src/main/java/org/bitcoinj/core/Block.java
index 2ab94e1d..16d273de 100644
--- a/core/src/main/java/org/bitcoinj/core/Block.java
+++ b/core/src/main/java/org/bitcoinj/core/Block.java
@@ -93,9 +93,6 @@ public class Block extends Message {
/** Stores the hash of the block. If null, getHash() will recalculate it. */
private Sha256Hash hash;
- protected boolean headerParsed;
- protected boolean transactionsParsed;
-
protected boolean headerBytesValid;
protected boolean transactionBytesValid;
@@ -195,28 +192,6 @@ public class Block extends Message {
return FIFTY_COINS.shiftRight(height / params.getSubsidyDecreaseBlockCount());
}
- protected void parseHeader() throws ProtocolException {
- if (headerParsed)
- return;
-
- cursor = offset;
- version = readUint32();
- prevBlockHash = readHash();
- merkleRoot = readHash();
- time = readUint32();
- difficultyTarget = readUint32();
- nonce = readUint32();
-
- hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(payload, offset, cursor));
-
- headerParsed = true;
- headerBytesValid = serializer.isParseRetainMode();
- }
-
- protected void parseTransactions() throws ProtocolException {
- parseTransactions(offset + HEADER_SIZE);
- }
-
/**
* Parse transactions from the block.
*
@@ -225,14 +200,10 @@ public class Block extends Message {
* size.
*/
protected void parseTransactions(final int transactionsOffset) throws ProtocolException {
- if (transactionsParsed)
- return;
-
cursor = transactionsOffset;
optimalEncodingMessageSize = HEADER_SIZE;
if (payload.length == cursor) {
// This message is just a header, it has no transactions.
- transactionsParsed = true;
transactionBytesValid = false;
return;
}
@@ -248,160 +219,36 @@ public class Block extends Message {
cursor += tx.getMessageSize();
optimalEncodingMessageSize += tx.getOptimalEncodingMessageSize();
}
- // 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 = serializer.isParseRetainMode();
}
@Override
- void parse() throws ProtocolException {
- parseHeader();
- parseTransactions();
+ protected void parse() throws ProtocolException {
+ // header
+ cursor = offset;
+ version = readUint32();
+ prevBlockHash = readHash();
+ merkleRoot = readHash();
+ time = readUint32();
+ difficultyTarget = readUint32();
+ nonce = readUint32();
+ hash = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(payload, offset, cursor));
+ headerBytesValid = serializer.isParseRetainMode();
+
+ // transactions
+ parseTransactions(offset + HEADER_SIZE);
length = cursor - offset;
}
public int getOptimalEncodingMessageSize() {
if (optimalEncodingMessageSize != 0)
return optimalEncodingMessageSize;
- maybeParseTransactions();
if (optimalEncodingMessageSize != 0)
return optimalEncodingMessageSize;
optimalEncodingMessageSize = bitcoinSerialize().length;
return optimalEncodingMessageSize;
}
- @Override
- protected void parseLite() throws ProtocolException {
- // 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(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 || serializer.isParseRetainMode() && length > HEADER_SIZE;
- }
- headerBytesValid = !headerParsed || serializer.isParseRetainMode() && length >= HEADER_SIZE;
- }
-
- /*
- * Block uses some special handling for lazy parsing and retention of cached bytes. Parsing and serializing the
- * block header and the transaction list are both non-trivial so there are good efficiency gains to be had by
- * separating them. There are many cases where a user may need to access or change one or the other but not both.
- *
- * With this in mind we ignore the inherited checkParse() and unCache() methods and implement a separate version
- * of them for both header and transactions.
- *
- * Serializing methods are also handled in their own way. Whilst they deal with separate parts of the block structure
- * there are some interdependencies. For example altering a tx requires invalidating the Merkle root and therefore
- * the cached header bytes.
- */
- private void maybeParseHeader() {
- if (headerParsed || payload == null)
- return;
- try {
- parseHeader();
- if (!(headerBytesValid || transactionBytesValid))
- 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);
- }
- }
-
- private void maybeParseTransactions() {
- if (transactionsParsed || payload == null)
- return;
- try {
- parseTransactions();
- if (!serializer.isParseRetainMode()) {
- transactionBytesValid = false;
- if (headerParsed)
- 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);
- }
- }
-
- /**
- * Ensure the object is parsed if needed. This should be called in every getter before returning a value. If the
- * lazy parse flag is not set this is a method returns immediately.
- */
- @Override
- protected void maybeParse() {
- throw new LazyParseException(
- "checkParse() should never be called on a Block. Instead use checkParseHeader() and checkParseTransactions()");
- }
-
- /**
- * In lazy parsing mode access to getters and setters may throw an unchecked LazyParseException. If guaranteed
- * safe access is required this method will force parsing to occur immediately thus ensuring LazyParseExeption will
- * never be thrown from this Message. If the Message contains child messages (e.g. a Block containing Transaction
- * messages) this will not force child messages to parse.
- *
- * This method ensures parsing of both headers and transactions.
- *
- * @throws ProtocolException
- */
- @Override
- public void ensureParsed() throws ProtocolException {
- try {
- maybeParseHeader();
- maybeParseTransactions();
- } catch (LazyParseException e) {
- if (e.getCause() instanceof ProtocolException)
- throw (ProtocolException) e.getCause();
- throw new ProtocolException(e);
- }
- }
-
- /**
- * In lazy parsing mode access to getters and setters may throw an unchecked LazyParseException. If guaranteed
- * safe access is required this method will force parsing to occur immediately thus ensuring LazyParseExeption
- * will never be thrown from this Message. If the Message contains child messages (e.g. a Block containing
- * Transaction messages) this will not force child messages to parse.
- *
- * This method ensures parsing of headers only.
- *
- * @throws ProtocolException
- */
- public void ensureParsedHeader() throws ProtocolException {
- try {
- maybeParseHeader();
- } catch (LazyParseException e) {
- if (e.getCause() instanceof ProtocolException)
- throw (ProtocolException) e.getCause();
- throw new ProtocolException(e);
- }
- }
-
- /**
- * In lazy parsing mode access to getters and setters may throw an unchecked LazyParseException. If guaranteed
- * safe access is required this method will force parsing to occur immediately thus ensuring LazyParseExeption will
- * never be thrown from this Message. If the Message contains child messages (e.g. a Block containing Transaction
- * messages) this will not force child messages to parse.
- *
- * This method ensures parsing of transactions only.
- *
- * @throws ProtocolException
- */
- public void ensureParsedTransactions() throws ProtocolException {
- try {
- maybeParseTransactions();
- } catch (LazyParseException e) {
- if (e.getCause() instanceof ProtocolException)
- throw (ProtocolException) e.getCause();
- throw new ProtocolException(e);
- }
- }
-
// default for testing
void writeHeader(OutputStream stream) throws IOException {
// try for cached write first
@@ -410,7 +257,6 @@ public class Block extends Message {
return;
}
// fall back to manual write
- maybeParseHeader();
Utils.uint32ToByteStreamLE(version, stream);
stream.write(prevBlockHash.getReversedBytes());
stream.write(getMerkleRoot().getReversedBytes());
@@ -422,7 +268,7 @@ public class Block extends Message {
private void writeTransactions(OutputStream stream) throws IOException {
// check for no transaction conditions first
// must be a more efficient way to do this but I'm tired atm.
- if (transactions == null && transactionsParsed) {
+ if (transactions == null) {
return;
}
@@ -509,7 +355,6 @@ public class Block extends Message {
}
private void unCacheHeader() {
- maybeParseHeader();
headerBytesValid = false;
if (!transactionBytesValid)
payload = null;
@@ -517,7 +362,6 @@ public class Block extends Message {
}
private void unCacheTransactions() {
- maybeParseTransactions();
transactionBytesValid = false;
if (!headerBytesValid)
payload = null;
@@ -584,7 +428,6 @@ public class Block extends Message {
/** Returns a copy of the block, but without any transactions. */
public Block cloneAsHeader() {
- maybeParseHeader();
Block block = new Block(params, BLOCK_VERSION_GENESIS);
copyBitcoinHeaderTo(block);
return block;
@@ -633,7 +476,6 @@ public class Block extends Message {
* extraNonce.
*/
public void solve() {
- maybeParseHeader();
while (true) {
try {
// Is our proof of work valid yet?
@@ -653,7 +495,6 @@ public class Block extends Message {
* is thrown.
*/
public BigInteger getDifficultyTargetAsInteger() throws VerificationException {
- maybeParseHeader();
BigInteger target = Utils.decodeCompactBits(difficultyTarget);
if (target.signum() <= 0 || target.compareTo(params.maxTarget) > 0)
throw new VerificationException("Difficulty target is bad: " + target.toString());
@@ -685,7 +526,6 @@ public class Block extends Message {
}
private void checkTimestamp() throws VerificationException {
- maybeParseHeader();
// Allow injection of a fake clock to allow unit testing.
long currentTime = Utils.currentTimeSeconds();
if (time > currentTime + ALLOWED_TIME_DRIFT)
@@ -747,7 +587,6 @@ public class Block extends Message {
// 2 3 4 4
// / \ / \ / \
// t1 t2 t3 t4 t5 t5
- maybeParseTransactions();
ArrayList tree = new ArrayList();
// Start by adding all the hashes of the transactions as leaves of the tree.
for (Transaction t : transactions) {
@@ -796,7 +635,6 @@ public class Block extends Message {
//
// Firstly we need to ensure this block does in fact represent real work done. If the difficulty is high
// enough, it's probably been done by the network.
- maybeParseHeader();
checkProofOfWork(true);
checkTimestamp();
}
@@ -813,7 +651,6 @@ public class Block extends Message {
// transactions that reference spent or non-existant inputs.
if (transactions.isEmpty())
throw new VerificationException("Block had no transactions");
- maybeParseTransactions();
if (this.getOptimalEncodingMessageSize() > MAX_BLOCK_SIZE)
throw new VerificationException("Block larger than MAX_BLOCK_SIZE");
checkTransactions();
@@ -847,7 +684,6 @@ public class Block extends Message {
* Returns the merkle root in big endian form, calculating it from transactions if necessary.
*/
public Sha256Hash getMerkleRoot() {
- maybeParseHeader();
if (merkleRoot == null) {
//TODO check if this is really necessary.
unCacheHeader();
@@ -888,7 +724,6 @@ public class Block extends Message {
/** Returns the version of the block data structure as defined by the Bitcoin protocol. */
public long getVersion() {
- maybeParseHeader();
return version;
}
@@ -896,7 +731,6 @@ public class Block extends Message {
* Returns the hash of the previous block in the chain, as defined by the block header.
*/
public Sha256Hash getPrevBlockHash() {
- maybeParseHeader();
return prevBlockHash;
}
@@ -911,7 +745,6 @@ public class Block extends Message {
* is measured in seconds since the UNIX epoch (midnight Jan 1st 1970).
*/
public long getTimeSeconds() {
- maybeParseHeader();
return time;
}
@@ -938,7 +771,6 @@ public class Block extends Message {
* Calculating the difficulty that way is currently unsupported.
*/
public long getDifficultyTarget() {
- maybeParseHeader();
return difficultyTarget;
}
@@ -954,7 +786,6 @@ public class Block extends Message {
* difficulty target.
*/
public long getNonce() {
- maybeParseHeader();
return nonce;
}
@@ -968,7 +799,6 @@ public class Block extends Message {
/** Returns an immutable list of transactions held in this block, or null if this object represents just a header. */
@Nullable
public List getTransactions() {
- maybeParseTransactions();
return transactions == null ? null : ImmutableList.copyOf(transactions);
}
@@ -1087,16 +917,6 @@ public class Block extends Message {
return createNextBlock(null, 1, null, Utils.currentTimeSeconds(), pubKey, FIFTY_COINS);
}
- @VisibleForTesting
- boolean isParsedHeader() {
- return headerParsed;
- }
-
- @VisibleForTesting
- boolean isParsedTransactions() {
- return transactionsParsed;
- }
-
@VisibleForTesting
boolean isHeaderBytesValid() {
return headerBytesValid;
diff --git a/core/src/main/java/org/bitcoinj/core/BloomFilter.java b/core/src/main/java/org/bitcoinj/core/BloomFilter.java
index 447e89a2..c1d62391 100644
--- a/core/src/main/java/org/bitcoinj/core/BloomFilter.java
+++ b/core/src/main/java/org/bitcoinj/core/BloomFilter.java
@@ -1,5 +1,6 @@
/*
* Copyright 2012 Matt Corallo
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -130,7 +131,7 @@ public class BloomFilter extends Message {
}
@Override
- void parse() throws ProtocolException {
+ protected void parse() throws ProtocolException {
data = readByteArray();
if (data.length > MAX_FILTER_SIZE)
throw new ProtocolException ("Bloom filter out of size range.");
@@ -154,11 +155,6 @@ public class BloomFilter extends Message {
stream.write(nFlags);
}
- @Override
- protected void parseLite() throws ProtocolException {
- // Do nothing, lazy parsing isn't useful for bloom filters.
- }
-
private static int rotateLeft32(int x, int r) {
return (x << r) | (x >>> (32 - r));
}
diff --git a/core/src/main/java/org/bitcoinj/core/DummySerializer.java b/core/src/main/java/org/bitcoinj/core/DummySerializer.java
index efef9959..7d426619 100644
--- a/core/src/main/java/org/bitcoinj/core/DummySerializer.java
+++ b/core/src/main/java/org/bitcoinj/core/DummySerializer.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.bitcoinj.core;
import java.io.IOException;
@@ -47,11 +48,6 @@ class DummySerializer implements MessageSerializer {
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
}
- @Override
- public boolean isParseLazyMode() {
- return false;
- }
-
@Override
public boolean isParseRetainMode() {
return false;
diff --git a/core/src/main/java/org/bitcoinj/core/EmptyMessage.java b/core/src/main/java/org/bitcoinj/core/EmptyMessage.java
index 5a24ef21..2186a98a 100644
--- a/core/src/main/java/org/bitcoinj/core/EmptyMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/EmptyMessage.java
@@ -1,5 +1,6 @@
/*
* Copyright 2011 Steve Coughlan.
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.bitcoinj.core;
import java.io.IOException;
@@ -43,31 +45,7 @@ public abstract class EmptyMessage extends Message {
}
@Override
- public int getMessageSize() {
- return 0;
- }
-
- /* (non-Javadoc)
- * @see Message#parse()
- */
- @Override
- void parse() throws ProtocolException {
- }
-
- /* (non-Javadoc)
- * @see Message#parseLite()
- */
- @Override
- protected void parseLite() throws ProtocolException {
- length = 0;
- }
-
- /* (non-Javadoc)
- * @see Message#ensureParsed()
- */
- @Override
- public void ensureParsed() throws ProtocolException {
- parsed = true;
+ protected void parse() throws ProtocolException {
}
/* (non-Javadoc)
@@ -77,6 +55,4 @@ public abstract class EmptyMessage extends Message {
public byte[] bitcoinSerialize() {
return new byte[0];
}
-
-
}
diff --git a/core/src/main/java/org/bitcoinj/core/FilteredBlock.java b/core/src/main/java/org/bitcoinj/core/FilteredBlock.java
index e34fb8e9..73b261fb 100644
--- a/core/src/main/java/org/bitcoinj/core/FilteredBlock.java
+++ b/core/src/main/java/org/bitcoinj/core/FilteredBlock.java
@@ -1,5 +1,6 @@
/**
* Copyright 2012 Matt Corallo
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -57,7 +58,7 @@ public class FilteredBlock extends Message {
}
@Override
- void parse() throws ProtocolException {
+ protected void parse() throws ProtocolException {
byte[] headerBytes = new byte[Block.HEADER_SIZE];
System.arraycopy(payload, 0, headerBytes, 0, Block.HEADER_SIZE);
header = params.getDefaultSerializer().makeBlock(headerBytes);
@@ -67,11 +68,6 @@ public class FilteredBlock extends Message {
length = Block.HEADER_SIZE + merkleTree.getMessageSize();
}
- @Override
- protected void parseLite() throws ProtocolException {
-
- }
-
/**
* Gets a list of leaf hashes which are contained in the partial merkle tree in this filtered block
*
diff --git a/core/src/main/java/org/bitcoinj/core/GetBlocksMessage.java b/core/src/main/java/org/bitcoinj/core/GetBlocksMessage.java
index a8cbf401..66d464d1 100644
--- a/core/src/main/java/org/bitcoinj/core/GetBlocksMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/GetBlocksMessage.java
@@ -1,5 +1,6 @@
/*
* Copyright 2011 Google Inc.
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,22 +44,13 @@ public class GetBlocksMessage extends Message {
}
@Override
- protected void parseLite() throws ProtocolException {
+ protected void parse() throws ProtocolException {
cursor = offset;
version = readUint32();
int startCount = (int) readVarInt();
if (startCount > 500)
throw new ProtocolException("Number of locators cannot be > 500, received: " + startCount);
length = cursor - offset + ((startCount + 1) * 32);
- }
-
- @Override
- public void parse() throws ProtocolException {
- cursor = offset;
- version = readUint32();
- int startCount = (int) readVarInt();
- if (startCount > 500)
- throw new ProtocolException("Number of locators cannot be > 500, received: " + startCount);
locator = new ArrayList(startCount);
for (int i = 0; i < startCount; i++) {
locator.add(readHash());
diff --git a/core/src/main/java/org/bitcoinj/core/GetUTXOsMessage.java b/core/src/main/java/org/bitcoinj/core/GetUTXOsMessage.java
index da177603..70aafe47 100644
--- a/core/src/main/java/org/bitcoinj/core/GetUTXOsMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/GetUTXOsMessage.java
@@ -78,11 +78,6 @@ public class GetUTXOsMessage extends Message {
return outPoints;
}
- @Override
- protected void parseLite() throws ProtocolException {
- // Not needed.
- }
-
@Override
void bitcoinSerializeToStream(OutputStream stream) throws IOException {
stream.write(new byte[]{includeMempool ? (byte) 1 : 0}); // include mempool.
diff --git a/core/src/main/java/org/bitcoinj/core/HeadersMessage.java b/core/src/main/java/org/bitcoinj/core/HeadersMessage.java
index 213a3874..a6b3e1a5 100644
--- a/core/src/main/java/org/bitcoinj/core/HeadersMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/HeadersMessage.java
@@ -1,5 +1,6 @@
/*
* Copyright 2011 Google Inc.
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,7 +63,7 @@ public class HeadersMessage extends Message {
}
@Override
- protected void parseLite() throws ProtocolException {
+ protected void parse() throws ProtocolException {
if (length == UNKNOWN_LENGTH) {
int saveCursor = cursor;
long numHeaders = readVarInt();
@@ -71,10 +72,7 @@ public class HeadersMessage extends Message {
// Each header has 80 bytes and one more byte for transactions number which is 00.
length = 81 * (int)numHeaders;
}
- }
- @Override
- void parse() throws ProtocolException {
long numHeaders = readVarInt();
if (numHeaders > MAX_HEADERS)
throw new ProtocolException("Too many headers: got " + numHeaders + " which is larger than " +
@@ -88,7 +86,7 @@ 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 = this.params.getSerializer(true, true)
+ Block newBlockHeader = this.params.getSerializer(true)
.makeBlock(blockHeader, 81);
blockHeaders.add(newBlockHeader);
}
@@ -100,7 +98,6 @@ public class HeadersMessage extends Message {
}
}
-
public List getBlockHeaders() {
return blockHeaders;
}
diff --git a/core/src/main/java/org/bitcoinj/core/ListMessage.java b/core/src/main/java/org/bitcoinj/core/ListMessage.java
index e209c725..2c278142 100644
--- a/core/src/main/java/org/bitcoinj/core/ListMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/ListMessage.java
@@ -1,5 +1,6 @@
/*
* Copyright 2011 Google Inc.
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +50,6 @@ public abstract class ListMessage extends Message {
}
public List getItems() {
- maybeParse();
return Collections.unmodifiableList(items);
}
@@ -68,15 +68,12 @@ public abstract class ListMessage extends Message {
}
@Override
- protected void parseLite() throws ProtocolException {
+ protected void parse() throws ProtocolException {
arrayLen = readVarInt();
if (arrayLen > MAX_INVENTORY_ITEMS)
throw new ProtocolException("Too many items in INV message: " + arrayLen);
length = (int) (cursor - offset + (arrayLen * InventoryItem.MESSAGE_LENGTH));
- }
- @Override
- public void parse() throws ProtocolException {
// An inv is vector where CInv is int+hash. The int is either 1 or 2 for tx or block.
items = new ArrayList((int) arrayLen);
for (int i = 0; i < arrayLen; i++) {
diff --git a/core/src/main/java/org/bitcoinj/core/MemoryPoolMessage.java b/core/src/main/java/org/bitcoinj/core/MemoryPoolMessage.java
index c52a172f..33a44a77 100644
--- a/core/src/main/java/org/bitcoinj/core/MemoryPoolMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/MemoryPoolMessage.java
@@ -1,5 +1,6 @@
/*
* Copyright 2012 Google Inc.
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,10 +29,7 @@ import java.io.OutputStream;
*/
public class MemoryPoolMessage extends Message {
@Override
- void parse() throws ProtocolException {}
-
- @Override
- protected void parseLite() throws ProtocolException {}
+ protected void parse() throws ProtocolException {}
@Override
void bitcoinSerializeToStream(OutputStream stream) throws IOException {}
diff --git a/core/src/main/java/org/bitcoinj/core/Message.java b/core/src/main/java/org/bitcoinj/core/Message.java
index 90e84166..1b34a374 100644
--- a/core/src/main/java/org/bitcoinj/core/Message.java
+++ b/core/src/main/java/org/bitcoinj/core/Message.java
@@ -52,7 +52,6 @@ public abstract class Message {
// The raw message payload bytes themselves.
protected byte[] payload;
- protected boolean parsed = false;
protected boolean recached = false;
protected MessageSerializer serializer;
@@ -61,17 +60,15 @@ public abstract class Message {
protected NetworkParameters params;
protected Message() {
- parsed = true;
serializer = DummySerializer.DEFAULT;
}
- Message(NetworkParameters params) {
+ protected Message(NetworkParameters params) {
this.params = params;
- parsed = true;
serializer = params.getDefaultSerializer();
}
- Message(NetworkParameters params, byte[] payload, int offset, int protocolVersion) throws ProtocolException {
+ protected Message(NetworkParameters params, byte[] payload, int offset, int protocolVersion) throws ProtocolException {
this(params, payload, offset, protocolVersion, params.getDefaultSerializer(), UNKNOWN_LENGTH);
}
@@ -86,38 +83,30 @@ public abstract class Message {
* 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, MessageSerializer serializer, int length) throws ProtocolException {
+ protected 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 (serializer.isParseLazyMode()) {
- parseLite();
- } else {
- parseLite();
- parse();
- parsed = true;
- }
+
+ parse();
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(), serializer.isParseLazyMode() ? "lite" : "full");
+ checkState(false, "Length field has not been set in constructor for %s after parse.",
+ getClass().getSimpleName());
if (SELF_CHECK) {
selfCheck(payload, offset);
}
- if (serializer.isParseRetainMode() || !parsed)
- return;
- this.payload = null;
+ if (!serializer.isParseRetainMode())
+ this.payload = null;
}
private void selfCheck(byte[] payload, int offset) {
if (!(this instanceof VersionMessage)) {
- maybeParse();
byte[] payloadBytes = new byte[cursor - offset];
System.arraycopy(payload, offset, payloadBytes, 0, cursor - offset);
byte[] reserialized = bitcoinSerialize();
@@ -138,68 +127,15 @@ public abstract class Message {
// These methods handle the serialization/deserialization using the custom Bitcoin protocol.
- abstract void parse() throws ProtocolException;
+ protected abstract void parse() throws ProtocolException;
/**
- * Perform the most minimal parse possible to calculate the length of the message payload.
- * This is only required for subclasses of ChildMessage as root level messages will have their length passed
- * into the constructor.
- *
- * Implementations should adhere to the following contract: If parseLazy = true the 'length'
- * field must be set before returning. If parseLazy = false the length field must be set either
- * within the parseLite() method OR the parse() method. The overriding requirement is that length
- * must be set to non UNKNOWN_MESSAGE value by the time the constructor exits.
- *
- * @return
- * @throws ProtocolException
- */
- protected abstract void parseLite() throws ProtocolException;
-
- /**
- * Ensure the object is parsed if needed. This should be called in every getter before returning a value.
- * If the lazy parse flag is not set this is a method returns immediately.
- */
- protected synchronized void maybeParse() {
- if (parsed || payload == null)
- return;
- try {
- parse();
- parsed = true;
- 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);
- }
- }
-
- /**
- * In lazy parsing mode access to getters and setters may throw an unchecked LazyParseException. If guaranteed safe access is required
- * this method will force parsing to occur immediately thus ensuring LazyParseExeption will never be thrown from this Message.
- * If the Message contains child messages (e.g. a Block containing Transaction messages) this will not force child messages to parse.
- *
- * This could be overidden for Transaction and it's child classes to ensure the entire tree of Message objects is parsed.
- *
- * @throws ProtocolException
- */
- public void ensureParsed() throws ProtocolException {
- try {
- maybeParse();
- } catch (LazyParseException e) {
- if (e.getCause() instanceof ProtocolException)
- throw (ProtocolException) e.getCause();
- throw new ProtocolException(e);
- }
- }
-
- /**
- * To be called before any change of internal values including any setters. This ensures any cached byte array is
- * removed after performing a lazy parse if necessary to ensure the object is fully populated.
- *
- * Child messages of this object(e.g. Transactions belonging to a Block) will not have their internal byte caches
- * invalidated unless they are also modified internally.
+ * To be called before any change of internal values including any setters. This ensures any cached byte array is
+ * removed.
+ * Child messages of this object(e.g. Transactions belonging to a Block) will not have their internal byte caches
+ * invalidated unless they are also modified internally.
*/
protected void unCache() {
- maybeParse();
payload = null;
recached = false;
}
@@ -220,13 +156,6 @@ public abstract class Message {
length += VarInt.sizeOf(newArraySize) - VarInt.sizeOf(newArraySize - 1);
}
- /**
- * used for unit testing
- */
- public boolean isParsed() {
- return parsed;
- }
-
/**
* used for unit testing
*/
@@ -346,17 +275,11 @@ public abstract class Message {
}
/**
- * This should be overridden to extract correct message size in the case of lazy parsing. Until this method is
- * implemented in a subclass of ChildMessage lazy parsing may have no effect.
- *
- * This default implementation is a safe fall back that will ensure it returns a correct value by parsing the message.
+ * This returns a correct value by parsing the message.
*/
- public int getMessageSize() {
- if (length != UNKNOWN_LENGTH)
- return length;
- maybeParse();
+ public final int getMessageSize() {
if (length == UNKNOWN_LENGTH)
- checkState(false, "Length field has not been set in %s after full parse.", getClass().getSimpleName());
+ checkState(false, "Length field has not been set in %s.", getClass().getSimpleName());
return length;
}
@@ -448,16 +371,4 @@ public abstract class Message {
this.serializer = params.getDefaultSerializer();
}
}
-
- public static class LazyParseException extends RuntimeException {
-
- public LazyParseException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public LazyParseException(String message) {
- super(message);
- }
-
- }
}
diff --git a/core/src/main/java/org/bitcoinj/core/MessageSerializer.java b/core/src/main/java/org/bitcoinj/core/MessageSerializer.java
index 35736a2f..8a9f7d4e 100644
--- a/core/src/main/java/org/bitcoinj/core/MessageSerializer.java
+++ b/core/src/main/java/org/bitcoinj/core/MessageSerializer.java
@@ -15,6 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.bitcoinj.core;
import java.io.IOException;
@@ -45,11 +46,6 @@ public interface MessageSerializer {
*/
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
*/
diff --git a/core/src/main/java/org/bitcoinj/core/NetworkParameters.java b/core/src/main/java/org/bitcoinj/core/NetworkParameters.java
index 42c9e9f5..4f04f516 100644
--- a/core/src/main/java/org/bitcoinj/core/NetworkParameters.java
+++ b/core/src/main/java/org/bitcoinj/core/NetworkParameters.java
@@ -439,7 +439,7 @@ public abstract class NetworkParameters {
// 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);
+ this.defaultSerializer = getSerializer(false);
}
}
}
@@ -449,7 +449,7 @@ public abstract class NetworkParameters {
/**
* Construct and return a custom serializer.
*/
- public abstract BitcoinSerializer getSerializer(boolean parseLazy, boolean parseRetain);
+ public abstract BitcoinSerializer getSerializer(boolean parseRetain);
/**
* The number of blocks in the last {@link getMajorityWindow()} blocks
diff --git a/core/src/main/java/org/bitcoinj/core/PartialMerkleTree.java b/core/src/main/java/org/bitcoinj/core/PartialMerkleTree.java
index bd2f868b..681e3067 100644
--- a/core/src/main/java/org/bitcoinj/core/PartialMerkleTree.java
+++ b/core/src/main/java/org/bitcoinj/core/PartialMerkleTree.java
@@ -1,6 +1,7 @@
/**
* Copyright 2012 The Bitcoin Developers
* Copyright 2012 Matt Corallo
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -109,7 +110,7 @@ public class PartialMerkleTree extends Message {
}
@Override
- void parse() throws ProtocolException {
+ protected void parse() throws ProtocolException {
transactionCount = (int)readUint32();
int nHashes = (int) readVarInt();
@@ -167,11 +168,6 @@ public class PartialMerkleTree extends Message {
return combineLeftRight(left.getBytes(), right.getBytes());
}
- @Override
- protected void parseLite() {
-
- }
-
// helper function to efficiently calculate the number of nodes at given height in the merkle tree
private static int getTreeWidth(int transactionCount, int height) {
return (transactionCount + (1 << height) - 1) >> height;
diff --git a/core/src/main/java/org/bitcoinj/core/PeerAddress.java b/core/src/main/java/org/bitcoinj/core/PeerAddress.java
index 771157e2..380305a6 100644
--- a/core/src/main/java/org/bitcoinj/core/PeerAddress.java
+++ b/core/src/main/java/org/bitcoinj/core/PeerAddress.java
@@ -1,5 +1,6 @@
/*
* Copyright 2011 Google Inc.
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,12 +64,8 @@ public class PeerAddress extends ChildMessage {
*/
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.
}
-
/**
* Construct a peer address from a memorized or hardcoded address.
*/
@@ -139,11 +136,6 @@ public class PeerAddress extends ChildMessage {
stream.write((byte) (0xFF & port));
}
- @Override
- protected void parseLite() {
- length = protocolVersion > 31402 ? MESSAGE_SIZE : MESSAGE_SIZE - 4;
- }
-
@Override
protected void parse() throws ProtocolException {
// Format of a serialized address:
@@ -163,22 +155,15 @@ public class PeerAddress extends ChildMessage {
throw new RuntimeException(e); // Cannot happen.
}
port = ((0xFF & payload[cursor++]) << 8) | (0xFF & payload[cursor++]);
- }
-
- @Override
- public int getMessageSize() {
// The 4 byte difference is the uint32 timestamp that was introduced in version 31402
length = protocolVersion > 31402 ? MESSAGE_SIZE : MESSAGE_SIZE - 4;
- return length;
}
public String getHostname() {
- maybeParse();
return hostname;
}
public InetAddress getAddr() {
- maybeParse();
return addr;
}
@@ -191,43 +176,33 @@ public class PeerAddress extends ChildMessage {
this.addr = addr;
}
-
public int getPort() {
- maybeParse();
return port;
}
-
public void setPort(int port) {
unCache();
this.port = port;
}
-
public BigInteger getServices() {
- maybeParse();
return services;
}
-
public void setServices(BigInteger services) {
unCache();
this.services = services;
}
-
public long getTime() {
- maybeParse();
return time;
}
-
public void setTime(long time) {
unCache();
this.time = time;
}
-
@Override
public String toString() {
if (hostname != null) {
diff --git a/core/src/main/java/org/bitcoinj/core/Ping.java b/core/src/main/java/org/bitcoinj/core/Ping.java
index b357daac..c7ea558e 100644
--- a/core/src/main/java/org/bitcoinj/core/Ping.java
+++ b/core/src/main/java/org/bitcoinj/core/Ping.java
@@ -1,5 +1,6 @@
/**
* Copyright 2011 Noa Resare
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,7 +52,7 @@ public class Ping extends Message {
}
@Override
- void parse() throws ProtocolException {
+ protected void parse() throws ProtocolException {
try {
nonce = readInt64();
hasNonce = true;
@@ -61,11 +62,6 @@ public class Ping extends Message {
length = hasNonce ? 8 : 0;
}
- @Override
- protected void parseLite() {
-
- }
-
public boolean hasNonce() {
return hasNonce;
}
diff --git a/core/src/main/java/org/bitcoinj/core/Pong.java b/core/src/main/java/org/bitcoinj/core/Pong.java
index 09147555..6335388d 100644
--- a/core/src/main/java/org/bitcoinj/core/Pong.java
+++ b/core/src/main/java/org/bitcoinj/core/Pong.java
@@ -1,5 +1,6 @@
/**
* Copyright 2012 Matt Corallo
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +39,7 @@ public class Pong extends Message {
}
@Override
- void parse() throws ProtocolException {
+ protected void parse() throws ProtocolException {
nonce = readInt64();
length = 8;
}
@@ -48,10 +49,6 @@ public class Pong extends Message {
Utils.int64ToByteStreamLE(nonce, stream);
}
- @Override
- protected void parseLite() {
- }
-
/** Returns the nonce sent by the remote peer. */
public long getNonce() {
return nonce;
diff --git a/core/src/main/java/org/bitcoinj/core/RejectMessage.java b/core/src/main/java/org/bitcoinj/core/RejectMessage.java
index 323637c6..f5a7e5df 100644
--- a/core/src/main/java/org/bitcoinj/core/RejectMessage.java
+++ b/core/src/main/java/org/bitcoinj/core/RejectMessage.java
@@ -1,5 +1,6 @@
/*
* Copyright 2013 Matt Corallo
+ * Copyright 2015 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,7 +83,7 @@ public class RejectMessage extends Message {
}
@Override
- protected void parseLite() throws ProtocolException {
+ protected void parse() throws ProtocolException {
message = readStr();
code = RejectCode.fromCode(readBytes(1)[0]);
reason = readStr();
@@ -91,12 +92,6 @@ public class RejectMessage extends Message {
length = cursor - offset;
}
- @Override
- public void parse() throws ProtocolException {
- if (length == UNKNOWN_LENGTH)
- parseLite();
- }
-
@Override
public void bitcoinSerializeToStream(OutputStream stream) throws IOException {
byte[] messageBytes = message.getBytes("UTF-8");
@@ -115,7 +110,6 @@ public class RejectMessage extends Message {
* Note that this is ENTIRELY UNTRUSTED and should be sanity-checked before it is printed or processed.
*/
public String getRejectedMessage() {
- ensureParsed();
return message;
}
@@ -123,7 +117,6 @@ public class RejectMessage extends Message {
* Provides the hash of the rejected object (if getRejectedMessage() is either "tx" or "block"), otherwise null.
*/
public Sha256Hash getRejectedObjectHash() {
- ensureParsed();
return messageHash;
}
diff --git a/core/src/main/java/org/bitcoinj/core/Transaction.java b/core/src/main/java/org/bitcoinj/core/Transaction.java
index 15b21ed1..ae20fb0a 100644
--- a/core/src/main/java/org/bitcoinj/core/Transaction.java
+++ b/core/src/main/java/org/bitcoinj/core/Transaction.java
@@ -201,7 +201,6 @@ public class Transaction 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.
@@ -253,7 +252,6 @@ public class Transaction extends ChildMessage {
* include spent outputs or not.
*/
Coin getValueSentToMe(TransactionBag transactionBag, boolean includeSpent) {
- maybeParse();
// This is tested in WalletTest.
Coin v = Coin.ZERO;
for (TransactionOutput o : outputs) {
@@ -357,7 +355,6 @@ public class Transaction extends ChildMessage {
* @return sum of the inputs that are spending coins with keys in the wallet
*/
public Coin getValueSentFromMe(TransactionBag wallet) throws ScriptException {
- maybeParse();
// This is tested in WalletTest.
Coin v = Coin.ZERO;
for (TransactionInput input : inputs) {
@@ -421,7 +418,6 @@ public class Transaction extends ChildMessage {
* Returns true if any of the outputs is marked as spent.
*/
public boolean isAnyOutputSpent() {
- maybeParse();
for (TransactionOutput output : outputs) {
if (!output.isAvailableForSpending())
return true;
@@ -434,7 +430,6 @@ public class Transaction extends ChildMessage {
* otherwise.
*/
public boolean isEveryOwnedOutputSpent(TransactionBag transactionBag) {
- maybeParse();
for (TransactionOutput output : outputs) {
if (output.isAvailableForSpending() && output.isMineOrWatched(transactionBag))
return false;
@@ -479,29 +474,6 @@ public class Transaction extends ChildMessage {
hash = null;
}
- @Override
- protected void parseLite() throws ProtocolException {
-
- //skip this if the length has been provided i.e. the tx is not part of a block
- 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.
- //This is due to the fact that transactions in the block's list do not include a
- //size header and inputs/outputs are also variable length due the contained
- //script so each must be instantiated so the scriptlength varint can be read
- //to calculate total length of the transaction.
- //We will still persist will this semi-light parsing because getting the lengths
- //of the various components gains us the ability to cache the backing bytearrays
- //so that only those subcomponents that have changed will need to be reserialized.
-
- //parse();
- //parsed = true;
- length = calcLength(payload, offset);
- cursor = offset + length;
- }
- }
-
protected static int calcLength(byte[] buf, int offset) {
VarInt varint;
// jump past version (uint32)
@@ -539,11 +511,7 @@ public class Transaction extends ChildMessage {
}
@Override
- void parse() throws ProtocolException {
-
- if (parsed)
- return;
-
+ protected void parse() throws ProtocolException {
cursor = offset;
version = readUint32();
@@ -579,7 +547,6 @@ public class Transaction extends ChildMessage {
public int getOptimalEncodingMessageSize() {
if (optimalEncodingMessageSize != 0)
return optimalEncodingMessageSize;
- maybeParse();
if (optimalEncodingMessageSize != 0)
return optimalEncodingMessageSize;
optimalEncodingMessageSize = getMessageSize();
@@ -610,7 +577,6 @@ public class Transaction extends ChildMessage {
* position in a block but by the data in the inputs.
*/
public boolean isCoinBase() {
- maybeParse();
return inputs.size() == 1 && inputs.get(0).isCoinBase();
}
@@ -1067,7 +1033,6 @@ public class Transaction extends ChildMessage {
* standard and won't be relayed or included in the memory pool either.
*/
public long getLockTime() {
- maybeParse();
return lockTime;
}
@@ -1098,19 +1063,16 @@ public class Transaction extends ChildMessage {
* @return the version
*/
public long getVersion() {
- maybeParse();
return version;
}
/** Returns an unmodifiable view of all inputs. */
public List getInputs() {
- maybeParse();
return Collections.unmodifiableList(inputs);
}
/** Returns an unmodifiable view of all outputs. */
public List getOutputs() {
- maybeParse();
return Collections.unmodifiableList(outputs);
}
@@ -1123,7 +1085,6 @@ public class Transaction extends ChildMessage {
* @return linked list of outputs relevant to the wallet in this transaction
*/
public List getWalletOutputs(TransactionBag transactionBag){
- maybeParse();
List walletOutputs = new LinkedList();
for (TransactionOutput o : outputs) {
if (!o.isMineOrWatched(transactionBag)) continue;
@@ -1135,19 +1096,16 @@ public class Transaction extends ChildMessage {
/** Randomly re-orders the transaction outputs: good for privacy */
public void shuffleOutputs() {
- maybeParse();
Collections.shuffle(outputs);
}
/** Same as getInputs().get(index). */
public TransactionInput getInput(long index) {
- maybeParse();
return inputs.get((int)index);
}
/** Same as getOutputs().get(index) */
public TransactionOutput getOutput(long index) {
- maybeParse();
return outputs.get((int)index);
}
@@ -1197,7 +1155,6 @@ public class Transaction extends ChildMessage {
* Gets the count of regular SigOps in this transactions
*/
public int getSigOpCount() throws ScriptException {
- maybeParse();
int sigOps = 0;
for (TransactionInput input : inputs)
sigOps += Script.getSigOpCount(input.getScriptBytes());
@@ -1223,7 +1180,6 @@ public class Transaction extends ChildMessage {
* @throws VerificationException
*/
public void verify() throws VerificationException {
- maybeParse();
if (inputs.size() == 0 || outputs.size() == 0)
throw new VerificationException.EmptyInputsOrOutputs();
if (this.getMessageSize() > Block.MAX_BLOCK_SIZE)
diff --git a/core/src/main/java/org/bitcoinj/core/TransactionInput.java b/core/src/main/java/org/bitcoinj/core/TransactionInput.java
index 1f99a7b6..23a7561b 100644
--- a/core/src/main/java/org/bitcoinj/core/TransactionInput.java
+++ b/core/src/main/java/org/bitcoinj/core/TransactionInput.java
@@ -25,7 +25,6 @@ import com.google.common.base.Objects;
import javax.annotation.Nullable;
import java.io.IOException;
-import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.Arrays;
@@ -126,18 +125,11 @@ public class TransactionInput extends ChildMessage {
}
@Override
- protected void parseLite() throws ProtocolException {
- int curs = cursor;
- int scriptLen = (int) readVarInt(36);
- length = cursor - offset + scriptLen + 4;
- cursor = curs;
- }
-
- @Override
- void parse() throws ProtocolException {
+ protected void parse() throws ProtocolException {
outpoint = new TransactionOutPoint(params, payload, cursor, this, serializer);
cursor += outpoint.getMessageSize();
int scriptLen = (int) readVarInt();
+ length = cursor - offset + scriptLen + 4;
scriptBytes = readBytes(scriptLen);
sequence = readUint32();
}
@@ -154,7 +146,6 @@ public class TransactionInput extends ChildMessage {
* Coinbase transactions have special inputs with hashes of zero. If this is such an input, returns true.
*/
public boolean isCoinBase() {
- maybeParse();
return outpoint.getHash().equals(Sha256Hash.ZERO_HASH) &&
(outpoint.getIndex() & 0xFFFFFFFFL) == 0xFFFFFFFFL; // -1 but all is serialized to the wire as unsigned int.
}
@@ -168,7 +159,6 @@ public class TransactionInput extends ChildMessage {
// parameter is overloaded to be something totally different.
Script script = scriptSig == null ? null : scriptSig.get();
if (script == null) {
- maybeParse();
script = new Script(scriptBytes);
scriptSig = new WeakReference