Reject blocks with high precision timestamps.

This commit adds an additional sanity check to ensure the block that is
being processed does not contain a timestamp with a precision higher than
one second.  This is necessary because the consensus rules only deal with
whole seconds in the time comparisons whereas the internal data structures
make use of Go time.Time values which support up to nanosecond precision.

Also, add a test to ensure the new functionality works as expected.

ok @owainga
This commit is contained in:
Dave Collins 2014-02-24 10:17:13 -06:00
parent bfef4e4a31
commit 1c052a01d8
3 changed files with 66 additions and 42 deletions

View file

@ -1,90 +1,94 @@
github.com/conformal/btcchain/validate.go checkSerializedHeight 100.00% (17/17)
github.com/conformal/btcchain/chain.go BlockChain.removeOrphanBlock 100.00% (16/16)
github.com/conformal/btcchain/validate.go countSigOps 100.00% (8/8)
github.com/conformal/btcchain/txlookup.go disconnectTransactions 100.00% (13/13)
github.com/conformal/btcchain/validate.go countSigOps 100.00% (9/9)
github.com/conformal/btcchain/checkpoints.go init 100.00% (6/6)
github.com/conformal/btcchain/chain.go BlockChain.IsKnownOrphan 100.00% (5/5)
github.com/conformal/btcchain/difficulty.go ShaHashToBig 100.00% (5/5)
github.com/conformal/btcchain/merkle.go hashMerkleBranches 100.00% (5/5)
github.com/conformal/btcchain/difficulty.go ShaHashToBig 100.00% (5/5)
github.com/conformal/btcchain/chain.go BlockChain.IsKnownOrphan 100.00% (5/5)
github.com/conformal/btcchain/merkle.go nextPowerOfTwo 100.00% (4/4)
github.com/conformal/btcchain/chain.go newBlockNode 100.00% (4/4)
github.com/conformal/btcchain/chain.go newBlockNode 100.00% (3/3)
github.com/conformal/btcchain/process.go BlockChain.blockExists 100.00% (3/3)
github.com/conformal/btcchain/chain.go New 100.00% (2/2)
github.com/conformal/btcchain/checkpoints.go newShaHashFromStr 100.00% (2/2)
github.com/conformal/btcchain/log.go DisableLog 100.00% (1/1)
github.com/conformal/btcchain/validate.go calcBlockSubsidy 100.00% (1/1)
github.com/conformal/btcchain/chain.go New 100.00% (2/2)
github.com/conformal/btcchain/timesorter.go timeSorter.Swap 100.00% (1/1)
github.com/conformal/btcchain/validate.go BlockChain.calcBlockSubsidy 100.00% (1/1)
github.com/conformal/btcchain/chain.go BlockChain.HaveBlock 100.00% (1/1)
github.com/conformal/btcchain/log.go init 100.00% (1/1)
github.com/conformal/btcchain/timesorter.go timeSorter.Less 100.00% (1/1)
github.com/conformal/btcchain/timesorter.go timeSorter.Len 100.00% (1/1)
github.com/conformal/btcchain/timesorter.go timeSorter.Swap 100.00% (1/1)
github.com/conformal/btcchain/scriptval.go newTxValidator 100.00% (1/1)
github.com/conformal/btcchain/checkpoints.go BlockChain.DisableCheckpoints 100.00% (1/1)
github.com/conformal/btcchain/scriptval.go txValidator.sendResult 100.00% (1/1)
github.com/conformal/btcchain/log.go DisableLog 100.00% (1/1)
github.com/conformal/btcchain/params.go BlockChain.chainParams 100.00% (1/1)
github.com/conformal/btcchain/log.go init 100.00% (1/1)
github.com/conformal/btcchain/txlookup.go fetchTxStoreMain 94.44% (17/18)
github.com/conformal/btcchain/merkle.go BuildMerkleTreeStore 94.12% (16/17)
github.com/conformal/btcchain/txlookup.go disconnectTransactions 93.75% (15/16)
github.com/conformal/btcchain/txlookup.go fetchTxStoreMain 95.65% (22/23)
github.com/conformal/btcchain/merkle.go BuildMerkleTreeStore 93.33% (14/15)
github.com/conformal/btcchain/chain.go BlockChain.getReorganizeNodes 92.86% (13/14)
github.com/conformal/btcchain/process.go BlockChain.processOrphans 92.86% (13/14)
github.com/conformal/btcchain/chain.go BlockChain.connectBestChain 90.00% (27/30)
github.com/conformal/btcchain/scriptval.go ValidateTransactionScripts 88.24% (30/34)
github.com/conformal/btcchain/txlookup.go BlockChain.fetchTxStore 86.36% (19/22)
github.com/conformal/btcchain/scriptval.go checkBlockScripts 85.71% (6/7)
github.com/conformal/btcchain/scriptval.go txValidator.Validate 88.46% (23/26)
github.com/conformal/btcchain/scriptval.go checkBlockScripts 88.24% (15/17)
github.com/conformal/btcchain/txlookup.go BlockChain.fetchTxStore 86.96% (20/23)
github.com/conformal/btcchain/validate.go IsCoinBase 85.71% (6/7)
github.com/conformal/btcchain/chain.go BlockChain.connectBestChain 85.29% (29/34)
github.com/conformal/btcchain/chain.go BlockChain.reorganizeChain 85.29% (29/34)
github.com/conformal/btcchain/process.go BlockChain.processOrphans 84.21% (16/19)
github.com/conformal/btcchain/chain.go BlockChain.connectBlock 83.33% (10/12)
github.com/conformal/btcchain/validate.go IsCoinBase 83.33% (5/6)
github.com/conformal/btcchain/chain.go BlockChain.calcPastMedianTime 82.35% (14/17)
github.com/conformal/btcchain/chain.go BlockChain.isMajorityVersion 80.00% (8/10)
github.com/conformal/btcchain/difficulty.go calcWork 80.00% (4/5)
github.com/conformal/btcchain/difficulty.go CalcWork 80.00% (4/5)
github.com/conformal/btcchain/chain.go BlockChain.addOrphanBlock 77.78% (14/18)
github.com/conformal/btcchain/chain.go BlockChain.getPrevNodeFromBlock 77.78% (7/9)
github.com/conformal/btcchain/chain.go BlockChain.disconnectBlock 76.92% (10/13)
github.com/conformal/btcchain/txlookup.go BlockChain.fetchInputTransactions 76.00% (19/25)
github.com/conformal/btcchain/txlookup.go BlockChain.fetchInputTransactions 75.00% (18/24)
github.com/conformal/btcchain/difficulty.go BigToCompact 75.00% (12/16)
github.com/conformal/btcchain/difficulty.go CompactToBig 75.00% (9/12)
github.com/conformal/btcchain/validate.go BlockChain.checkConnectBlock 69.23% (36/52)
github.com/conformal/btcchain/validate.go CheckBlockSanity 67.44% (29/43)
github.com/conformal/btcchain/validate.go isNullOutpoint 66.67% (2/3)
github.com/conformal/btcchain/validate.go BlockChain.checkBlockSanity 65.12% (28/43)
github.com/conformal/btcchain/validate.go CheckTransactionInputs 65.12% (28/43)
github.com/conformal/btcchain/validate.go BlockChain.checkBIP0030 64.71% (11/17)
github.com/conformal/btcchain/scriptval.go validateTxIn 64.71% (11/17)
github.com/conformal/btcchain/validate.go CheckTransactionInputs 64.44% (29/45)
github.com/conformal/btcchain/validate.go CheckTransactionSanity 62.16% (23/37)
github.com/conformal/btcchain/txlookup.go connectTransactions 60.00% (9/15)
github.com/conformal/btcchain/params.go ChainParams 60.00% (3/5)
github.com/conformal/btcchain/txlookup.go connectTransactions 61.54% (8/13)
github.com/conformal/btcchain/validate.go CheckTransactionSanity 61.11% (22/36)
github.com/conformal/btcchain/validate.go isBIP0030Node 60.00% (3/5)
github.com/conformal/btcchain/validate.go BlockChain.checkProofOfWork 58.82% (10/17)
github.com/conformal/btcchain/process.go BlockChain.ProcessBlock 53.49% (23/43)
github.com/conformal/btcchain/chain.go BlockChain.loadBlockNode 50.00% (11/22)
github.com/conformal/btcchain/params.go ChainParams 60.00% (3/5)
github.com/conformal/btcchain/scriptval.go txValidator.validateHandler 59.26% (16/27)
github.com/conformal/btcchain/validate.go checkProofOfWork 53.33% (8/15)
github.com/conformal/btcchain/process.go BlockChain.ProcessBlock 52.27% (23/44)
github.com/conformal/btcchain/chain.go BlockChain.loadBlockNode 52.00% (13/25)
github.com/conformal/btcchain/accept.go BlockChain.maybeAcceptBlock 51.28% (40/78)
github.com/conformal/btcchain/chain.go BlockChain.getPrevNodeFromNode 50.00% (4/8)
github.com/conformal/btcchain/notifications.go BlockChain.sendNotification 50.00% (2/4)
github.com/conformal/btcchain/checkpoints.go BlockChain.LatestCheckpoint 50.00% (2/4)
github.com/conformal/btcchain/accept.go BlockChain.maybeAcceptBlock 49.30% (35/71)
github.com/conformal/btcchain/notifications.go BlockChain.sendNotification 50.00% (2/4)
github.com/conformal/btcchain/chain.go BlockChain.pruneBlockNodes 41.18% (7/17)
github.com/conformal/btcchain/checkpoints.go BlockChain.verifyCheckpoint 33.33% (2/6)
github.com/conformal/btcchain/validate.go IsFinalizedTransaction 23.08% (3/13)
github.com/conformal/btcchain/checkpoints.go BlockChain.findLatestKnownCheckpoint 18.18% (2/11)
github.com/conformal/btcchain/validate.go IsFinalizedTransaction 28.57% (4/14)
github.com/conformal/btcchain/checkpoints.go BlockChain.verifyCheckpoint 22.22% (2/9)
github.com/conformal/btcchain/difficulty.go BlockChain.calcNextRequiredDifficulty 17.07% (7/41)
github.com/conformal/btcchain/checkpoints.go BlockChain.findPreviousCheckpoint 4.88% (2/41)
github.com/conformal/btcchain/blocklocator.go BlockChain.BlockLocatorFromHash 0.00% (0/39)
github.com/conformal/btcchain/checkpoints.go BlockChain.IsCheckpointCandidate 0.00% (0/32)
github.com/conformal/btcchain/validate.go countP2SHSigOps 0.00% (0/24)
github.com/conformal/btcchain/chain.go BlockChain.GenerateInitialIndex 0.00% (0/17)
github.com/conformal/btcchain/validate.go countP2SHSigOps 0.00% (0/26)
github.com/conformal/btcchain/chain.go BlockChain.GenerateInitialIndex 0.00% (0/22)
github.com/conformal/btcchain/difficulty.go BlockChain.calcEasiestDifficulty 0.00% (0/15)
github.com/conformal/btcchain/chain.go BlockChain.removeBlockNode 0.00% (0/12)
github.com/conformal/btcchain/difficulty.go BlockChain.findPrevTestNetDifficulty 0.00% (0/12)
github.com/conformal/btcchain/chain.go BlockChain.removeBlockNode 0.00% (0/12)
github.com/conformal/btcchain/chain.go BlockChain.GetOrphanRoot 0.00% (0/11)
github.com/conformal/btcchain/txlookup.go BlockChain.FetchTransactionStore 0.00% (0/9)
github.com/conformal/btcchain/scriptval.go ValidateTransactionScripts 0.00% (0/11)
github.com/conformal/btcchain/log.go SetLogWriter 0.00% (0/10)
github.com/conformal/btcchain/chain.go BlockChain.IsCurrent 0.00% (0/9)
github.com/conformal/btcchain/chain.go removeChildNode 0.00% (0/8)
github.com/conformal/btcchain/log.go SetLogWriter 0.00% (0/7)
github.com/conformal/btcchain/blocklocator.go BlockChain.LatestBlockLocator 0.00% (0/6)
github.com/conformal/btcchain/txlookup.go BlockChain.FetchTransactionStore 0.00% (0/6)
github.com/conformal/btcchain/checkpoints.go isNonstandardTransaction 0.00% (0/5)
github.com/conformal/btcchain/validate.go isTransactionSpent 0.00% (0/4)
github.com/conformal/btcchain/checkpoints.go BlockChain.checkpointData 0.00% (0/4)
github.com/conformal/btcchain/validate.go isTransactionSpent 0.00% (0/4)
github.com/conformal/btcchain/chain.go addChildrenWork 0.00% (0/3)
github.com/conformal/btcchain/notifications.go NotificationType.String 0.00% (0/3)
github.com/conformal/btcchain/checkpoints.go BlockChain.Checkpoints 0.00% (0/3)
github.com/conformal/btcchain/log.go logClosure.String 0.00% (0/1)
github.com/conformal/btcchain/log.go newLogClosure 0.00% (0/1)
github.com/conformal/btcchain/chain.go BlockChain.DisableVerify 0.00% (0/1)
github.com/conformal/btcchain/log.go UseLogger 0.00% (0/1)
github.com/conformal/btcchain/process.go RuleError.Error 0.00% (0/1)
github.com/conformal/btcchain ------------------------------------- 55.88% (646/1156)
github.com/conformal/btcchain ------------------------------------- 53.75% (666/1239)

