Export CheckConnectBlock function.
This commit makes a slight variant of the existing checkConnectBlock function available to external callers. The new exported version checks if the passed block will connect to the end of the current main chain. In order to support this, a few other small modifications have been made to the initial index generation and the existing checkConnectBlock since it previously made some assumptions about the state of genesis block which can no longer be assumed due accepting blocks from callers directly. Also, add a quick test to ensure the new function fails when checking if the genesis block will connect again when it's already inserted.
This commit is contained in:
parent
acdce27f9f
commit
1676ecd7a6
4 changed files with 80 additions and 27 deletions
8
chain.go
8
chain.go
|
@ -340,7 +340,7 @@ func (b *BlockChain) GenerateInitialIndex() error {
|
||||||
|
|
||||||
// Calculate the starting height based on the minimum number of nodes
|
// Calculate the starting height based on the minimum number of nodes
|
||||||
// needed in memory.
|
// needed in memory.
|
||||||
startHeight := endHeight - (minMemoryNodes + 1)
|
startHeight := endHeight - minMemoryNodes
|
||||||
if startHeight < 0 {
|
if startHeight < 0 {
|
||||||
startHeight = 0
|
startHeight = 0
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ func (b *BlockChain) GenerateInitialIndex() error {
|
||||||
// is going to be nuked eventually, the bug isn't being fixed in the
|
// is going to be nuked eventually, the bug isn't being fixed in the
|
||||||
// driver. In the mean time, work around the issue by calling
|
// driver. In the mean time, work around the issue by calling
|
||||||
// FetchBlockBySha multiple times with the appropriate indices as needed.
|
// FetchBlockBySha multiple times with the appropriate indices as needed.
|
||||||
for start := startHeight; start < endHeight; {
|
for start := startHeight; start <= endHeight; {
|
||||||
hashList, err := b.db.FetchHeightRange(start, endHeight+1)
|
hashList, err := b.db.FetchHeightRange(start, endHeight+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -368,8 +368,8 @@ func (b *BlockChain) GenerateInitialIndex() error {
|
||||||
// Loop forwards through each block loading the node into the
|
// Loop forwards through each block loading the node into the
|
||||||
// index for the block.
|
// index for the block.
|
||||||
for _, hash := range hashList {
|
for _, hash := range hashList {
|
||||||
// Make a copy of the hash to make sure there are no references
|
// Make a copy of the hash to make sure there are no
|
||||||
// into the list so it can be freed.
|
// references into the list so it can be freed.
|
||||||
hashCopy := hash
|
hashCopy := hash
|
||||||
node, err := b.loadBlockNode(&hashCopy)
|
node, err := b.loadBlockNode(&hashCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,27 +2,28 @@
|
||||||
github.com/conformal/btcchain/validate.go checkSerializedHeight 100.00% (17/17)
|
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/chain.go BlockChain.removeOrphanBlock 100.00% (16/16)
|
||||||
github.com/conformal/btcchain/txlookup.go disconnectTransactions 100.00% (13/13)
|
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/validate.go CountSigOps 100.00% (9/9)
|
||||||
|
github.com/conformal/btcchain/validate.go BlockChain.CheckConnectBlock 100.00% (7/7)
|
||||||
github.com/conformal/btcchain/checkpoints.go init 100.00% (6/6)
|
github.com/conformal/btcchain/checkpoints.go init 100.00% (6/6)
|
||||||
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/difficulty.go ShaHashToBig 100.00% (5/5)
|
||||||
|
github.com/conformal/btcchain/merkle.go hashMerkleBranches 100.00% (5/5)
|
||||||
github.com/conformal/btcchain/chain.go BlockChain.IsKnownOrphan 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/merkle.go nextPowerOfTwo 100.00% (4/4)
|
||||||
github.com/conformal/btcchain/chain.go newBlockNode 100.00% (3/3)
|
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/process.go BlockChain.blockExists 100.00% (3/3)
|
||||||
github.com/conformal/btcchain/checkpoints.go newShaHashFromStr 100.00% (2/2)
|
|
||||||
github.com/conformal/btcchain/chain.go New 100.00% (2/2)
|
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/checkpoints.go newShaHashFromStr 100.00% (2/2)
|
||||||
github.com/conformal/btcchain/validate.go BlockChain.calcBlockSubsidy 100.00% (1/1)
|
github.com/conformal/btcchain/timesorter.go timeSorter.Less 100.00% (1/1)
|
||||||
github.com/conformal/btcchain/chain.go BlockChain.HaveBlock 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/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.Swap 100.00% (1/1)
|
||||||
github.com/conformal/btcchain/timesorter.go timeSorter.Len 100.00% (1/1)
|
github.com/conformal/btcchain/timesorter.go timeSorter.Len 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/checkpoints.go BlockChain.DisableCheckpoints 100.00% (1/1)
|
||||||
|
github.com/conformal/btcchain/scriptval.go newTxValidator 100.00% (1/1)
|
||||||
github.com/conformal/btcchain/scriptval.go txValidator.sendResult 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/params.go BlockChain.chainParams 100.00% (1/1)
|
||||||
|
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/txlookup.go fetchTxStoreMain 95.65% (22/23)
|
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/merkle.go BuildMerkleTreeStore 93.33% (14/15)
|
||||||
github.com/conformal/btcchain/chain.go BlockChain.getReorganizeNodes 92.86% (13/14)
|
github.com/conformal/btcchain/chain.go BlockChain.getReorganizeNodes 92.86% (13/14)
|
||||||
|
@ -35,19 +36,21 @@ github.com/conformal/btcchain/chain.go BlockChain.reorganizeChain 85.29% (29
|
||||||
github.com/conformal/btcchain/process.go BlockChain.processOrphans 84.21% (16/19)
|
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/chain.go BlockChain.connectBlock 83.33% (10/12)
|
||||||
github.com/conformal/btcchain/chain.go BlockChain.calcPastMedianTime 82.35% (14/17)
|
github.com/conformal/btcchain/chain.go BlockChain.calcPastMedianTime 82.35% (14/17)
|
||||||
|
github.com/conformal/btcchain/validate.go BlockChain.checkBIP0030 82.35% (14/17)
|
||||||
github.com/conformal/btcchain/chain.go BlockChain.isMajorityVersion 80.00% (8/10)
|
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.addOrphanBlock 77.78% (14/18)
|
||||||
github.com/conformal/btcchain/chain.go BlockChain.getPrevNodeFromBlock 77.78% (7/9)
|
github.com/conformal/btcchain/chain.go BlockChain.getPrevNodeFromBlock 77.78% (7/9)
|
||||||
|
github.com/conformal/btcchain/chain.go BlockChain.GenerateInitialIndex 77.27% (17/22)
|
||||||
github.com/conformal/btcchain/chain.go BlockChain.disconnectBlock 76.92% (10/13)
|
github.com/conformal/btcchain/chain.go BlockChain.disconnectBlock 76.92% (10/13)
|
||||||
github.com/conformal/btcchain/txlookup.go BlockChain.fetchInputTransactions 75.00% (18/24)
|
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 BigToCompact 75.00% (12/16)
|
||||||
github.com/conformal/btcchain/difficulty.go CompactToBig 75.00% (9/12)
|
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 isTransactionSpent 75.00% (3/4)
|
||||||
|
github.com/conformal/btcchain/validate.go BlockChain.checkConnectBlock 71.15% (37/52)
|
||||||
github.com/conformal/btcchain/validate.go CheckBlockSanity 67.44% (29/43)
|
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 isNullOutpoint 66.67% (2/3)
|
||||||
github.com/conformal/btcchain/validate.go CheckTransactionInputs 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/txlookup.go connectTransactions 61.54% (8/13)
|
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 CheckTransactionSanity 61.11% (22/36)
|
||||||
github.com/conformal/btcchain/validate.go isBIP0030Node 60.00% (3/5)
|
github.com/conformal/btcchain/validate.go isBIP0030Node 60.00% (3/5)
|
||||||
|
@ -63,12 +66,11 @@ github.com/conformal/btcchain/notifications.go BlockChain.sendNotification 50
|
||||||
github.com/conformal/btcchain/chain.go BlockChain.pruneBlockNodes 41.18% (7/17)
|
github.com/conformal/btcchain/chain.go BlockChain.pruneBlockNodes 41.18% (7/17)
|
||||||
github.com/conformal/btcchain/validate.go IsFinalizedTransaction 28.57% (4/14)
|
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/checkpoints.go BlockChain.verifyCheckpoint 22.22% (2/9)
|
||||||
github.com/conformal/btcchain/difficulty.go BlockChain.calcNextRequiredDifficulty 17.07% (7/41)
|
github.com/conformal/btcchain/difficulty.go BlockChain.calcNextRequiredDifficulty 17.50% (7/40)
|
||||||
github.com/conformal/btcchain/checkpoints.go BlockChain.findPreviousCheckpoint 4.88% (2/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/blocklocator.go BlockChain.BlockLocatorFromHash 0.00% (0/39)
|
||||||
github.com/conformal/btcchain/checkpoints.go BlockChain.IsCheckpointCandidate 0.00% (0/32)
|
github.com/conformal/btcchain/checkpoints.go BlockChain.IsCheckpointCandidate 0.00% (0/32)
|
||||||
github.com/conformal/btcchain/validate.go countP2SHSigOps 0.00% (0/26)
|
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/difficulty.go BlockChain.calcEasiestDifficulty 0.00% (0/15)
|
||||||
github.com/conformal/btcchain/difficulty.go BlockChain.findPrevTestNetDifficulty 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.removeBlockNode 0.00% (0/12)
|
||||||
|
@ -81,14 +83,14 @@ github.com/conformal/btcchain/blocklocator.go BlockChain.LatestBlockLocator 0
|
||||||
github.com/conformal/btcchain/txlookup.go BlockChain.FetchTransactionStore 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/checkpoints.go isNonstandardTransaction 0.00% (0/5)
|
||||||
github.com/conformal/btcchain/checkpoints.go BlockChain.checkpointData 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/notifications.go NotificationType.String 0.00% (0/3)
|
||||||
|
github.com/conformal/btcchain/chain.go addChildrenWork 0.00% (0/3)
|
||||||
github.com/conformal/btcchain/checkpoints.go BlockChain.Checkpoints 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/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/process.go RuleError.Error 0.00% (0/1)
|
||||||
github.com/conformal/btcchain ------------------------------------- 53.75% (666/1239)
|
github.com/conformal/btcchain/difficulty.go BlockChain.CalcNextRequiredDifficulty 0.00% (0/1)
|
||||||
|
github.com/conformal/btcchain/log.go logClosure.String 0.00% (0/1)
|
||||||
|
github.com/conformal/btcchain/log.go UseLogger 0.00% (0/1)
|
||||||
|
github.com/conformal/btcchain/log.go newLogClosure 0.00% (0/1)
|
||||||
|
github.com/conformal/btcchain ------------------------------------- 55.94% (697/1246)
|
||||||
|
|
||||||
|
|
35
validate.go
35
validate.go
|
@ -711,6 +711,15 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int64, txStore TxStore) (in
|
||||||
// checkConnectBlock performs several checks to confirm connecting the passed
|
// checkConnectBlock performs several checks to confirm connecting the passed
|
||||||
// block to the main chain (including whatever reorganization might be necessary
|
// block to the main chain (including whatever reorganization might be necessary
|
||||||
// to get this node to the main chain) does not violate any rules.
|
// to get this node to the main chain) does not violate any rules.
|
||||||
|
//
|
||||||
|
// The CheckConnectBlock function makes use of this function to perform the
|
||||||
|
// bulk of its work. The only difference is this function accepts a node which
|
||||||
|
// may or may not require reorganization to connect it to the main chain whereas
|
||||||
|
// CheckConnectBlock creates a new node which specifically connects to the end
|
||||||
|
// of the current main chain and then calls this function with that node.
|
||||||
|
//
|
||||||
|
// See the comments for CheckConnectBlock for some examples of the type of
|
||||||
|
// checks performed by this function.
|
||||||
func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block) error {
|
func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block) error {
|
||||||
// If the side chain blocks end up in the database, a call to
|
// If the side chain blocks end up in the database, a call to
|
||||||
// checkBlockSanity should be done here in case a previous version
|
// checkBlockSanity should be done here in case a previous version
|
||||||
|
@ -718,12 +727,9 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block) er
|
||||||
// implementation only currently uses memory for the side chain blocks,
|
// implementation only currently uses memory for the side chain blocks,
|
||||||
// it isn't currently necessary.
|
// it isn't currently necessary.
|
||||||
|
|
||||||
// TODO(davec): Keep a flag if this has already been done to avoid
|
|
||||||
// multiple runs.
|
|
||||||
|
|
||||||
// The coinbase for the Genesis block is not spendable, so just return
|
// The coinbase for the Genesis block is not spendable, so just return
|
||||||
// now.
|
// now.
|
||||||
if node.hash.IsEqual(b.chainParams().GenesisHash) {
|
if node.hash.IsEqual(b.chainParams().GenesisHash) && b.bestChain == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,3 +870,24 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block) er
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckConnectBlock performs several checks to confirm connecting the passed
|
||||||
|
// block to the main chain does not violate any rules. An example of some of
|
||||||
|
// the checks performed are ensuring connecting the block would not cause any
|
||||||
|
// duplicate transaction hashes for old transactions that aren't already fully
|
||||||
|
// spent, double spends, exceeding the maximum allowed signature operations
|
||||||
|
// per block, invalid values in relation to the expected block subisidy, or
|
||||||
|
// fail transaction script validation.
|
||||||
|
//
|
||||||
|
// This function is NOT safe for concurrent access.
|
||||||
|
func (b *BlockChain) CheckConnectBlock(block *btcutil.Block) error {
|
||||||
|
prevNode := b.bestChain
|
||||||
|
blockSha, _ := block.Sha()
|
||||||
|
newNode := newBlockNode(&block.MsgBlock().Header, blockSha, block.Height())
|
||||||
|
if prevNode != nil {
|
||||||
|
newNode.parent = prevNode
|
||||||
|
newNode.workSum.Add(prevNode.workSum, newNode.workSum)
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.checkConnectBlock(newNode, block)
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,30 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TestCheckConnectBlock tests the CheckConnectBlock function to ensure it
|
||||||
|
// fails
|
||||||
|
func TestCheckConnectBlock(t *testing.T) {
|
||||||
|
// Create a new database and chain instance to run tests against.
|
||||||
|
chain, teardownFunc, err := chainSetup("checkconnectblock")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to setup chain instance: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer teardownFunc()
|
||||||
|
|
||||||
|
err = chain.GenerateInitialIndex()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GenerateInitialIndex: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The genesis block should fail to connect since it's already
|
||||||
|
// inserted.
|
||||||
|
err = chain.CheckConnectBlock(btcutil.NewBlock(&btcwire.GenesisBlock))
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("CheckConnectBlock: Did not received expected error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCheckBlockSanity(t *testing.T) {
|
func TestCheckBlockSanity(t *testing.T) {
|
||||||
powLimit := btcchain.ChainParams(btcwire.MainNet).PowLimit
|
powLimit := btcchain.ChainParams(btcwire.MainNet).PowLimit
|
||||||
block := btcutil.NewBlock(&Block100000)
|
block := btcutil.NewBlock(&Block100000)
|
||||||
|
|
Loading…
Reference in a new issue