Example #1
0
// NewTx returns a new instance of a transaction given an underlying
// wire.MsgTx.  See Tx.
func NewTx(msgTx *wire.MsgTx) *Tx {
	return &Tx{
		hash:    msgTx.TxSha(),
		msgTx:   msgTx,
		txTree:  TxTreeUnknown,
		txIndex: TxIndexUnknown,
	}
}
Example #2
0
// NewTxFromReader returns a new instance of a transaction given a
// Reader to deserialize the transaction.  See Tx.
func NewTxFromReader(r io.Reader) (*Tx, error) {
	// Deserialize the bytes into a MsgTx.
	var msgTx wire.MsgTx
	err := msgTx.Deserialize(r)
	if err != nil {
		return nil, err
	}

	t := Tx{
		hash:    msgTx.TxSha(),
		msgTx:   &msgTx,
		txTree:  TxTreeUnknown,
		txIndex: TxIndexUnknown,
	}

	return &t, nil
}
Example #3
0
// 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.TxSha(),
		msgTx:   msgTx,
		txTree:  TxTreeUnknown,
		txIndex: TxIndexUnknown,
	}
}
Example #4
0
				0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */
				0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */
				0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */
				0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */
				0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */
				0x1d, 0x5f, 0xac, /* |._.| */
			},
		},
	},
	LockTime: 0,
	Expiry:   0,
}

// testNetGenesisMerkleRoot is the hash of the first transaction in the genesis block
// for the test network.
var testNetGenesisMerkleRoot = genesisCoinbaseTxLegacy.TxSha()