View file

@ -398,8 +398,19 @@ func CheckBlockSanity(block *btcutil.Block, powLimit *big.Int) error {
return err
}
// Ensure the block time is not more than 2 hours in the future.
// A block timestamp must not have a greater precision than one second.
// This check is necessary because Go time.Time values support
// nanosecond precision whereas the consensus rules only apply to
// seconds and it's much nicer to deal with standard Go time values
// instead of converting to seconds everywhere.
header := &block.MsgBlock().Header
if !header.Timestamp.Equal(time.Unix(header.Timestamp.Unix(), 0)) {
str := fmt.Sprintf("block timestamp of %v has a higher "+
"precision than one second", header.Timestamp)
return RuleError(str)
}
// Ensure the block time is not more than 2 hours in the future.
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)

View file

@ -21,6 +21,15 @@ func TestCheckBlockSanity(t *testing.T) {
if err != nil {
t.Errorf("CheckBlockSanity: %v", err)
}
// Ensure a block that has a timestamp with a precision higher than one
// second fails.
timestamp := block.MsgBlock().Header.Timestamp
block.MsgBlock().Header.Timestamp = timestamp.Add(time.Nanosecond)
err = btcchain.CheckBlockSanity(block, powLimit)
if err == nil {
t.Errorf("CheckBlockSanity: error is nil when it shouldn't be")
}
}
// TestCheckSerializedHeight tests the checkSerializedHeight function with