mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-03-15 04:11:51 +01:00
Transaction: cache transaction IDs
Without caching, transactions are serialized way too often.
This effectively reverts b8d3c4a641
, but
invalidation is slightly different.
This commit is contained in:
parent
2f7579d797
commit
e57e21cc98
1 changed files with 59 additions and 16 deletions
|
@ -222,6 +222,10 @@ public class Transaction extends BaseMessage {
|
||||||
@Nullable
|
@Nullable
|
||||||
private String memo;
|
private String memo;
|
||||||
|
|
||||||
|
// These are in memory helpers only. They contain the transaction hashes without and with witness.
|
||||||
|
private Sha256Hash cachedTxId;
|
||||||
|
private Sha256Hash cachedWTxId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an incomplete coinbase transaction with a minimal input script and no outputs.
|
* Constructs an incomplete coinbase transaction with a minimal input script and no outputs.
|
||||||
*
|
*
|
||||||
|
@ -330,17 +334,26 @@ public class Transaction extends BaseMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the transaction id as you see them in block explorers. It is used as a reference by transaction inputs
|
* Returns the transaction ID as you see them in block explorers. It is used as a reference by transaction inputs
|
||||||
* via outpoints.
|
* via outpoints.
|
||||||
|
*
|
||||||
|
* @return transaction ID
|
||||||
*/
|
*/
|
||||||
public Sha256Hash getTxId() {
|
public Sha256Hash getTxId() {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
if (cachedTxId == null) {
|
||||||
try {
|
if (!hasWitnesses() && cachedWTxId != null) {
|
||||||
bitcoinSerializeToStream(baos, false);
|
cachedTxId = cachedWTxId;
|
||||||
} catch (IOException e) {
|
} else {
|
||||||
throw new RuntimeException(e); // cannot happen
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
bitcoinSerializeToStream(baos, false);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e); // cannot happen
|
||||||
|
}
|
||||||
|
cachedTxId = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(baos.toByteArray()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Sha256Hash.wrapReversed(Sha256Hash.hashTwice(baos.toByteArray()));
|
return cachedTxId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -352,17 +365,32 @@ public class Transaction extends BaseMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the witness transaction id (aka witness id) as per BIP144. For transactions without witness, this is the
|
* Returns the witness transaction ID (aka witness ID) as per BIP144. For transactions without witness, this is the
|
||||||
* same as {@link #getTxId()}.
|
* same as {@link #getTxId()}.
|
||||||
|
*
|
||||||
|
* @return witness transaction ID
|
||||||
*/
|
*/
|
||||||
public Sha256Hash getWTxId() {
|
public Sha256Hash getWTxId() {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
if (cachedWTxId == null) {
|
||||||
try {
|
if (!hasWitnesses() && cachedTxId != null) {
|
||||||
bitcoinSerializeToStream(baos, hasWitnesses());
|
cachedWTxId = cachedTxId;
|
||||||
} catch (IOException e) {
|
} else {
|
||||||
throw new RuntimeException(e); // cannot happen
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
bitcoinSerializeToStream(baos, hasWitnesses());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e); // cannot happen
|
||||||
|
}
|
||||||
|
cachedWTxId = Sha256Hash.wrapReversed(Sha256Hash.hashTwice(baos.toByteArray()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Sha256Hash.wrapReversed(Sha256Hash.hashTwice(baos.toByteArray()));
|
return cachedWTxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** invalidates cache for both transaction IDs */
|
||||||
|
private void invalidateCachedTxIds() {
|
||||||
|
cachedTxId = null;
|
||||||
|
cachedWTxId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the transaction weight as defined in BIP141. */
|
/** Gets the transaction weight as defined in BIP141. */
|
||||||
|
@ -643,6 +671,7 @@ public class Transaction extends BaseMessage {
|
||||||
for (long i = 0; i < numInputs; i++) {
|
for (long i = 0; i < numInputs; i++) {
|
||||||
inputs.add(TransactionInput.read(payload, this));
|
inputs.add(TransactionInput.read(payload, this));
|
||||||
}
|
}
|
||||||
|
invalidateCachedTxIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readOutputs(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
private void readOutputs(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||||
|
@ -653,6 +682,7 @@ public class Transaction extends BaseMessage {
|
||||||
for (long i = 0; i < numOutputs; i++) {
|
for (long i = 0; i < numOutputs; i++) {
|
||||||
outputs.add(TransactionOutput.read(payload, this));
|
outputs.add(TransactionOutput.read(payload, this));
|
||||||
}
|
}
|
||||||
|
invalidateCachedTxIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readWitnesses(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
private void readWitnesses(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||||
|
@ -864,6 +894,7 @@ public class Transaction extends BaseMessage {
|
||||||
input.setParent(null);
|
input.setParent(null);
|
||||||
}
|
}
|
||||||
inputs.clear();
|
inputs.clear();
|
||||||
|
invalidateCachedTxIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -874,7 +905,9 @@ public class Transaction extends BaseMessage {
|
||||||
* @return the newly created input.
|
* @return the newly created input.
|
||||||
*/
|
*/
|
||||||
public TransactionInput addInput(TransactionOutput from) {
|
public TransactionInput addInput(TransactionOutput from) {
|
||||||
return addInput(new TransactionInput(this, from));
|
TransactionInput input = addInput(new TransactionInput(this, from));
|
||||||
|
invalidateCachedTxIds();
|
||||||
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -884,6 +917,7 @@ public class Transaction extends BaseMessage {
|
||||||
public TransactionInput addInput(TransactionInput input) {
|
public TransactionInput addInput(TransactionInput input) {
|
||||||
input.setParent(this);
|
input.setParent(this);
|
||||||
inputs.add(input);
|
inputs.add(input);
|
||||||
|
invalidateCachedTxIds();
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,7 +926,10 @@ public class Transaction extends BaseMessage {
|
||||||
* @return the newly created input.
|
* @return the newly created input.
|
||||||
*/
|
*/
|
||||||
public TransactionInput addInput(Sha256Hash spendTxHash, long outputIndex, Script script) {
|
public TransactionInput addInput(Sha256Hash spendTxHash, long outputIndex, Script script) {
|
||||||
return addInput(new TransactionInput(this, script.program(), new TransactionOutPoint(outputIndex, spendTxHash)));
|
TransactionInput input = addInput(new TransactionInput(this, script.program(),
|
||||||
|
new TransactionOutPoint(outputIndex, spendTxHash)));
|
||||||
|
invalidateCachedTxIds();
|
||||||
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1029,6 +1066,7 @@ public class Transaction extends BaseMessage {
|
||||||
oldInput.setParent(null);
|
oldInput.setParent(null);
|
||||||
input.setParent(this);
|
input.setParent(this);
|
||||||
inputs.add(index, input);
|
inputs.add(index, input);
|
||||||
|
invalidateCachedTxIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1040,6 +1078,7 @@ public class Transaction extends BaseMessage {
|
||||||
output.setParent(null);
|
output.setParent(null);
|
||||||
}
|
}
|
||||||
outputs.clear();
|
outputs.clear();
|
||||||
|
invalidateCachedTxIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1048,6 +1087,7 @@ public class Transaction extends BaseMessage {
|
||||||
public TransactionOutput addOutput(TransactionOutput to) {
|
public TransactionOutput addOutput(TransactionOutput to) {
|
||||||
to.setParent(this);
|
to.setParent(this);
|
||||||
outputs.add(to);
|
outputs.add(to);
|
||||||
|
invalidateCachedTxIds();
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1064,6 +1104,7 @@ public class Transaction extends BaseMessage {
|
||||||
oldOutput.setParent(null);
|
oldOutput.setParent(null);
|
||||||
output.setParent(this);
|
output.setParent(this);
|
||||||
outputs.add(index, output);
|
outputs.add(index, output);
|
||||||
|
invalidateCachedTxIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1549,6 +1590,7 @@ public class Transaction extends BaseMessage {
|
||||||
log.warn("You are setting the lock time on a transaction but none of the inputs have non-default sequence numbers. This will not do what you expect!");
|
log.warn("You are setting the lock time on a transaction but none of the inputs have non-default sequence numbers. This will not do what you expect!");
|
||||||
}
|
}
|
||||||
this.vLockTime = LockTime.of(lockTime);
|
this.vLockTime = LockTime.of(lockTime);
|
||||||
|
invalidateCachedTxIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getVersion() {
|
public long getVersion() {
|
||||||
|
@ -1557,6 +1599,7 @@ public class Transaction extends BaseMessage {
|
||||||
|
|
||||||
public void setVersion(int version) {
|
public void setVersion(int version) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
|
invalidateCachedTxIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns an unmodifiable view of all inputs. */
|
/** Returns an unmodifiable view of all inputs. */
|
||||||
|
|
Loading…
Add table
Reference in a new issue