// testNetGenesisBlock defines the genesis block of the block chain which
// serves as the public transaction ledger for the test network (version 3).
var testNetGenesisBlock = wire.MsgBlock{
	Header: wire.BlockHeader{
		Version:    1,
		PrevBlock:  chainhash.Hash{},
		MerkleRoot: testNetGenesisMerkleRoot,
		Timestamp:  time.Unix(1453908222, 0), // 2016-01-27 TestNet9
		Bits:       0x1e00ffff,
		SBits:      20000000,
		Nonce:      0x18aea41a,
	},
	Transactions: []*wire.MsgTx{&genesisCoinbaseTxLegacy},
}
Example #5
0
func TestStakeInvalidationTxInsert(t *testing.T) {
	db, s, teardown, err := setup()
	defer teardown()
	if err != nil {
		t.Fatal(err)
	}

	g := makeBlockGenerator()
	block1Header := g.generate(dcrutil.BlockValid)
	block2Header := g.generate(dcrutil.BlockValid)
	block3Header := g.generate(0)

	block1Tx := wire.MsgTx{
		TxOut: []*wire.TxOut{{Value: 2e8}},
	}
	block2Tx := wire.MsgTx{
		TxIn: []*wire.TxIn{
			{PreviousOutPoint: wire.OutPoint{Hash: block1Tx.TxSha(), Index: 0, Tree: 0}},
		},
		TxOut: []*wire.TxOut{{Value: 1e8}},
	}
	block1TxRec, err := NewTxRecordFromMsgTx(&block1Tx, time.Time{})
	if err != nil {
		t.Fatal(err)
	}
	block2TxRec, err := NewTxRecordFromMsgTx(&block2Tx, time.Time{})
	if err != nil {
		t.Fatal(err)
	}

	err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error {
		ns := tx.ReadWriteBucket(wtxmgrNamespaceKey)
		addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)

		headerData := makeHeaderDataSlice(block1Header, block2Header, block3Header)
		err = s.InsertMainChainHeaders(ns, addrmgrNs, headerData)
		if err != nil {
			return err
		}

		err = s.InsertMinedTx(ns, addrmgrNs, block1TxRec, &headerData[0].BlockHash)
		if err != nil {
			return err
		}
		err = s.AddCredit(ns, block1TxRec, makeBlockMeta(block1Header), 0, false, 0)
		if err != nil {
			return err
		}
		err = s.InsertMinedTx(ns, addrmgrNs, block2TxRec, &headerData[1].BlockHash)
		if err != nil {
			return err
		}
		err = s.AddCredit(ns, block2TxRec, makeBlockMeta(block2Header), 0, false, 0)
		if err != nil {
			return err
		}

		// The transaction in block 2 was inserted invalidated.  There should
		// only be one unspent output, from block 1.
		bal, err := s.Balance(ns, addrmgrNs, 1, BFBalanceFullScan, true, 0)
		if err != nil {
			return err
		}
		if bal != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Wrong balance: expected %v got %v", dcrutil.Amount(block1Tx.TxOut[0].Value), bal)
		}
		bal, err = s.Balance(ns, addrmgrNs, 1, BFBalanceSpendable, true, 0)
		if err != nil {
			return err
		}
		if bal != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Wrong balance: expected %v got %v", dcrutil.Amount(block1Tx.TxOut[0].Value), bal)
		}
		credits, err := s.UnspentOutputs(ns)
		if err != nil {
			return err
		}
		if len(credits) != 1 {
			t.Errorf("Expected only 1 credit, got %v", len(credits))
			return nil
		}
		if credits[0].Hash != block1Tx.TxSha() {
			t.Errorf("Credit hash does not match tx from block 1")
			return nil
		}
		if credits[0].Amount != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Credit value does not match tx output 0 from block 1")
			return nil
		}

		return nil
	})
	if err != nil {
		t.Error(err)
	}
}
Example #6
0
func TestStakeInvalidationOfTip(t *testing.T) {
	db, s, teardown, err := setup()
	defer teardown()
	if err != nil {
		t.Fatal(err)
	}

	g := makeBlockGenerator()
	block1Header := g.generate(dcrutil.BlockValid)
	block2Header := g.generate(dcrutil.BlockValid)
	block3Header := g.generate(0)

	block1Tx := wire.MsgTx{
		TxOut: []*wire.TxOut{{Value: 2e8}},
	}
	block2Tx := wire.MsgTx{
		TxIn: []*wire.TxIn{
			{PreviousOutPoint: wire.OutPoint{Hash: block1Tx.TxSha(), Index: 0, Tree: 0}},
		},
		TxOut: []*wire.TxOut{{Value: 1e8}},
	}
	block1TxRec, err := NewTxRecordFromMsgTx(&block1Tx, time.Time{})
	if err != nil {
		t.Fatal(err)
	}
	block2TxRec, err := NewTxRecordFromMsgTx(&block2Tx, time.Time{})
	if err != nil {
		t.Fatal(err)
	}

	const balanceFlag = BFBalanceSpendable

	err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error {
		ns := tx.ReadWriteBucket(wtxmgrNamespaceKey)
		addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)

		err := s.InsertMemPoolTx(ns, block1TxRec)
		if err != nil {
			return err
		}
		err = s.AddCredit(ns, block1TxRec, nil, 0, false, 0)
		if err != nil {
			return err
		}
		err = s.InsertMemPoolTx(ns, block2TxRec)
		if err != nil {
			return err
		}
		err = s.AddCredit(ns, block2TxRec, nil, 0, false, 0)
		if err != nil {
			return err
		}

		bal, err := s.Balance(ns, addrmgrNs, 0, balanceFlag, false, 0)
		if err != nil {
			return err
		}
		if bal != 1e8 {
			t.Errorf("Wrong balance before mining either transaction: %v", bal)
		}

		headerData := makeHeaderDataSlice(block1Header, block2Header)
		err = s.InsertMainChainHeaders(ns, addrmgrNs, headerData)
		if err != nil {
			return err
		}

		err = s.InsertMinedTx(ns, addrmgrNs, block1TxRec, &headerData[0].BlockHash)
		if err != nil {
			return err
		}
		err = s.InsertMinedTx(ns, addrmgrNs, block2TxRec, &headerData[1].BlockHash)
		if err != nil {
			return err
		}

		// At this point there should only be one credit for the tx in block 2.
		bal, err = s.Balance(ns, addrmgrNs, 1, balanceFlag, false, 0)
		if err != nil {
			return err
		}
		if bal != dcrutil.Amount(block2Tx.TxOut[0].Value) {
			t.Errorf("Wrong balance: expected %v got %v", dcrutil.Amount(block2Tx.TxOut[0].Value), bal)
		}
		credits, err := s.UnspentOutputs(ns)
		if err != nil {
			return err
		}
		if len(credits) != 1 {
			t.Errorf("Expected only 1 credit, got %v", len(credits))
			return nil
		}
		if credits[0].Hash != block2Tx.TxSha() {
			t.Errorf("Credit hash does match tx from block 2")
			return nil
		}
		if credits[0].Amount != dcrutil.Amount(block2Tx.TxOut[0].Value) {
			t.Errorf("Credit value does not match tx output 0 from block 2")
			return nil
		}

		// Add the next block header which invalidates the regular tx tree of
		// block 2.
		t.Log("Invalidating block 2")
		headerData = makeHeaderDataSlice(block3Header)
		err = s.InsertMainChainHeaders(ns, addrmgrNs, headerData)
		if err != nil {
			return err
		}
		/*
			d := makeHeaderData(block3Header)
			err = s.ExtendMainChain(ns, &d)
			if err != nil {
				return err
			}
		*/

		// Now the transaction in block 2 is invalidated.  There should only be
		// one unspent output, from block 1.
		bal, err = s.Balance(ns, addrmgrNs, 1, balanceFlag, false, 0)
		if err != nil {
			return err
		}
		if bal != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Wrong balance: expected %v got %v", dcrutil.Amount(block1Tx.TxOut[0].Value), bal)
		}
		credits, err = s.UnspentOutputs(ns)
		if err != nil {
			return err
		}
		if len(credits) != 1 {
			t.Errorf("Expected only 1 credit, got %v", len(credits))
			return nil
		}
		if credits[0].Hash != block1Tx.TxSha() {
			t.Errorf("Credit hash does not match tx from block 1")
			return nil
		}
		if credits[0].Amount != dcrutil.Amount(block1Tx.TxOut[0].Value) {
			t.Errorf("Credit value does not match tx output 0 from block 1")
			return nil
		}

		return nil
	})
	if err != nil {
		t.Error(err)
	}
}
Example #7
0
// DebugMsgTxString dumps a verbose message containing information about the
// contents of a transaction.
func DebugMsgTxString(msgTx *wire.MsgTx) string {
	tx := dcrutil.NewTx(msgTx)
	isSStx, _ := stake.IsSStx(tx)
	isSSGen, _ := stake.IsSSGen(tx)
	var sstxType []bool
	var sstxPkhs [][]byte
	var sstxAmts []int64
	var sstxRules [][]bool
	var sstxLimits [][]uint16

	if isSStx {
		sstxType, sstxPkhs, sstxAmts, _, sstxRules, sstxLimits =
			stake.GetSStxStakeOutputInfo(tx)
	}

	var buffer bytes.Buffer

	hash := msgTx.TxSha()
	str := fmt.Sprintf("Transaction hash: %v, Version %v, Locktime: %v, "+
		"Expiry %v\n\n", hash, msgTx.Version, msgTx.LockTime, msgTx.Expiry)
	buffer.WriteString(str)

	str = fmt.Sprintf("==INPUTS==\nNumber of inputs: %v\n\n",
		len(msgTx.TxIn))
	buffer.WriteString(str)

	for i, input := range msgTx.TxIn {
		str = fmt.Sprintf("Input number: %v\n", i)
		buffer.WriteString(str)

		str = fmt.Sprintf("Previous outpoint hash: %v, ",
			input.PreviousOutPoint.Hash)
		buffer.WriteString(str)

		str = fmt.Sprintf("Previous outpoint index: %v, ",
			input.PreviousOutPoint.Index)
		buffer.WriteString(str)

		str = fmt.Sprintf("Previous outpoint tree: %v \n",
			input.PreviousOutPoint.Tree)
		buffer.WriteString(str)

		str = fmt.Sprintf("Sequence: %v \n",
			input.Sequence)
		buffer.WriteString(str)

		str = fmt.Sprintf("ValueIn: %v \n",
			input.ValueIn)
		buffer.WriteString(str)

		str = fmt.Sprintf("BlockHeight: %v \n",
			input.BlockHeight)
		buffer.WriteString(str)

		str = fmt.Sprintf("BlockIndex: %v \n",
			input.BlockIndex)
		buffer.WriteString(str)

		str = fmt.Sprintf("Raw signature script: %x \n", input.SignatureScript)
		buffer.WriteString(str)

		sigScr, _ := txscript.DisasmString(input.SignatureScript)
		str = fmt.Sprintf("Disasmed signature script: %v \n\n",
			sigScr)
		buffer.WriteString(str)
	}

	str = fmt.Sprintf("==OUTPUTS==\nNumber of outputs: %v\n\n",
		len(msgTx.TxOut))
	buffer.WriteString(str)

	for i, output := range msgTx.TxOut {
		str = fmt.Sprintf("Output number: %v\n", i)
		buffer.WriteString(str)

		coins := float64(output.Value) / 1e8
		str = fmt.Sprintf("Output amount: %v atoms or %v coins\n", output.Value,
			coins)
		buffer.WriteString(str)

		// SStx OP_RETURNs, dump pkhs and amts committed
		if isSStx && i != 0 && i%2 == 1 {
			coins := float64(sstxAmts[i/2]) / 1e8
			str = fmt.Sprintf("SStx commit amount: %v atoms or %v coins\n",
				sstxAmts[i/2], coins)
			buffer.WriteString(str)
			str = fmt.Sprintf("SStx commit address: %x\n",
				sstxPkhs[i/2])
			buffer.WriteString(str)
			str = fmt.Sprintf("SStx address type is P2SH: %v\n",
				sstxType[i/2])
			buffer.WriteString(str)

			str = fmt.Sprintf("SStx all address types is P2SH: %v\n",
				sstxType)
			buffer.WriteString(str)

			str = fmt.Sprintf("Voting is fee limited: %v\n",
				sstxLimits[i/2][0])
			buffer.WriteString(str)
			if sstxRules[i/2][0] {
				str = fmt.Sprintf("Voting limit imposed: %v\n",
					sstxLimits[i/2][0])
				buffer.WriteString(str)
			}

			str = fmt.Sprintf("Revoking is fee limited: %v\n",
				sstxRules[i/2][1])
			buffer.WriteString(str)

			if sstxRules[i/2][1] {
				str = fmt.Sprintf("Voting limit imposed: %v\n",
					sstxLimits[i/2][1])
				buffer.WriteString(str)
			}
		}

		// SSGen block/block height OP_RETURN.
		if isSSGen && i == 0 {
			blkHash, blkHeight, _ := stake.GetSSGenBlockVotedOn(tx)
			str = fmt.Sprintf("SSGen block hash voted on: %v, height: %v\n",
				blkHash, blkHeight)
			buffer.WriteString(str)
		}

		if isSSGen && i == 1 {
			vb := stake.GetSSGenVoteBits(tx)
			str = fmt.Sprintf("SSGen vote bits: %v\n", vb)
			buffer.WriteString(str)
		}

		str = fmt.Sprintf("Raw script: %x \n", output.PkScript)
		buffer.WriteString(str)

		scr, _ := txscript.DisasmString(output.PkScript)
		str = fmt.Sprintf("Disasmed script: %v \n\n", scr)
		buffer.WriteString(str)
	}

	return buffer.String()
}
Example #8
0
				0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, /* |..yb...a| */
				0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, /* |..I..?L.| */
				0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, /* |8..U....| */
				0x12, 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, /* |..\8M...| */
				0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, /* |.W.Lp+k.| */
				0x1d, 0x5f, 0xac, /* |._.| */
			},
		},
	},
	LockTime: 0,
	Expiry:   0,
}

