mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-02-22 22:25:41 +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
179fb049fa
commit
85d9d3e881
1 changed files with 59 additions and 16 deletions
|
@ -221,6 +221,10 @@ public class Transaction extends BaseMessage {
|
|||
@Nullable
|
||||
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.
|
||||
*
|
||||
|
@ -323,17 +327,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.
|
||||
*
|
||||
* @return transaction ID
|
||||
*/
|
||||
public Sha256Hash getTxId() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
bitcoinSerializeToStream(baos, false);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e); // cannot happen
|
||||
if (cachedTxId == null) {
|
||||
if (!hasWitnesses() && cachedWTxId != null) {
|
||||
cachedTxId = cachedWTxId;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -345,17 +358,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()}.
|
||||
*
|
||||
* @return witness transaction ID
|
||||
*/
|
||||
public Sha256Hash getWTxId() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
bitcoinSerializeToStream(baos, hasWitnesses());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e); // cannot happen
|
||||
if (cachedWTxId == null) {
|
||||
if (!hasWitnesses() && cachedTxId != null) {
|
||||
cachedWTxId = cachedTxId;
|
||||
} else {
|
||||
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. */
|
||||
|
@ -621,6 +649,7 @@ public class Transaction extends BaseMessage {
|
|||
for (long i = 0; i < numInputs; i++) {
|
||||
inputs.add(TransactionInput.read(payload, this));
|
||||
}
|
||||
invalidateCachedTxIds();
|
||||
}
|
||||
|
||||
private void readOutputs(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
|
@ -631,6 +660,7 @@ public class Transaction extends BaseMessage {
|
|||
for (long i = 0; i < numOutputs; i++) {
|
||||
outputs.add(TransactionOutput.read(payload, this));
|
||||
}
|
||||
invalidateCachedTxIds();
|
||||
}
|
||||
|
||||
private void readWitnesses(ByteBuffer payload) throws BufferUnderflowException, ProtocolException {
|
||||
|
@ -842,6 +872,7 @@ public class Transaction extends BaseMessage {
|
|||
input.setParent(null);
|
||||
}
|
||||
inputs.clear();
|
||||
invalidateCachedTxIds();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -852,7 +883,9 @@ public class Transaction extends BaseMessage {
|
|||
* @return the newly created input.
|
||||
*/
|
||||
public TransactionInput addInput(TransactionOutput from) {
|
||||
return addInput(new TransactionInput(this, from));
|
||||
TransactionInput input = addInput(new TransactionInput(this, from));
|
||||
invalidateCachedTxIds();
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -862,6 +895,7 @@ public class Transaction extends BaseMessage {
|
|||
public TransactionInput addInput(TransactionInput input) {
|
||||
input.setParent(this);
|
||||
inputs.add(input);
|
||||
invalidateCachedTxIds();
|
||||
return input;
|
||||
}
|
||||
|
||||
|
@ -870,7 +904,10 @@ public class Transaction extends BaseMessage {
|
|||
* @return the newly created input.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1007,6 +1044,7 @@ public class Transaction extends BaseMessage {
|
|||
oldInput.setParent(null);
|
||||
input.setParent(this);
|
||||
inputs.add(index, input);
|
||||
invalidateCachedTxIds();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1018,6 +1056,7 @@ public class Transaction extends BaseMessage {
|
|||
output.setParent(null);
|
||||
}
|
||||
outputs.clear();
|
||||
invalidateCachedTxIds();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1026,6 +1065,7 @@ public class Transaction extends BaseMessage {
|
|||
public TransactionOutput addOutput(TransactionOutput to) {
|
||||
to.setParent(this);
|
||||
outputs.add(to);
|
||||
invalidateCachedTxIds();
|
||||
return to;
|
||||
}
|
||||
|
||||
|
@ -1042,6 +1082,7 @@ public class Transaction extends BaseMessage {
|
|||
oldOutput.setParent(null);
|
||||
output.setParent(this);
|
||||
outputs.add(index, output);
|
||||
invalidateCachedTxIds();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1527,6 +1568,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!");
|
||||
}
|
||||
this.vLockTime = LockTime.of(lockTime);
|
||||
invalidateCachedTxIds();
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
|
@ -1535,6 +1577,7 @@ public class Transaction extends BaseMessage {
|
|||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
invalidateCachedTxIds();
|
||||
}
|
||||
|
||||
/** Returns an unmodifiable view of all inputs. */
|
||||
|
|
Loading…
Add table
Reference in a new issue