Use network adjusted time for finalized tx check.

This commit modifies finalized transaction check used by the memory pool
and block templates to use the network adjusted time instead of the
unadjusted local time.  This helps keep the transactions accepted to the
memory pool, and hence allowed to relay, more consistent across nodes.
This commit is contained in:
Dave Collins 2015-02-28 12:17:43 -06:00
parent e0bb106646
commit def0ef6af6
2 changed files with 13 additions and 8 deletions

View file

@ -225,7 +225,7 @@ func checkPkScriptStandard(pkScript []byte, scriptClass txscript.ScriptClass) er
// finalized, conforming to more stringent size constraints, having scripts // finalized, conforming to more stringent size constraints, having scripts
// of recognized forms, and not containing "dust" outputs (those that are // of recognized forms, and not containing "dust" outputs (those that are
// so small it costs more to process them than they are worth). // so small it costs more to process them than they are worth).
func checkTransactionStandard(tx *btcutil.Tx, height int64) error { func (mp *txMemPool) checkTransactionStandard(tx *btcutil.Tx, height int64) error {
msgTx := tx.MsgTx() msgTx := tx.MsgTx()
// The transaction must be a currently supported version. // The transaction must be a currently supported version.
@ -238,7 +238,8 @@ func checkTransactionStandard(tx *btcutil.Tx, height int64) error {
// The transaction must be finalized to be standard and therefore // The transaction must be finalized to be standard and therefore
// considered for inclusion in a block. // considered for inclusion in a block.
if !blockchain.IsFinalizedTransaction(tx, height, time.Now()) { adjustedTime := mp.server.timeSource.AdjustedTime()
if !blockchain.IsFinalizedTransaction(tx, height, adjustedTime) {
return txRuleError(wire.RejectNonstandard, return txRuleError(wire.RejectNonstandard,
"transaction is not finalized") "transaction is not finalized")
} }
@ -1030,7 +1031,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit boo
// Don't allow non-standard transactions if the network parameters // Don't allow non-standard transactions if the network parameters
// forbid their relaying. // forbid their relaying.
if !activeNetParams.RelayNonStdTxs { if !activeNetParams.RelayNonStdTxs {
err := checkTransactionStandard(tx, nextBlockHeight) err := mp.checkTransactionStandard(tx, nextBlockHeight)
if err != nil { if err != nil {
// Attempt to extract a reject code from the error so // Attempt to extract a reject code from the error so
// it can be retained. When not possible, fall back to // it can be retained. When not possible, fall back to

View file

@ -282,7 +282,7 @@ func minimumMedianTime(chainState *chainState) (time.Time, error) {
// medianAdjustedTime returns the current time adjusted to ensure it is at least // medianAdjustedTime returns the current time adjusted to ensure it is at least
// one second after the median timestamp of the last several blocks per the // one second after the median timestamp of the last several blocks per the
// chain consensus rules. // chain consensus rules.
func medianAdjustedTime(chainState *chainState) (time.Time, error) { func medianAdjustedTime(chainState *chainState, timeSource blockchain.MedianTimeSource) (time.Time, error) {
chainState.Lock() chainState.Lock()
defer chainState.Unlock() defer chainState.Unlock()
if chainState.pastMedianTimeErr != nil { if chainState.pastMedianTimeErr != nil {
@ -295,7 +295,7 @@ func medianAdjustedTime(chainState *chainState) (time.Time, error) {
// timestamp is truncated to a second boundary before comparison since a // timestamp is truncated to a second boundary before comparison since a
// block timestamp does not supported a precision greater than one // block timestamp does not supported a precision greater than one
// second. // second.
newTimestamp := time.Unix(time.Now().Unix(), 0) newTimestamp := timeSource.AdjustedTime()
minTimestamp := chainState.pastMedianTime.Add(time.Second) minTimestamp := chainState.pastMedianTime.Add(time.Second)
if newTimestamp.Before(minTimestamp) { if newTimestamp.Before(minTimestamp) {
newTimestamp = minTimestamp newTimestamp = minTimestamp
@ -367,6 +367,7 @@ func medianAdjustedTime(chainState *chainState) (time.Time, error) {
// ----------------------------------- -- // ----------------------------------- --
func NewBlockTemplate(mempool *txMemPool, payToAddress btcutil.Address) (*BlockTemplate, error) { func NewBlockTemplate(mempool *txMemPool, payToAddress btcutil.Address) (*BlockTemplate, error) {
blockManager := mempool.server.blockManager blockManager := mempool.server.blockManager
timeSource := mempool.server.timeSource
chainState := &blockManager.chainState chainState := &blockManager.chainState
chain := blockManager.blockChain chain := blockManager.blockChain
@ -445,7 +446,9 @@ mempoolLoop:
minrLog.Tracef("Skipping coinbase tx %s", tx.Sha()) minrLog.Tracef("Skipping coinbase tx %s", tx.Sha())
continue continue
} }
if !blockchain.IsFinalizedTransaction(tx, nextBlockHeight, time.Now()) { if !blockchain.IsFinalizedTransaction(tx, nextBlockHeight,
timeSource.AdjustedTime()) {
minrLog.Tracef("Skipping non-finalized tx %s", tx.Sha()) minrLog.Tracef("Skipping non-finalized tx %s", tx.Sha())
continue continue
} }
@ -708,7 +711,7 @@ mempoolLoop:
// Calculate the required difficulty for the block. The timestamp // Calculate the required difficulty for the block. The timestamp
// is potentially adjusted to ensure it comes after the median time of // is potentially adjusted to ensure it comes after the median time of
// the last several blocks per the chain consensus rules. // the last several blocks per the chain consensus rules.
ts, err := medianAdjustedTime(chainState) ts, err := medianAdjustedTime(chainState, timeSource)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -766,7 +769,8 @@ func UpdateBlockTime(msgBlock *wire.MsgBlock, bManager *blockManager) error {
// The new timestamp is potentially adjusted to ensure it comes after // The new timestamp is potentially adjusted to ensure it comes after
// the median time of the last several blocks per the chain consensus // the median time of the last several blocks per the chain consensus
// rules. // rules.
newTimestamp, err := medianAdjustedTime(&bManager.chainState) newTimestamp, err := medianAdjustedTime(&bManager.chainState,
bManager.server.timeSource)
if err != nil { if err != nil {
return err return err
} }