From c0e134a36ea56a307391cc89b87abf3b1214204c Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 13 Dec 2016 22:01:15 +0100 Subject: [PATCH 1/5] verification of 1000-transaction blocks --- Cargo.lock | 2 + bencher/Cargo.toml | 2 + bencher/src/main.rs | 5 ++ bencher/src/verifier.rs | 95 ++++++++++++++++++++++++++++++ verification/src/chain_verifier.rs | 1 - 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 bencher/src/verifier.rs diff --git a/Cargo.lock b/Cargo.lock index e47785a4..ae8c6818 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "bencher" version = "0.1.0" dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "chain 0.1.0", "db 0.1.0", "ethcore-devtools 1.3.0", + "network 0.1.0", "primitives 0.1.0", "test-data 0.1.0", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/bencher/Cargo.toml b/bencher/Cargo.toml index 0aec1566..3c1521a3 100644 --- a/bencher/Cargo.toml +++ b/bencher/Cargo.toml @@ -8,11 +8,13 @@ description = "Parity bitcoin client." [dependencies] db = { path = "../db" } verification = { path = "../verification" } +network = { path = "../network" } chain = { path = "../chain" } primitives = { path = "../primitives" } ethcore-devtools = { path = "../devtools" } test-data = { path = "../test-data" } time = "*" +byteorder = "0.5" [[bin]] path = "src/main.rs" diff --git a/bencher/src/main.rs b/bencher/src/main.rs index e37f119e..bd177364 100644 --- a/bencher/src/main.rs +++ b/bencher/src/main.rs @@ -3,8 +3,12 @@ extern crate chain; extern crate ethcore_devtools as devtools; extern crate test_data; extern crate time; +extern crate verification; +extern crate network; +extern crate byteorder; mod database; +mod verifier; use time::{PreciseTime, Duration}; use std::io::Write; @@ -70,4 +74,5 @@ fn main() { benchmark!(database::write); benchmark!(database::reorg_short); benchmark!(database::write_heavy); + benchmark!(verifier::main); } diff --git a/bencher/src/verifier.rs b/bencher/src/verifier.rs new file mode 100644 index 00000000..32b26114 --- /dev/null +++ b/bencher/src/verifier.rs @@ -0,0 +1,95 @@ +use std::sync::Arc; +use devtools::RandomTempPath; +use db::{Storage, BlockStapler, IndexedBlock}; +use verification::{BackwardsCompatibleChainVerifier as ChainVerifier, Verify}; +use network::Magic; +use test_data; +use byteorder::{LittleEndian, ByteOrder}; + +use super::Benchmark; + +// 1. write BLOCKS_INITIAL blocks with 1 transaction each +// 2. verify blocks that has transaction each with output each, +// spending outputs from last blocks +pub fn main(benchmark: &mut Benchmark) { + // params + const BLOCKS_INITIAL: usize = 200200; + const BLOCKS: usize = 10; + const TRANSACTIONS: usize = 2000; + const OUTPUTS: usize = 10; + + benchmark.samples(BLOCKS); + + assert!(BLOCKS_INITIAL - 100 > BLOCKS * OUTPUTS * TRANSACTIONS, + "There will be not enough initial blocks to continue this bench"); + + // test setup + let path = RandomTempPath::create_dir(); + let store = Arc::new(Storage::new(path.as_path()).unwrap()); + + let genesis = test_data::genesis(); + store.insert_block(&genesis).unwrap(); + + let genesis = test_data::genesis(); + store.insert_block(&genesis).unwrap(); + + let mut rolling_hash = genesis.hash(); + let mut blocks: Vec = Vec::new(); + + for x in 0..BLOCKS_INITIAL { + let mut coinbase_nonce = [0u8;8]; + LittleEndian::write_u64(&mut coinbase_nonce[..], x as u64); + let next_block = test_data::block_builder() + .transaction() + .input() + .coinbase() + .signature_bytes(coinbase_nonce.to_vec().into()) + .build() + .output().value(5000000000).build() + .build() + .merkled_header() + .parent(rolling_hash.clone()) + .nonce(x as u32) + .build() + .build(); + rolling_hash = next_block.hash(); + blocks.push(next_block.into()); + } + for block in blocks.iter() { store.insert_indexed_block(block).unwrap(); } + + let mut verification_blocks: Vec = Vec::new(); + for b in 0..BLOCKS { + let mut builder = test_data::block_builder() + .transaction() + .coinbase() + .output().value((b*b+(BLOCKS-b)) as u64).build() + .build(); + + for t in 0..TRANSACTIONS { + let mut tx_builder = builder.transaction(); + + for o in 0..OUTPUTS { + let parent_hash = blocks[(b*TRANSACTIONS*OUTPUTS + t * OUTPUTS + o)].transactions[0].hash.clone(); + + tx_builder = tx_builder + .input() + .hash(parent_hash) + .index(0) + .build() + } + + builder = tx_builder.output().value(5000).build().build() + } + + verification_blocks.push(builder.merkled_header().parent(rolling_hash.clone()).build().build().into()); + } + + let chain_verifier = ChainVerifier::new(store.clone(), Magic::Mainnet).pow_skip(); + + // bench + benchmark.start(); + for block in verification_blocks.iter() { + chain_verifier.verify(block).unwrap(); + } + benchmark.stop(); +} diff --git a/verification/src/chain_verifier.rs b/verification/src/chain_verifier.rs index 3fa700e3..44dba1ec 100644 --- a/verification/src/chain_verifier.rs +++ b/verification/src/chain_verifier.rs @@ -42,7 +42,6 @@ impl BackwardsCompatibleChainVerifier { } } - #[cfg(test)] pub fn pow_skip(mut self) -> Self { self.skip_pow = true; self From 82189b74265d712093082c148473c73cf25d29b5 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 13 Dec 2016 22:05:30 +0100 Subject: [PATCH 2/5] remove copy-paste artifact --- bencher/src/verifier.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/bencher/src/verifier.rs b/bencher/src/verifier.rs index 32b26114..0e8af22c 100644 --- a/bencher/src/verifier.rs +++ b/bencher/src/verifier.rs @@ -30,9 +30,6 @@ pub fn main(benchmark: &mut Benchmark) { let genesis = test_data::genesis(); store.insert_block(&genesis).unwrap(); - let genesis = test_data::genesis(); - store.insert_block(&genesis).unwrap(); - let mut rolling_hash = genesis.hash(); let mut blocks: Vec = Vec::new(); From b67f33ce5b990f294178fa812166a920b44c8b32 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 13 Dec 2016 23:22:36 +0100 Subject: [PATCH 3/5] database drop --- bencher/src/verifier.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/bencher/src/verifier.rs b/bencher/src/verifier.rs index 0e8af22c..a124983f 100644 --- a/bencher/src/verifier.rs +++ b/bencher/src/verifier.rs @@ -25,10 +25,8 @@ pub fn main(benchmark: &mut Benchmark) { // test setup let path = RandomTempPath::create_dir(); - let store = Arc::new(Storage::new(path.as_path()).unwrap()); let genesis = test_data::genesis(); - store.insert_block(&genesis).unwrap(); let mut rolling_hash = genesis.hash(); let mut blocks: Vec = Vec::new(); @@ -52,7 +50,12 @@ pub fn main(benchmark: &mut Benchmark) { rolling_hash = next_block.hash(); blocks.push(next_block.into()); } - for block in blocks.iter() { store.insert_indexed_block(block).unwrap(); } + + { + let store = Arc::new(Storage::new(path.as_path()).unwrap()); + store.insert_block(&genesis).unwrap(); + for block in blocks.iter() { store.insert_indexed_block(block).unwrap(); } + } let mut verification_blocks: Vec = Vec::new(); for b in 0..BLOCKS { @@ -81,6 +84,9 @@ pub fn main(benchmark: &mut Benchmark) { verification_blocks.push(builder.merkled_header().parent(rolling_hash.clone()).build().build().into()); } + + let store = Arc::new(Storage::new(path.as_path()).unwrap()); + let chain_verifier = ChainVerifier::new(store.clone(), Magic::Mainnet).pow_skip(); // bench From 5017956dbc8f0fef51b95f550e3cb3c9e3f2393c Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 13 Dec 2016 23:26:39 +0100 Subject: [PATCH 4/5] move overflow into separate error type --- verification/src/accept_block.rs | 12 ++++++++++-- verification/src/error.rs | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/verification/src/accept_block.rs b/verification/src/accept_block.rs index 5e158a33..9dfaaf59 100644 --- a/verification/src/accept_block.rs +++ b/verification/src/accept_block.rs @@ -127,8 +127,16 @@ impl<'a> BlockRule for BlockCoinbaseClaim<'a> { let claim = self.block.transactions[0].raw.total_spends(); let (fees, overflow) = available.overflowing_sub(spends); - let (reward, overflow2) = fees.overflowing_add(block_reward_satoshi(self.height)); - if overflow || overflow2 || claim > reward { + if overflow { + return Err(Error::TransactionFeesOverflow); + } + + let (reward, overflow) = fees.overflowing_add(block_reward_satoshi(self.height)); + if overflow { + return Err(Error::TransactionFeeAndRewardOverflow); + } + + if claim > reward { Err(Error::CoinbaseOverspend { expected_max: reward, actual: claim }) } else { Ok(()) diff --git a/verification/src/error.rs b/verification/src/error.rs index 3bbfb1e6..72b2f8f0 100644 --- a/verification/src/error.rs +++ b/verification/src/error.rs @@ -36,6 +36,10 @@ pub enum Error { NonFinalBlock, /// Old version block. OldVersionBlock, + /// Sum of the transaction fees in block + coinbase reward exceeds u64::max + TransactionFeeAndRewardOverflow, + /// Sum of the transaction fees in block exceeds u64::max + TransactionFeesOverflow, } #[derive(Debug, PartialEq)] From 79cc2f1b4e5cae683b03022f9746939550780328 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 14 Dec 2016 12:57:47 +0100 Subject: [PATCH 5/5] make satoshi --- bencher/src/verifier.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bencher/src/verifier.rs b/bencher/src/verifier.rs index a124983f..5628ce02 100644 --- a/bencher/src/verifier.rs +++ b/bencher/src/verifier.rs @@ -59,10 +59,12 @@ pub fn main(benchmark: &mut Benchmark) { let mut verification_blocks: Vec = Vec::new(); for b in 0..BLOCKS { + let mut coinbase_nonce = [0u8;8]; + LittleEndian::write_u64(&mut coinbase_nonce[..], (b + BLOCKS_INITIAL) as u64); let mut builder = test_data::block_builder() .transaction() - .coinbase() - .output().value((b*b+(BLOCKS-b)) as u64).build() + .input().coinbase().signature_bytes(coinbase_nonce.to_vec().into()).build() + .output().value(5000000000).build() .build(); for t in 0..TRANSACTIONS { @@ -73,12 +75,12 @@ pub fn main(benchmark: &mut Benchmark) { tx_builder = tx_builder .input() - .hash(parent_hash) - .index(0) - .build() + .hash(parent_hash) + .index(0) + .build() } - builder = tx_builder.output().value(5000).build().build() + builder = tx_builder.output().value(5000000000000).build().build() } verification_blocks.push(builder.merkled_header().parent(rolling_hash.clone()).build().build().into());