From fed0bd3ed31e9811255942c126b32d69230ddd76 Mon Sep 17 00:00:00 2001 From: Simon B Date: Mon, 20 Nov 2017 01:59:07 +0100 Subject: [PATCH] [CONSENSUS] Limit number of inputs in a block #261 (#328) * Limit number of inputs in a block, fix #261 * MAX_BLOCK_INPUTS = 300_000 // IO-time bound DoS protection. 5MB/s disk random reads gives ~150k UTXO lookups/s, so set limit at 300k UTXO inputs --- core/src/consensus.rs | 5 +++++ core/src/core/transaction.rs | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/core/src/consensus.rs b/core/src/consensus.rs index ee3e36b7a..8fd1610a5 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -85,10 +85,15 @@ pub const BLOCK_KERNEL_WEIGHT: usize = 2; /// Total maximum block weight pub const MAX_BLOCK_WEIGHT: usize = 80_000; +/// Maximum inputs for a block (issue#261) +/// Hundreds of inputs + 1 output might be slow to validate (issue#258) +pub const MAX_BLOCK_INPUTS: usize = 300_000; // soft fork down when too_high + /// Whether a block exceeds the maximum acceptable weight pub fn exceeds_weight(input_len: usize, output_len: usize, kernel_len: usize) -> bool { input_len * BLOCK_INPUT_WEIGHT + output_len * BLOCK_OUTPUT_WEIGHT + kernel_len * BLOCK_KERNEL_WEIGHT > MAX_BLOCK_WEIGHT + || input_len > MAX_BLOCK_INPUTS } /// Fork every 250,000 blocks for first 2 years, simple number and just a diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 44d575656..ee7db3d5d 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -22,6 +22,7 @@ use util::secp::pedersen::{Commitment, RangeProof}; use std::cmp::Ordering; use std::ops; +use consensus; use core::Committed; use core::hash::Hashed; use core::pmmr::Summable; @@ -72,6 +73,8 @@ pub enum Error { /// Underlying Secp256k1 error (signature validation or invalid public /// key typically) Secp(secp::Error), + /// Restrict number of incoming inputs + TooManyInputs, } impl From for Error { @@ -347,6 +350,9 @@ impl Transaction { if self.fee & 1 != 0 { return Err(Error::OddFee); } + if self.inputs.len() > consensus::MAX_BLOCK_INPUTS { + return Err(Error::TooManyInputs); + } for out in &self.outputs { out.verify_proof()?; }