Convert API to use new btcutil.Tx.

This is part of the ongoing transaction hash optimization effort noted in
conformal/btcd#25.
This commit is contained in:
Dave Collins 2013-10-28 15:17:53 -05:00
parent b6e4ae4441
commit 6165e9b95b
8 changed files with 83 additions and 129 deletions

View file

@ -60,16 +60,10 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block) error {
}
// Ensure all transactions in the block are finalized.
for i, tx := range block.MsgBlock().Transactions {
for _, tx := range block.Transactions() {
if !IsFinalizedTransaction(tx, blockHeight, blockHeader.Timestamp) {
// Use the TxSha function from the block rather
// than the transaction itself since the block version
// is cached. Also, it's safe to ignore the error here
// since the only reason TxSha can fail is if the index
// is out of range which is impossible here.
txSha, _ := block.TxSha(i)
str := fmt.Sprintf("block contains unfinalized "+
"transaction %v", txSha)
"transaction %v", tx.Sha())
return RuleError(str)
}
}
@ -129,7 +123,7 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block) error {
if prevNode != nil {
expectedHeight = prevNode.height + 1
}
coinbaseTx := block.MsgBlock().Transactions[0]
coinbaseTx := block.Transactions()[0]
err := checkSerializedHeight(coinbaseTx, expectedHeight)
if err != nil {
return err

View file

@ -154,11 +154,11 @@ func (b *BlockChain) findLatestKnownCheckpoint() (*btcutil.Block, error) {
// isNonstandardTransaction determines whether a transaction contains any
// scripts which are not one of the standard types.
func isNonstandardTransaction(tx *btcwire.MsgTx) bool {
func isNonstandardTransaction(tx *btcutil.Tx) bool {
// TODO(davec): Should there be checks for the input signature scripts?
// Check all of the output public key scripts for non-standard scripts.
for _, txOut := range tx.TxOut {
for _, txOut := range tx.MsgTx().TxOut {
scriptClass := btcscript.GetScriptClass(txOut.PkScript)
if scriptClass == btcscript.NonStandardTy {
return true
@ -235,7 +235,7 @@ func (b *BlockChain) IsCheckpointCandidate(block *btcutil.Block) (bool, error) {
// A checkpoint must have transactions that only contain standard
// scripts.
for _, tx := range block.MsgBlock().Transactions {
for _, tx := range block.Transactions() {
if isNonstandardTransaction(tx) {
return false, nil
}

View file

@ -13,7 +13,6 @@ package btcchain
import (
"github.com/conformal/btcutil"
"github.com/conformal/btcwire"
"time"
)
@ -37,6 +36,6 @@ func TstTimeSorter(times []time.Time) timeSorter {
// TstCheckSerializedHeight makes the internal checkSerializedHeight function
// available to the test package.
func TstCheckSerializedHeight(coinbaseTx *btcwire.MsgTx, wantHeight int64) error {
func TstCheckSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int64) error {
return checkSerializedHeight(coinbaseTx, wantHeight)
}

View file

@ -69,21 +69,15 @@ func hashMerkleBranches(left *btcwire.ShaHash, right *btcwire.ShaHash) *btcwire.
// Since this function uses nodes that are pointers to the hashes, empty nodes
// will be nil.
func BuildMerkleTreeStore(block *btcutil.Block) []*btcwire.ShaHash {
numTransactions := len(block.MsgBlock().Transactions)
// Calculate how many entries are required to hold the binary merkle
// tree as a linear array and create an array of that size.
nextPoT := nextPowerOfTwo(numTransactions)
nextPoT := nextPowerOfTwo(len(block.Transactions()))
arraySize := nextPoT*2 - 1
merkles := make([]*btcwire.ShaHash, arraySize)
// Create the base transaction shas and populate the array with them.
for i := 0; i < numTransactions; i++ {
// Ignore the error since the only reason TxSha can fail is
// if the index is out of range which is impossible here due
// to using a loop over the existing transactions.
sha, _ := block.TxSha(i)
merkles[i] = sha
for i, tx := range block.Transactions() {
merkles[i] = tx.Sha()
}
// Start the array offset after the last transaction and adjusted to the

View file

@ -19,16 +19,10 @@ type txValidate struct {
err error
}
// txProcessList
type txProcessList struct {
txsha btcwire.ShaHash
tx *btcwire.MsgTx
}
// validateTxIn validates a the script pair for the passed spending transaction
// (along with the specific input index) and origin transaction (with the
// specific output index).
func validateTxIn(txInIdx int, txin *btcwire.TxIn, txSha *btcwire.ShaHash, tx *btcwire.MsgTx, originTx *btcwire.MsgTx, flags btcscript.ScriptFlags) error {
func validateTxIn(txInIdx int, txin *btcwire.TxIn, tx *btcutil.Tx, originTx *btcutil.Tx, flags btcscript.ScriptFlags) error {
// If the input transaction has no previous input, there is nothing
// to check.
originTxIdx := txin.PreviousOutpoint.Index
@ -36,17 +30,17 @@ func validateTxIn(txInIdx int, txin *btcwire.TxIn, txSha *btcwire.ShaHash, tx *b
return nil
}
if originTxIdx >= uint32(len(originTx.TxOut)) {
if originTxIdx >= uint32(len(originTx.MsgTx().TxOut)) {
originTxSha := &txin.PreviousOutpoint.Hash
log.Warnf("unable to locate source tx %v spending tx %v",
originTxSha, &txSha)
originTxSha, tx.Sha())
return fmt.Errorf("invalid index %x", originTxIdx)
}
sigScript := txin.SignatureScript
pkScript := originTx.TxOut[originTxIdx].PkScript
engine, err := btcscript.NewScript(sigScript, pkScript, txInIdx, tx,
flags)
pkScript := originTx.MsgTx().TxOut[originTxIdx].PkScript
engine, err := btcscript.NewScript(sigScript, pkScript, txInIdx,
tx.MsgTx(), flags)
if err != nil {
return err
}
@ -62,9 +56,9 @@ func validateTxIn(txInIdx int, txin *btcwire.TxIn, txSha *btcwire.ShaHash, tx *b
// ValidateTransactionScripts validates the scripts for the passed transaction
// using multiple goroutines.
func ValidateTransactionScripts(tx *btcwire.MsgTx, txHash *btcwire.ShaHash, txStore TxStore, flags btcscript.ScriptFlags) (err error) {
func ValidateTransactionScripts(tx *btcutil.Tx, txStore TxStore, flags btcscript.ScriptFlags) (err error) {
c := make(chan txValidate)
job := tx.TxIn
job := tx.MsgTx().TxIn
resultErrors := make([]error, len(job))
var currentItem int
@ -72,12 +66,12 @@ func ValidateTransactionScripts(tx *btcwire.MsgTx, txHash *btcwire.ShaHash, txSt
processFunc := func(txInIdx int) {
log.Tracef("validating tx %v input %v len %v",
txHash, currentItem, len(job))
tx.Sha(), currentItem, len(job))
txin := job[txInIdx]
originTxSha := &txin.PreviousOutpoint.Hash
origintxidx := txin.PreviousOutpoint.Index
var originTx *btcwire.MsgTx
var originTx *btcutil.Tx
if origintxidx != math.MaxUint32 {
txInfo, ok := txStore[*originTxSha]
if !ok {
@ -87,8 +81,7 @@ func ValidateTransactionScripts(tx *btcwire.MsgTx, txHash *btcwire.ShaHash, txSt
}
originTx = txInfo.Tx
}
err := validateTxIn(txInIdx, job[txInIdx], txHash, tx, originTx,
flags)
err := validateTxIn(txInIdx, txin, tx, originTx, flags)
r := txValidate{txInIdx, err}
c <- r
}
@ -114,7 +107,8 @@ func ValidateTransactionScripts(tx *btcwire.MsgTx, txHash *btcwire.ShaHash, txSt
}
for i := 0; i < len(job); i++ {
if resultErrors[i] != nil {
log.Warnf("tx %v failed input %v, err %v", txHash, i, resultErrors[i])
log.Warnf("tx %v failed input %v, err %v", tx.Sha(), i,
resultErrors[i])
}
}
return
@ -130,17 +124,14 @@ func checkBlockScripts(block *btcutil.Block, txStore TxStore) error {
flags |= btcscript.ScriptBip16
}
txList := block.MsgBlock().Transactions
txList := block.Transactions()
c := make(chan txValidate)
resultErrors := make([]error, len(txList))
var currentItem int
var completedItems int
processFunc := func(txIdx int) {
tx := txList[txIdx]
txHash, _ := block.TxSha(txIdx)
err := ValidateTransactionScripts(tx, txHash, txStore, flags)
err := ValidateTransactionScripts(txList[txIdx], txStore, flags)
r := txValidate{txIdx, err}
c <- r
}

View file

@ -14,7 +14,7 @@ import (
// TxData contains contextual information about transactions such as which block
// they were found in and whether or not the outputs are spent.
type TxData struct {
Tx *btcwire.MsgTx
Tx *btcutil.Tx
Hash *btcwire.ShaHash
BlockHeight int64
Spent []bool
@ -33,23 +33,19 @@ type TxStore map[btcwire.ShaHash]*TxData
func connectTransactions(txStore TxStore, block *btcutil.Block) error {
// Loop through all of the transactions in the block to see if any of
// them are ones we need to update and spend based on the results map.
for i, tx := range block.MsgBlock().Transactions {
txHash, err := block.TxSha(i)
if err != nil {
return err
}
for _, tx := range block.Transactions() {
// Update the transaction store with the transaction information
// if it's one of the requested transactions.
if txD, exists := txStore[*txHash]; exists {
msgTx := tx.MsgTx()
if txD, exists := txStore[*tx.Sha()]; exists {
txD.Tx = tx
txD.BlockHeight = block.Height()
txD.Spent = make([]bool, len(tx.TxOut))
txD.Spent = make([]bool, len(msgTx.TxOut))
txD.Err = nil
}
// Spend the origin transaction output.
for _, txIn := range tx.TxIn {
for _, txIn := range msgTx.TxIn {
originHash := &txIn.PreviousOutpoint.Hash
originIndex := txIn.PreviousOutpoint.Index
if originTx, exists := txStore[*originHash]; exists {
@ -67,18 +63,13 @@ func connectTransactions(txStore TxStore, block *btcutil.Block) error {
func disconnectTransactions(txStore TxStore, block *btcutil.Block) error {
// Loop through all of the transactions in the block to see if any of
// them are ones that need to be undone based on the transaction store.
for i, tx := range block.MsgBlock().Transactions {
txHash, err := block.TxSha(i)
if err != nil {
return err
}
for _, tx := range block.Transactions() {
// Clear this transaction from the transaction store if needed.
// Only clear it rather than deleting it because the transaction
// connect code relies on its presence to decide whether or not
// to update the store and any transactions which exist on both
// sides of a fork would otherwise not be updated.
if txD, exists := txStore[*txHash]; exists {
if txD, exists := txStore[*tx.Sha()]; exists {
txD.Tx = nil
txD.BlockHeight = 0
txD.Spent = nil
@ -86,7 +77,7 @@ func disconnectTransactions(txStore TxStore, block *btcutil.Block) error {
}
// Unspend the origin transaction output.
for _, txIn := range tx.TxIn {
for _, txIn := range tx.MsgTx().TxIn {
originHash := &txIn.PreviousOutpoint.Hash
originIndex := txIn.PreviousOutpoint.Index
originTx, exists := txStore[*originHash]
@ -146,7 +137,7 @@ func fetchTxStoreMain(db btcdb.Db, txSet map[btcwire.ShaHash]bool, includeSpent
// cause subtle errors, so avoid the potential altogether.
txD.Err = txReply.Err
if txReply.Err == nil {
txD.Tx = txReply.Tx
txD.Tx = btcutil.NewTx(txReply.Tx)
txD.BlockHeight = txReply.Height
txD.Spent = make([]bool, len(txReply.TxSpent))
copy(txD.Spent, txReply.TxSpent)
@ -240,14 +231,9 @@ func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Bloc
// this block could be referencing other transactions earlier in this
// block which are not yet in the chain.
txInFlight := map[btcwire.ShaHash]int{}
transactions := block.MsgBlock().Transactions
for i := range transactions {
// Get transaction hash. It's safe to ignore the error since
// it's already cached in the nominal code path and the only
// way it can fail is if the index is out of range which is
// impossible here.
txHash, _ := block.TxSha(i)
txInFlight[*txHash] = i
transactions := block.Transactions()
for i, tx := range transactions {
txInFlight[*tx.Sha()] = i
}
// Loop through all of the transaction inputs (except for the coinbase
@ -256,7 +242,7 @@ func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Bloc
txNeededSet := make(map[btcwire.ShaHash]bool)
txStore := make(TxStore)
for i, tx := range transactions[1:] {
for _, txIn := range tx.TxIn {
for _, txIn := range tx.MsgTx().TxIn {
// Add an entry to the transaction store for the needed
// transaction with it set to missing by default.
originHash := &txIn.PreviousOutpoint.Hash
@ -279,7 +265,7 @@ func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Bloc
originTx := transactions[inFlightIndex]
txD.Tx = originTx
txD.BlockHeight = node.height
txD.Spent = make([]bool, len(originTx.TxOut))
txD.Spent = make([]bool, len(originTx.MsgTx().TxOut))
txD.Err = nil
} else {
txNeededSet[*originHash] = true
@ -306,18 +292,13 @@ func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Bloc
// passed transaction from the point of view of the end of the main chain. It
// also attempts to fetch the transaction itself so the returned TxStore can be
// examined for duplicate transactions.
func (b *BlockChain) FetchTransactionStore(tx *btcwire.MsgTx) (TxStore, error) {
txHash, err := tx.TxSha()
if err != nil {
return nil, err
}
func (b *BlockChain) FetchTransactionStore(tx *btcutil.Tx) (TxStore, error) {
// Create a set of needed transactions from the transactions referenced
// by the inputs of the passed transaction. Also, add the passed
// transaction itself as a way for the caller to detect duplicates.
txNeededSet := make(map[btcwire.ShaHash]bool)
txNeededSet[txHash] = true
for _, txIn := range tx.TxIn {
txNeededSet[*tx.Sha()] = true
for _, txIn := range tx.MsgTx().TxIn {
txNeededSet[txIn.PreviousOutpoint.Hash] = true
}

View file

@ -94,7 +94,9 @@ func isNullOutpoint(outpoint *btcwire.OutPoint) bool {
// represented in the block chain by a transaction with a single input that has
// a previous output transaction index set to the maximum value along with a
// zero hash.
func IsCoinBase(msgTx *btcwire.MsgTx) bool {
func IsCoinBase(tx *btcutil.Tx) bool {
msgTx := tx.MsgTx()
// A coin base must only have one transaction input.
if len(msgTx.TxIn) != 1 {
return false
@ -111,7 +113,9 @@ func IsCoinBase(msgTx *btcwire.MsgTx) bool {
}
// IsFinalizedTransaction determines whether or not a transaction is finalized.
func IsFinalizedTransaction(msgTx *btcwire.MsgTx, blockHeight int64, blockTime time.Time) bool {
func IsFinalizedTransaction(tx *btcutil.Tx, blockHeight int64, blockTime time.Time) bool {
msgTx := tx.MsgTx()
// Lock time of zero means the transaction is finalized.
lockTime := msgTx.LockTime
if lockTime == 0 {
@ -175,14 +179,15 @@ func calcBlockSubsidy(height int64) int64 {
// CheckTransactionSanity performs some preliminary checks on a transaction to
// ensure it is sane. These checks are context free.
func CheckTransactionSanity(tx *btcwire.MsgTx) error {
func CheckTransactionSanity(tx *btcutil.Tx) error {
// A transaction must have at least one input.
if len(tx.TxIn) == 0 {
msgTx := tx.MsgTx()
if len(msgTx.TxIn) == 0 {
return RuleError("transaction has no inputs")
}
// A transaction must have at least one output.
if len(tx.TxOut) == 0 {
if len(msgTx.TxOut) == 0 {
return RuleError("transaction has no outputs")
}
@ -198,7 +203,7 @@ func CheckTransactionSanity(tx *btcwire.MsgTx) error {
// as a satoshi. One bitcoin is a quantity of satoshi as defined by the
// satoshiPerBitcoin constant.
var totalSatoshi int64
for _, txOut := range tx.TxOut {
for _, txOut := range msgTx.TxOut {
satoshi := txOut.Value
if satoshi < 0 {
str := fmt.Sprintf("transaction output has negative "+
@ -231,7 +236,7 @@ func CheckTransactionSanity(tx *btcwire.MsgTx) error {
// Check for duplicate transaction inputs.
existingTxOut := make(map[btcwire.OutPoint]bool)
for _, txIn := range tx.TxIn {
for _, txIn := range msgTx.TxIn {
if _, exists := existingTxOut[txIn.PreviousOutpoint]; exists {
return RuleError("transaction contains duplicate outpoint")
}
@ -240,7 +245,7 @@ func CheckTransactionSanity(tx *btcwire.MsgTx) error {
// Coinbase script length must be between min and max length.
if IsCoinBase(tx) {
slen := len(tx.TxIn[0].SignatureScript)
slen := len(msgTx.TxIn[0].SignatureScript)
if slen < minCoinbaseScriptLen || slen > maxCoinbaseScriptLen {
str := fmt.Sprintf("coinbase transaction script length "+
"of %d is out of range (min: %d, max: %d)",
@ -250,7 +255,7 @@ func CheckTransactionSanity(tx *btcwire.MsgTx) error {
} else {
// Previous transaction outputs referenced by the inputs to this
// transaction must not be null.
for _, txIn := range tx.TxIn {
for _, txIn := range msgTx.TxIn {
prevOut := &txIn.PreviousOutpoint
if isNullOutpoint(prevOut) {
return RuleError("transaction input refers to " +
@ -302,7 +307,9 @@ func (b *BlockChain) checkProofOfWork(block *btcutil.Block) error {
// input and output scripts in the provided transaction. This uses the
// quicker, but imprecise, signature operation counting mechanism from
// btcscript.
func countSigOps(msgTx *btcwire.MsgTx) int {
func countSigOps(tx *btcutil.Tx) int {
msgTx := tx.MsgTx()
// Accumulate the number of signature operations in all transaction
// inputs.
totalSigOps := 0
@ -325,20 +332,15 @@ func countSigOps(msgTx *btcwire.MsgTx) int {
// transactions which are of the pay-to-script-hash type. This uses the
// precise, signature operation counting mechanism from btcscript which requires
// access to the input transaction scripts.
func countP2SHSigOps(msgTx *btcwire.MsgTx, isCoinBaseTx bool, txStore TxStore) (int, error) {
func countP2SHSigOps(tx *btcutil.Tx, isCoinBaseTx bool, txStore TxStore) (int, error) {
// Coinbase transactions have no interesting inputs.
if isCoinBaseTx {
return 0, nil
}
// TODO(davec): Need to pass the cached version in.
txHash, err := msgTx.TxSha()
if err != nil {
return 0, err
}
// Accumulate the number of signature operations in all transaction
// inputs.
msgTx := tx.MsgTx()
totalSigOps := 0
for _, txIn := range msgTx.TxIn {
// Ensure the referenced input transaction is available.
@ -347,23 +349,24 @@ func countP2SHSigOps(msgTx *btcwire.MsgTx, isCoinBaseTx bool, txStore TxStore) (
if !exists || originTx.Err != nil || originTx.Tx == nil {
str := fmt.Sprintf("unable to find input transaction "+
"%v referenced from transaction %v", txInHash,
txHash)
tx.Sha())
return 0, RuleError(str)
}
originMsgTx := originTx.Tx.MsgTx()
// Ensure the output index in the referenced transaction is
// available.
originTxIndex := txIn.PreviousOutpoint.Index
if originTxIndex >= uint32(len(originTx.Tx.TxOut)) {
if originTxIndex >= uint32(len(originMsgTx.TxOut)) {
str := fmt.Sprintf("out of bounds input index %d in "+
"transaction %v referenced from transaction %v",
originTxIndex, txInHash, txHash)
originTxIndex, txInHash, tx.Sha())
return 0, RuleError(str)
}
// We're only interested in pay-to-script-hash types, so skip
// this input if it's not one.
pkScript := originTx.Tx.TxOut[originTxIndex].PkScript
pkScript := originMsgTx.TxOut[originTxIndex].PkScript
if !btcscript.IsPayToScriptHash(pkScript) {
continue
}
@ -407,8 +410,7 @@ func (b *BlockChain) checkBlockSanity(block *btcutil.Block) error {
}
// Ensure the block time is not more than 2 hours in the future.
msgBlock := block.MsgBlock()
header := &msgBlock.Header
header := &block.MsgBlock().Header
if header.Timestamp.After(time.Now().Add(time.Hour * 2)) {
str := fmt.Sprintf("block timestamp of %v is too far in the "+
"future", header.Timestamp)
@ -416,7 +418,7 @@ func (b *BlockChain) checkBlockSanity(block *btcutil.Block) error {
}
// A block must have at least one transaction.
transactions := msgBlock.Transactions
transactions := block.Transactions()
if len(transactions) == 0 {
return RuleError("block does not contain any transactions")
}
@ -463,11 +465,8 @@ func (b *BlockChain) checkBlockSanity(block *btcutil.Block) error {
// since the transaction hashes are already cached due to building the
// merkle tree above.
existingTxHashes := make(map[btcwire.ShaHash]bool)
txShas, err := block.TxShas()
if err != nil {
return err
}
for _, hash := range txShas {
for _, tx := range transactions {
hash := tx.Sha()
if _, exists := existingTxHashes[*hash]; exists {
str := fmt.Sprintf("block contains duplicate "+
"transaction %v", hash)
@ -497,8 +496,8 @@ func (b *BlockChain) checkBlockSanity(block *btcutil.Block) error {
// checkSerializedHeight checks if the signature script in the passed
// transaction starts with the serialized block height of wantHeight.
func checkSerializedHeight(coinbaseTx *btcwire.MsgTx, wantHeight int64) error {
sigScript := coinbaseTx.TxIn[0].SignatureScript
func checkSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int64) error {
sigScript := coinbaseTx.MsgTx().TxIn[0].SignatureScript
if len(sigScript) < 1 {
str := "the coinbase signature script for blocks of " +
"version %d or greater must start with the " +
@ -601,20 +600,15 @@ func (b *BlockChain) checkBIP0030(node *blockNode, block *btcutil.Block) error {
// amount, and verifying the signatures to prove the spender was the owner of
// the bitcoins and therefore allowed to spend them. As it checks the inputs,
// it also calculates the total fees for the transaction and returns that value.
func CheckTransactionInputs(tx *btcwire.MsgTx, txHeight int64, txStore TxStore) (int64, error) {
func CheckTransactionInputs(tx *btcutil.Tx, txHeight int64, txStore TxStore) (int64, error) {
// Coinbase transactions have no inputs.
if IsCoinBase(tx) {
return 0, nil
}
// TODO(davec): Need to pass the cached version in.
txHash, err := tx.TxSha()
if err != nil {
return 0, err
}
txHash := tx.Sha()
var totalSatoshiIn int64
for _, txIn := range tx.TxIn {
for _, txIn := range tx.MsgTx().TxIn {
// Ensure the input is available.
txInHash := &txIn.PreviousOutpoint.Hash
originTx, exists := txStore[*txInHash]
@ -659,7 +653,7 @@ func CheckTransactionInputs(tx *btcwire.MsgTx, txHeight int64, txStore TxStore)
// a transaction are in a unit value known as a satoshi. One
// bitcoin is a quantity of satoshi as defined by the
// satoshiPerBitcoin constant.
originTxSatoshi := originTx.Tx.TxOut[originTxIndex].Value
originTxSatoshi := originTx.Tx.MsgTx().TxOut[originTxIndex].Value
if originTxSatoshi < 0 {
str := fmt.Sprintf("transaction output has negative "+
"value of %v", originTxSatoshi)
@ -693,7 +687,7 @@ func CheckTransactionInputs(tx *btcwire.MsgTx, txHeight int64, txStore TxStore)
// to ignore overflow and out of range errors here because those error
// conditions would have already been caught by checkTransactionSanity.
var totalSatoshiOut int64
for _, txOut := range tx.TxOut {
for _, txOut := range tx.MsgTx().TxOut {
totalSatoshiOut += txOut.Value
}
@ -771,7 +765,7 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block) er
// expands the count to include a precise count of pay-to-script-hash
// signature operations in each of the input transaction public key
// scripts.
transactions := block.MsgBlock().Transactions
transactions := block.Transactions()
totalSigOps := 0
for i, tx := range transactions {
numsigOps := countSigOps(tx)
@ -832,7 +826,7 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block) er
// errors here because those error conditions would have already been
// caught by checkTransactionSanity.
var totalSatoshiOut int64
for _, txOut := range transactions[0].TxOut {
for _, txOut := range transactions[0].MsgTx().TxOut {
totalSatoshiOut += txOut.Value
}
expectedSatoshiOut := calcBlockSubsidy(node.height) + totalFees

View file

@ -66,8 +66,9 @@ func TestCheckSerializedHeight(t *testing.T) {
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
tx := coinbaseTx.Copy()
tx.TxIn[0].SignatureScript = test.sigScript
msgTx := coinbaseTx.Copy()
msgTx.TxIn[0].SignatureScript = test.sigScript
tx := btcutil.NewTx(msgTx)
err := btcchain.TstCheckSerializedHeight(tx, test.wantHeight)
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {