diff --git a/network/src/consensus.rs b/network/src/consensus.rs index ce7ebfdd..ce3a30be 100644 --- a/network/src/consensus.rs +++ b/network/src/consensus.rs @@ -11,7 +11,8 @@ pub const BITCOIN_CASH_FORK_BLOCK: u32 = 478559; // https://blockchair.com/bitco pub mod segwit { /// The maximum allowed weight for a block, see BIP 141 (network rule) pub const MAX_BLOCK_WEIGHT: usize = 4_000_000; - + /// The maximum allowed number of signature check operations in a block (network rule) + pub const MAX_BLOCK_SIGOPS_COST: usize = 80_000; /// Witness scale factor. pub const WITNESS_SCALE_FACTOR: usize = 4; } @@ -217,6 +218,18 @@ impl ConsensusFork { ConsensusFork::NoFork | ConsensusFork::SegWit2x(_) | ConsensusFork::BitcoinCash(_) => 20_000, } } + + pub fn check_block_sigops(&self, sigops: usize, height: u32, block_size: usize, deployments: &Deployments) -> bool { + match *self { + // according to REQ-5: max_block_sigops = 20000 * ceil((max(blocksize_bytes, 1000000) / 1000000)) + ConsensusFork::BitcoinCash(fork_height) if height >= fork_height && block_size > 1_000_000 => + sigops <= 20_000 * (max(block_size, 1_000_000) / 1_000_000), + ConsensusFork::NoFork | ConsensusFork::SegWit2x(_) if deployments.is_active("segwit") => + sigops * segwit::WITNESS_SCALE_FACTOR <= segwit::MAX_BLOCK_SIGOPS_COST, + ConsensusFork::NoFork | ConsensusFork::SegWit2x(_) | ConsensusFork::BitcoinCash(_) => + sigops <= 20_000, + } + } } #[cfg(test)] diff --git a/verification/src/accept_block.rs b/verification/src/accept_block.rs index fce40386..16b248e8 100644 --- a/verification/src/accept_block.rs +++ b/verification/src/accept_block.rs @@ -110,11 +110,14 @@ impl<'a> BlockSerializedSize<'a> { let is_segwit_active = self.deployments.is_active("segwit"); if is_segwit_active { - // TODO: block.vtx.size() * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT + if self.block.transactions.len() * segwit::WITNESS_SCALE_FACTOR > segwit::MAX_BLOCK_WEIGHT { + return Err(Error::Weight); + } + let size_with_witness = self.block.size_with_witness(); let weight = size * (segwit::WITNESS_SCALE_FACTOR - 1) + size_with_witness; if weight > segwit::MAX_BLOCK_WEIGHT { - return Err(Error::Weight(weight)); + return Err(Error::Weight); } } Ok(()) diff --git a/verification/src/error.rs b/verification/src/error.rs index 16d23dc6..f611dcbb 100644 --- a/verification/src/error.rs +++ b/verification/src/error.rs @@ -37,7 +37,7 @@ pub enum Error { /// Block size is invalid Size(usize), /// Block weight is invalid - Weight(usize), + Weight, /// Block transactions are not final. NonFinalBlock, /// Old version block.