Skip to content

Commit c254024

Browse files
committed
restore Clone, but encourage ShallowClone
1 parent e3fc117 commit c254024

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

script/interpreter/operations.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -2016,7 +2016,7 @@ func opcodeCheckSig(op *ParsedOpcode, t *thread) error {
20162016
return err
20172017
}
20182018

2019-
txCopy := t.tx.Clone()
2019+
txCopy := t.tx.ShallowClone()
20202020
sourceTxOut := txCopy.Inputs[t.inputIdx].SourceTxOutput()
20212021
sourceTxOut.LockingScript = up
20222022

@@ -2282,7 +2282,7 @@ func opcodeCheckMultiSig(op *ParsedOpcode, t *thread) error {
22822282
}
22832283

22842284
// Generate the signature hash based on the signature hash type.
2285-
txCopy := t.tx.Clone()
2285+
txCopy := t.tx.ShallowClone()
22862286
input := txCopy.Inputs[t.inputIdx]
22872287
sourceOut := input.SourceTxOutput()
22882288
if sourceOut != nil {

transaction/signaturehash.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func (tx *Transaction) CalcInputPreimageLegacy(inputNumber uint32, shf sighash.F
188188
return defaultHex, nil
189189
}
190190

191-
txCopy := tx.Clone()
191+
txCopy := tx.ShallowClone()
192192

193193
for i := range txCopy.Inputs {
194194
if i == int(inputNumber) {

transaction/transaction.go

+21
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/binary"
66
"encoding/hex"
77
"io"
8+
"log"
89
"slices"
910

1011
"github.com/bitcoin-sv/go-sdk/chainhash"
@@ -313,7 +314,27 @@ func (tx *Transaction) BytesWithClearedInputs(index int, lockingScript []byte) [
313314
return tx.toBytesHelper(index, lockingScript, false)
314315
}
315316

317+
// Clone returns a deep clone of the tx. Consider using ShallowClone if
318+
// you don't need to clone the source transactions.
316319
func (tx *Transaction) Clone() *Transaction {
320+
// Ignore err as byte slice passed in is created from valid tx
321+
clone, err := NewTransactionFromBytes(tx.Bytes())
322+
if err != nil {
323+
log.Fatal(err)
324+
}
325+
326+
for i, input := range tx.Inputs {
327+
if input.SourceTransaction != nil {
328+
clone.Inputs[i].SourceTransaction = input.SourceTransaction.Clone()
329+
}
330+
// clone.Inputs[i].SourceTransaction = input.SourceTransaction
331+
clone.Inputs[i].sourceOutput = input.sourceOutput
332+
}
333+
334+
return clone
335+
}
336+
337+
func (tx *Transaction) ShallowClone() *Transaction {
317338
// Creating a new Tx from scratch is much faster than cloning from bytes
318339
// ~ 420ns/op vs 2200ns/op of the above function in benchmarking
319340
// this matters as we clone txs a couple of times when verifying signatures

transaction/transaction_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func TestClone(t *testing.T) {
9898
tx, err := transaction.NewTransactionFromBEEFHex(BRC62Hex)
9999
require.NoError(t, err)
100100

101-
clone := tx.Clone()
101+
clone := tx.ShallowClone()
102102
require.Equal(t, tx.Bytes(), clone.Bytes())
103103
}
104104

@@ -107,7 +107,7 @@ func BenchmarkClone(b *testing.B) {
107107

108108
b.Run("clone", func(b *testing.B) {
109109
for i := 0; i < b.N; i++ {
110-
clone := tx.Clone()
110+
clone := tx.ShallowClone()
111111
_ = clone
112112
}
113113
})
@@ -132,7 +132,7 @@ func TestSignUnsigned(t *testing.T) {
132132
tx, err := transaction.NewTransactionFromBEEFHex(BRC62Hex)
133133
require.NoError(t, err)
134134

135-
cloneTx := tx.Clone()
135+
cloneTx := tx.ShallowClone()
136136
pk, _ := ec.NewPrivateKey()
137137

138138
// Adding a script template with random key so sigs will be different

0 commit comments

Comments
 (0)