diff --git a/blockchain/validate.go b/blockchain/validate.go index 0ee18deb0..0fc9a9497 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -127,6 +127,41 @@ func IsCoinBase(tx *btcutil.Tx) bool { return IsCoinBaseTx(tx.MsgTx()) } +// IsFinalizedTransaction determines whether or not a transaction is finalized. +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 { + return true + } + + // The lock time field of a transaction is either a block height at + // which the transaction is finalized or a timestamp depending on if the + // value is before the txscript.LockTimeThreshold. When it is under the + // threshold it is a block height. + blockTimeOrHeight := int64(0) + if lockTime < txscript.LockTimeThreshold { + blockTimeOrHeight = blockHeight + } else { + blockTimeOrHeight = blockTime.Unix() + } + if int64(lockTime) < blockTimeOrHeight { + return true + } + + // At this point, the transaction's lock time hasn't occured yet, but + // the transaction might still be finalized if the sequence number + // for all transaction inputs is maxed out. + for _, txIn := range msgTx.TxIn { + if txIn.Sequence != math.MaxUint32 { + return false + } + } + return true +} + // isBIP0030Node returns whether or not the passed node represents one of the // two blocks that violate the BIP0030 rule which prevents transactions from // overwriting old ones. @@ -672,7 +707,7 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode // Ensure all transactions in the block are finalized. for _, tx := range block.Transactions() { - if !txscript.IsFinalizedTransaction(tx.MsgTx(), blockHeight, + if !IsFinalizedTransaction(tx, blockHeight, header.Timestamp) { str := fmt.Sprintf("block contains unfinalized "+ diff --git a/mempool.go b/mempool.go index ada0db595..ebcaf5f79 100644 --- a/mempool.go +++ b/mempool.go @@ -237,7 +237,7 @@ func (mp *txMemPool) checkTransactionStandard(tx *btcutil.Tx, height int64) erro // The transaction must be finalized to be standard and therefore // considered for inclusion in a block. adjustedTime := mp.server.timeSource.AdjustedTime() - if !txscript.IsFinalizedTransaction(tx.MsgTx(), height, adjustedTime) { + if !blockchain.IsFinalizedTransaction(tx, height, adjustedTime) { return txRuleError(wire.RejectNonstandard, "transaction is not finalized") } diff --git a/mining.go b/mining.go index 0b739111f..4af911384 100644 --- a/mining.go +++ b/mining.go @@ -446,7 +446,7 @@ mempoolLoop: minrLog.Tracef("Skipping coinbase tx %s", tx.Sha()) continue } - if !txscript.IsFinalizedTransaction(tx.MsgTx(), nextBlockHeight, + if !blockchain.IsFinalizedTransaction(tx, nextBlockHeight, timeSource.AdjustedTime()) { minrLog.Tracef("Skipping non-finalized tx %s", tx.Sha()) diff --git a/txscript/consensus.go b/txscript/consensus.go index de73389cb..1aec50283 100644 --- a/txscript/consensus.go +++ b/txscript/consensus.go @@ -4,13 +4,6 @@ package txscript -import ( - "math" - "time" - - "github.com/btcsuite/btcd/wire" -) - const ( // LockTimeThreshold is the number below which a lock time is // interpreted to be a block number. Since an average of one block @@ -19,36 +12,3 @@ const ( // the lock time is a uint32, the max is sometime around 2106. LockTimeThreshold uint32 = 5e8 // Tue Nov 5 00:53:20 1985 UTC ) - -// IsFinalizedTransaction determines whether or not a transaction is finalized. -func IsFinalizedTransaction(msgTx *wire.MsgTx, blockHeight int64, blockTime time.Time) bool { - // Lock time of zero means the transaction is finalized. - lockTime := msgTx.LockTime - if lockTime == 0 { - return true - } - - // The lock time field of a transaction is either a block height at - // which the transaction is finalized or a timestamp depending on if the - // value is before the LockTimeThreshold. When it is under the - // threshold it is a block height. - blockTimeOrHeight := int64(0) - if lockTime < LockTimeThreshold { - blockTimeOrHeight = blockHeight - } else { - blockTimeOrHeight = blockTime.Unix() - } - if int64(lockTime) < blockTimeOrHeight { - return true - } - - // At this point, the transaction's lock time hasn't occured yet, but - // the transaction might still be finalized if the sequence number - // for all transaction inputs is maxed out. - for _, txIn := range msgTx.TxIn { - if txIn.Sequence != math.MaxUint32 { - return false - } - } - return true -}