diff --git a/blockchain/scriptval.go b/blockchain/scriptval.go index 33d31adc..fc82ed7c 100644 --- a/blockchain/scriptval.go +++ b/blockchain/scriptval.go @@ -249,6 +249,10 @@ func checkBlockScripts(block *btcutil.Block, utxoView *UtxoViewpoint, scriptFlags txscript.ScriptFlags, sigCache *txscript.SigCache, hashCache *txscript.HashCache) error { + // First determine if segwit is active according to the scriptFlags. If + // it isn't then we don't need to interact with the HashCache. + segwitActive := scriptFlags&txscript.ScriptVerifyWitness == txscript.ScriptVerifyWitness + // Collect all of the transaction inputs and required information for // validation for all transactions in the block into a single slice. numInputs := 0 @@ -308,7 +312,7 @@ func checkBlockScripts(block *btcutil.Block, utxoView *UtxoViewpoint, // If the HashCache is present, once we have validated the block, we no // longer need the cached hashes for these transactions, so we purge // them from the cache. - if hashCache != nil { + if segwitActive && hashCache != nil { for _, tx := range block.Transactions() { hashCache.PurgeSigHashes(tx.Hash()) } diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index 5007a043..f9b736ea 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -343,7 +343,6 @@ func (b *BlockChain) IsDeploymentActive(deploymentID uint32) (bool, error) { // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) deploymentState(prevNode *blockNode, deploymentID uint32) (ThresholdState, error) { - if deploymentID > uint32(len(b.chainParams.Deployments)) { return ThresholdFailed, DeploymentError(deploymentID) } diff --git a/blockchain/validate.go b/blockchain/validate.go index 8fb33df7..64bbfe54 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -537,17 +537,6 @@ func checkBlockSanity(block *btcutil.Block, powLimit *big.Int, timeSource Median return ruleError(ErrBadMerkleRoot, str) } - // Next, validate the witness commitment (if any) within the block. - // This involves asserting that if the coinbase contains the special - // commitment output, then this merkle root matches a computed merkle - // root of all the wtxid's of the transactions within the block. In - // addition, various other checks against the coinbase's witness stack. - // TODO(roasbeef): only perform this check if we expect block to have a - // witness commitment - if err := ValidateWitnessCommitment(block); err != nil { - return err - } - // Check for duplicate transactions. This check will be fairly quick // since the transaction hashes are already cached due to building the // merkle tree above. @@ -1076,8 +1065,15 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi // after the timestamp defined by txscript.Bip16Activation. See // https://en.bitcoin.it/wiki/BIP_0016 for more details. enforceBIP0016 := node.timestamp >= txscript.Bip16Activation.Unix() - // TODO(roasbeef): should check flag, consult bip 9 log etc - enforceSegWit := true + + // Query for the Version Bits state for the segwit soft-fork + // deployment. If segwit is active, we'll switch over to enforcing all + // the new rules. + segwitState, err := b.deploymentState(node.parent, chaincfg.DeploymentSegwit) + if err != nil { + return err + } + enforceSegWit := segwitState == ThresholdActive // The number of signature operations must be less than the maximum // allowed per block. Note that the preliminary sanity checks on a @@ -1105,7 +1101,6 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi lastSigOpCost := totalSigOpCost totalSigOpCost += sigOpCost if totalSigOpCost < lastSigOpCost || totalSigOpCost > MaxBlockSigOpsCost { - // TODO(roasbeef): modify error str := fmt.Sprintf("block contains too many "+ "signature operations - got %v, max %v", totalSigOpCost, MaxBlockSigOpsCost) @@ -1239,9 +1234,12 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi } } - // TODO(roasbeef): check bip9 for segwit here, others also - scriptFlags |= txscript.ScriptVerifyWitness - scriptFlags |= txscript.ScriptStrictMultiSig + // Enforce the segwit soft-fork package once the soft-fork has shifted + // into the "active" version bits state. + if enforceSegWit { + scriptFlags |= txscript.ScriptVerifyWitness + scriptFlags |= txscript.ScriptStrictMultiSig + } // Now that the inexpensive checks are done and have passed, verify the // transactions are actually allowed to spend the coins by running the