diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 21624159..e510fd5d 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1905,6 +1905,15 @@ func (b *BlockChain) initThresholdCaches() error { "change. This might take a while...") } + // Get the previous block node. This function is used over simply + // accessing b.bestNode.parent directly as it will dynamically create + // previous block nodes as needed. This helps allow only the pieces of + // the chain that are needed to remain in memory. + prevNode, err := b.getPrevNodeFromNode(b.bestNode) + if err != nil { + return err + } + // Initialize the warning and deployment caches by calculating the // threshold state for each of them. This will ensure the caches are // populated and any states that needed to be recalculated due to @@ -1912,7 +1921,7 @@ func (b *BlockChain) initThresholdCaches() error { for bit := uint32(0); bit < vbNumBits; bit++ { checker := bitConditionChecker{bit: bit, chain: b} cache := &b.warningCaches[bit] - _, err := b.thresholdState(b.bestNode, checker, cache) + _, err := b.thresholdState(prevNode, checker, cache) if err != nil { return err } @@ -1921,7 +1930,7 @@ func (b *BlockChain) initThresholdCaches() error { deployment := &b.chainParams.Deployments[id] cache := &b.deploymentCaches[id] checker := deploymentChecker{deployment: deployment, chain: b} - _, err := b.thresholdState(b.bestNode, checker, cache) + _, err := b.thresholdState(prevNode, checker, cache) if err != nil { return err } diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index e7620be9..f1ca8d19 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -141,9 +141,9 @@ func newThresholdCaches(numCaches uint32) []thresholdStateCache { return caches } -// thresholdState returns the current rule change threshold state for the given -// node and deployment ID. The cache is used to ensure the threshold states for -// previous windows are only calculated once. +// thresholdState returns the current rule change threshold state for the block +// AFTER the given node and deployment ID. The cache is used to ensure the +// threshold states for previous windows are only calculated once. // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdConditionChecker, cache *thresholdStateCache) (ThresholdState, error) { @@ -305,7 +305,7 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit } // ThresholdState returns the current rule change threshold state of the given -// deployment ID for the end of the current best chain. +// deployment ID for the block AFTER then end of the current best chain. // // This function is safe for concurrent access. func (b *BlockChain) ThresholdState(deploymentID uint32) (ThresholdState, error) { diff --git a/blockchain/versionbits.go b/blockchain/versionbits.go index c2ad2cde..4da737d9 100644 --- a/blockchain/versionbits.go +++ b/blockchain/versionbits.go @@ -244,12 +244,21 @@ func (b *BlockChain) CalcNextBlockVersion() (int32, error) { // // This function MUST be called with the chain state lock held (for writes) func (b *BlockChain) warnUnknownRuleActivations(node *blockNode) error { + // Get the previous block node. This function is used over simply + // accessing node.parent directly as it will dynamically create previous + // block nodes as needed. This helps allow only the pieces of the chain + // that are needed to remain in memory. + prevNode, err := b.getPrevNodeFromNode(node) + if err != nil { + return err + } + // Warn if any unknown new rules are either about to activate or have // already been activated. for bit := uint32(0); bit < vbNumBits; bit++ { checker := bitConditionChecker{bit: bit, chain: b} cache := &b.warningCaches[bit] - state, err := b.thresholdState(node, checker, cache) + state, err := b.thresholdState(prevNode, checker, cache) if err != nil { return err }