blockchain: guard enforcement of segwit rules by a BIP0009 state check
This commit updates the new segwit validation logic within block validation to be guarded by an initial check to the version bits state before conditionally enforcing the logic based off of the state.
This commit is contained in:
parent
b1893ed228
commit
728c0a4398
3 changed files with 20 additions and 19 deletions
|
@ -249,6 +249,10 @@ func checkBlockScripts(block *btcutil.Block, utxoView *UtxoViewpoint,
|
||||||
scriptFlags txscript.ScriptFlags, sigCache *txscript.SigCache,
|
scriptFlags txscript.ScriptFlags, sigCache *txscript.SigCache,
|
||||||
hashCache *txscript.HashCache) error {
|
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
|
// Collect all of the transaction inputs and required information for
|
||||||
// validation for all transactions in the block into a single slice.
|
// validation for all transactions in the block into a single slice.
|
||||||
numInputs := 0
|
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
|
// If the HashCache is present, once we have validated the block, we no
|
||||||
// longer need the cached hashes for these transactions, so we purge
|
// longer need the cached hashes for these transactions, so we purge
|
||||||
// them from the cache.
|
// them from the cache.
|
||||||
if hashCache != nil {
|
if segwitActive && hashCache != nil {
|
||||||
for _, tx := range block.Transactions() {
|
for _, tx := range block.Transactions() {
|
||||||
hashCache.PurgeSigHashes(tx.Hash())
|
hashCache.PurgeSigHashes(tx.Hash())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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).
|
// This function MUST be called with the chain state lock held (for writes).
|
||||||
func (b *BlockChain) deploymentState(prevNode *blockNode,
|
func (b *BlockChain) deploymentState(prevNode *blockNode,
|
||||||
deploymentID uint32) (ThresholdState, error) {
|
deploymentID uint32) (ThresholdState, error) {
|
||||||
|
|
||||||
if deploymentID > uint32(len(b.chainParams.Deployments)) {
|
if deploymentID > uint32(len(b.chainParams.Deployments)) {
|
||||||
return ThresholdFailed, DeploymentError(deploymentID)
|
return ThresholdFailed, DeploymentError(deploymentID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -537,17 +537,6 @@ func checkBlockSanity(block *btcutil.Block, powLimit *big.Int, timeSource Median
|
||||||
return ruleError(ErrBadMerkleRoot, str)
|
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
|
// Check for duplicate transactions. This check will be fairly quick
|
||||||
// since the transaction hashes are already cached due to building the
|
// since the transaction hashes are already cached due to building the
|
||||||
// merkle tree above.
|
// 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
|
// after the timestamp defined by txscript.Bip16Activation. See
|
||||||
// https://en.bitcoin.it/wiki/BIP_0016 for more details.
|
// https://en.bitcoin.it/wiki/BIP_0016 for more details.
|
||||||
enforceBIP0016 := node.timestamp >= txscript.Bip16Activation.Unix()
|
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
|
// The number of signature operations must be less than the maximum
|
||||||
// allowed per block. Note that the preliminary sanity checks on a
|
// 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
|
lastSigOpCost := totalSigOpCost
|
||||||
totalSigOpCost += sigOpCost
|
totalSigOpCost += sigOpCost
|
||||||
if totalSigOpCost < lastSigOpCost || totalSigOpCost > MaxBlockSigOpsCost {
|
if totalSigOpCost < lastSigOpCost || totalSigOpCost > MaxBlockSigOpsCost {
|
||||||
// TODO(roasbeef): modify error
|
|
||||||
str := fmt.Sprintf("block contains too many "+
|
str := fmt.Sprintf("block contains too many "+
|
||||||
"signature operations - got %v, max %v",
|
"signature operations - got %v, max %v",
|
||||||
totalSigOpCost, MaxBlockSigOpsCost)
|
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
|
// Enforce the segwit soft-fork package once the soft-fork has shifted
|
||||||
scriptFlags |= txscript.ScriptVerifyWitness
|
// into the "active" version bits state.
|
||||||
scriptFlags |= txscript.ScriptStrictMultiSig
|
if enforceSegWit {
|
||||||
|
scriptFlags |= txscript.ScriptVerifyWitness
|
||||||
|
scriptFlags |= txscript.ScriptStrictMultiSig
|
||||||
|
}
|
||||||
|
|
||||||
// Now that the inexpensive checks are done and have passed, verify the
|
// Now that the inexpensive checks are done and have passed, verify the
|
||||||
// transactions are actually allowed to spend the coins by running the
|
// transactions are actually allowed to spend the coins by running the
|
||||||
|
|
Loading…
Reference in a new issue