// NewTxDeepTxIns is used to deep copy a transaction, maintaining the old // pointers to the TxOuts while replacing the old pointers to the TxIns with // deep copies. This is to prevent races when the fraud proofs for the // transactions are set by the miner. func NewTxDeepTxIns(msgTx *wire.MsgTx) *Tx { if msgTx == nil { return nil } newMsgTx := new(wire.MsgTx) // Copy the fixed fields. newMsgTx.Version = msgTx.Version newMsgTx.LockTime = msgTx.LockTime newMsgTx.Expiry = msgTx.Expiry // Copy the TxIns deeply. for _, txIn := range msgTx.TxIn { sigScrLen := len(txIn.SignatureScript) sigScrCopy := make([]byte, sigScrLen, sigScrLen) txInCopy := new(wire.TxIn) txInCopy.PreviousOutPoint.Hash = txIn.PreviousOutPoint.Hash txInCopy.PreviousOutPoint.Index = txIn.PreviousOutPoint.Index txInCopy.PreviousOutPoint.Tree = txIn.PreviousOutPoint.Tree txInCopy.Sequence = txIn.Sequence txInCopy.ValueIn = txIn.ValueIn txInCopy.BlockHeight = txIn.BlockHeight txInCopy.BlockIndex = txIn.BlockIndex txInCopy.SignatureScript = sigScrCopy newMsgTx.AddTxIn(txIn) } // Shallow copy the TxOuts. for _, txOut := range msgTx.TxOut { newMsgTx.AddTxOut(txOut) } return &Tx{ hash: msgTx.TxHash(), msgTx: msgTx, txTree: wire.TxTreeUnknown, txIndex: TxIndexUnknown, } }
// TestCalcSignatureHash does some rudimentary testing of msg hash calculation. func TestCalcSignatureHash(t *testing.T) { tx := new(wire.MsgTx) for i := 0; i < 3; i++ { txIn := new(wire.TxIn) txIn.Sequence = 0xFFFFFFFF txIn.PreviousOutPoint.Hash = chainhash.HashFuncH([]byte{byte(i)}) txIn.PreviousOutPoint.Index = uint32(i) txIn.PreviousOutPoint.Tree = int8(0) tx.AddTxIn(txIn) } for i := 0; i < 2; i++ { txOut := new(wire.TxOut) txOut.PkScript = []byte{0x01, 0x01, 0x02, 0x03} txOut.Value = 0x0000FF00FF00FF00 tx.AddTxOut(txOut) } want, _ := hex.DecodeString("d09285b6f60c71329323bc2e76c48" + "a462cde4e1032aa8f59c55823f1722c7f4a") pops, _ := txscript.TstParseScript([]byte{0x01, 0x01, 0x02, 0x03}) // Test prefix caching. msg1, err := txscript.CalcSignatureHash(pops, txscript.SigHashAll, tx, 0, nil) if err != nil { t.Fatalf("unexpected error %v", err.Error()) } prefixHash := tx.TxSha() msg2, err := txscript.CalcSignatureHash(pops, txscript.SigHashAll, tx, 0, &prefixHash) if err != nil { t.Fatalf("unexpected error %v", err.Error()) } if !bytes.Equal(msg1, want) { t.Errorf("for sighash all sig noncached wrong msg %x given, want %x", msg1, want) } if !bytes.Equal(msg2, want) { t.Errorf("for sighash all sig cached wrong msg %x given, want %x", msg1, want) } if !bytes.Equal(msg1, msg2) { t.Errorf("for sighash all sig non-equivalent msgs %x and %x were "+ "returned when using a cached prefix", msg1, msg2) } // Move the index and make sure that we get a whole new hash, despite // using the same TxOuts. msg3, err := txscript.CalcSignatureHash(pops, txscript.SigHashAll, tx, 1, &prefixHash) if err != nil { t.Fatalf("unexpected error %v", err.Error()) } if bytes.Equal(msg1, msg3) { t.Errorf("for sighash all sig equivalent msgs %x and %x were "+ "returned when using a cached prefix but different indices", msg1, msg3) } }