// genesisMerkleRoot is the hash of the first transaction in the genesis block
// for the main network.
var genesisMerkleRoot = genesisCoinbaseTxLegacy.TxSha()

var regTestGenesisCoinbaseTx = wire.MsgTx{
	Version: 1,
	TxIn: []*wire.TxIn{
		{
			PreviousOutPoint: wire.OutPoint{
				Hash:  chainhash.Hash{},
				Index: 0xffffffff,
			},
			SignatureScript: []byte{
				0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, /* |.......E| */
				0x54, 0x68, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, /* |The Time| */
				0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, 0x61, 0x6e, /* |s 03/Jan| */
				0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, /* |/2009 Ch| */
				0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, /* |ancellor| */
Example #9
0
// loadTxStore returns a transaction store loaded from a file.
func loadTxStore(filename string) (blockchain.TxStore, error) {
	// The txstore file format is:
	// <num tx data entries> <tx length> <serialized tx> <blk height>
	// <num spent bits> <spent bits>
	//
	// All num and length fields are little-endian uint32s.  The spent bits
	// field is padded to a byte boundary.

	filename = filepath.Join("testdata/", filename)
	fi, err := os.Open(filename)
	if err != nil {
		return nil, err
	}

	// Choose read based on whether the file is compressed or not.
	var r io.Reader
	if strings.HasSuffix(filename, ".bz2") {
		r = bzip2.NewReader(fi)
	} else {
		r = fi
	}
	defer fi.Close()

	// Num of transaction store objects.
	var numItems uint32
	if err := binary.Read(r, binary.LittleEndian, &numItems); err != nil {
		return nil, err
	}

	txStore := make(blockchain.TxStore)
	var uintBuf uint32
	for height := uint32(0); height < numItems; height++ {
		txD := blockchain.TxData{}

		// Serialized transaction length.
		err = binary.Read(r, binary.LittleEndian, &uintBuf)
		if err != nil {
			return nil, err
		}
		serializedTxLen := uintBuf
		if serializedTxLen > wire.MaxBlockPayload {
			return nil, fmt.Errorf("Read serialized transaction "+
				"length of %d is larger max allowed %d",
				serializedTxLen, wire.MaxBlockPayload)
		}

		// Transaction.
		var msgTx wire.MsgTx
		err = msgTx.Deserialize(r)
		if err != nil {
			return nil, err
		}
		txD.Tx = dcrutil.NewTx(&msgTx)

		// Transaction hash.
		txHash := msgTx.TxSha()
		txD.Hash = &txHash

		// Block height the transaction came from.
		err = binary.Read(r, binary.LittleEndian, &uintBuf)
		if err != nil {
			return nil, err
		}
		txD.BlockHeight = int64(uintBuf)

		// Num spent bits.
		err = binary.Read(r, binary.LittleEndian, &uintBuf)
		if err != nil {
			return nil, err
		}
		numSpentBits := uintBuf
		numSpentBytes := numSpentBits / 8
		if numSpentBits%8 != 0 {
			numSpentBytes++
		}

		// Packed spent bytes.
		spentBytes := make([]byte, numSpentBytes)
		_, err = io.ReadFull(r, spentBytes)
		if err != nil {
			return nil, err
		}

		// Populate spent data based on spent bits.
		txD.Spent = make([]bool, numSpentBits)
		for byteNum, spentByte := range spentBytes {
			for bit := 0; bit < 8; bit++ {
				if uint32((byteNum*8)+bit) < numSpentBits {
					if spentByte&(1<<uint(bit)) != 0 {
						txD.Spent[(byteNum*8)+bit] = true
					}
				}
			}
		}

		txStore[*txD.Hash] = &txD
	}

	return txStore, nil
}
Example #10
0
// 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)
	}
}