diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index cc55c97a..8551caaa 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -347,12 +347,26 @@ class Chain extends AsyncEmitter { if (this.options.spv) return this.state; + // Check merkle root. + if (flags & common.flags.VERIFY_BODY) { + assert(typeof block.createMerkleRoot === 'function'); + + const root = block.createMerkleRoot('hex'); + + if (!root || block.merkleRoot !== root) { + throw new VerifyError(block, + 'invalid', + 'bad-txnmrklroot', + 100); + } + + flags &= ~common.flags.VERIFY_BODY; + } + // Once segwit is active, we will still // need to check for block mutability. if (!block.hasWitness() && !block.getCommitmentHash()) return new DeploymentState(); - - flags &= ~common.flags.VERIFY_BODY; } // Non-contextual checks. diff --git a/lib/primitives/block.js b/lib/primitives/block.js index 2749a77e..f620df72 100644 --- a/lib/primitives/block.js +++ b/lib/primitives/block.js @@ -416,17 +416,6 @@ class Block extends AbstractBlock { */ checkBody() { - // Check merkle root. - const root = this.createMerkleRoot('hex'); - - // If the merkle is mutated, - // we have duplicate txs. - if (!root) - return [false, 'bad-txns-duplicate', 100]; - - if (this.merkleRoot !== root) - return [false, 'bad-txnmrklroot', 100]; - // Check base size. if (this.txs.length === 0 || this.txs.length > consensus.MAX_BLOCK_SIZE @@ -438,6 +427,17 @@ class Block extends AbstractBlock { if (this.txs.length === 0 || !this.txs[0].isCoinbase()) return [false, 'bad-cb-missing', 100]; + // Check merkle root. + const root = this.createMerkleRoot('hex'); + + // If the merkle is mutated, + // we have duplicate txs. + if (!root) + return [false, 'bad-txns-duplicate', 100]; + + if (this.merkleRoot !== root) + return [false, 'bad-txnmrklroot', 100]; + // Test all transactions. const scale = consensus.WITNESS_SCALE_FACTOR;