blockchain: Correct startup threshold state warns.

The thresholdState and deploymentState functions expect the block node
for the block prior to which the threshold state is calculated, however
the startup code which checked the threshold states was using the
current best node instead of its parent.

While here, also update the comments and rename a couple of variables to
help make this fact more clear.
This commit is contained in:
Dave Collins 2016-12-02 22:54:04 -06:00
parent bc576b13b4
commit 712399c0db
No known key found for this signature in database
GPG key ID: B8904D9D9C93D1F2
3 changed files with 25 additions and 7 deletions

View file

@ -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
}

View file

@ -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) {

View file

@ -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
}