From 533fdd632a6291e4eaa19e298e2d836ad3b1a565 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 20:32:53 +0400 Subject: [PATCH 01/19] initial --- src/blockchain.rs | 6 ++++++ src/tests/helpers.rs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/src/blockchain.rs b/src/blockchain.rs index fb3755ff2..7323de827 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -769,4 +769,10 @@ mod tests { assert_eq!(bc.best_block_hash(), b1_hash); } } + + #[test] + fn can_consist_of_random_blocks() { + let bc = generate_dummy_blockchain(100); + assert_eq!(bc.best_block_hash(), 0); + } } diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index a566392cc..38aaafe5f 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -4,6 +4,7 @@ use super::test_common::*; use std::path::PathBuf; use spec::*; use std::fs::{remove_dir_all}; +use blockchain:{BlockChain}; pub struct RandomTempPath { @@ -77,4 +78,10 @@ pub fn generate_dummy_client(block_number: usize) -> Arc { client.flush_queue(); client.import_verified_blocks(&IoChannel::disconnected()); client +} + +pub fn generate_dummy_blockchain(block_number: usize) -> BlockChain { + let temp = RandomTempPath::new(); + let bc = BlockChain::new(&("fffffff".from_hex().unwrap()), temp.as_path()); + bc } \ No newline at end of file From 5818db9d0ead770c82cb79b9ddcbb7eb6d73b326 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 20:38:16 +0400 Subject: [PATCH 02/19] merge previous test changes --- src/tests/helpers.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 38aaafe5f..a522d24fe 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -4,7 +4,7 @@ use super::test_common::*; use std::path::PathBuf; use spec::*; use std::fs::{remove_dir_all}; -use blockchain:{BlockChain}; +use blockchain::{BlockChain}; pub struct RandomTempPath { @@ -82,6 +82,7 @@ pub fn generate_dummy_client(block_number: usize) -> Arc { pub fn generate_dummy_blockchain(block_number: usize) -> BlockChain { let temp = RandomTempPath::new(); - let bc = BlockChain::new(&("fffffff".from_hex().unwrap()), temp.as_path()); + let genesis = "fffffff".from_hex().unwrap(); + let bc = BlockChain::new(&genesis, temp.as_path()); bc } \ No newline at end of file From 6d69906159e04edf756c0deeb96e670490e50b91 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 21:31:14 +0400 Subject: [PATCH 03/19] working blockhain sequence generator --- src/blockchain.rs | 6 +++--- src/tests/helpers.rs | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/blockchain.rs b/src/blockchain.rs index f0e2ff62f..bdd1ba9a2 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -765,8 +765,8 @@ mod tests { } #[test] - fn can_consist_of_random_blocks() { - let bc = generate_dummy_blockchain(100); - assert_eq!(bc.best_block_hash(), 0); + fn can_contain_arbitrary_block_sequence() { + let bc = generate_dummy_blockchain(50); + assert_eq!(bc.best_block_number(), 49); } } diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index a522d24fe..ad27f75ed 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -45,6 +45,18 @@ pub fn create_test_block(header: &Header) -> Bytes { rlp.out() } +fn create_unverifiable_block(order: usize, parent_hash: H256) -> Bytes { + let mut header = Header::new(); + header.gas_limit = x!(0); + header.difficulty = x!(order * 100); + header.timestamp = (order * 10) as u64; + header.number = order as u64; + header.parent_hash = parent_hash; + header.state_root = H256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + + create_test_block(&header) +} + pub fn generate_dummy_client(block_number: usize) -> Arc { let dir = RandomTempPath::new(); @@ -82,7 +94,14 @@ pub fn generate_dummy_client(block_number: usize) -> Arc { pub fn generate_dummy_blockchain(block_number: usize) -> BlockChain { let temp = RandomTempPath::new(); - let genesis = "fffffff".from_hex().unwrap(); - let bc = BlockChain::new(&genesis, temp.as_path()); + let bc = BlockChain::new( + &create_unverifiable_block( + 0, + H256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap()), + temp.as_path()); + + for block_order in 1..block_number { + bc.insert_block(&create_unverifiable_block(block_order, bc.best_block_hash())); + } bc } \ No newline at end of file From 797a1498c9f89ee8d25affce82098b3e59e1a6da Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 14:55:03 +0400 Subject: [PATCH 04/19] valid tests for garbage collection (presumably) which fail --- src/blockchain.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/blockchain.rs b/src/blockchain.rs index bdd1ba9a2..818447df1 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -769,4 +769,21 @@ mod tests { let bc = generate_dummy_blockchain(50); assert_eq!(bc.best_block_number(), 49); } + + #[test] + fn can_collect_garbage() { + let bc = generate_dummy_blockchain(3000); + assert_eq!(bc.best_block_number(), 2999); + let best_hash = bc.best_block_hash(); + let mut block_header = bc.block_header(&best_hash); + + while !block_header.is_none() { + block_header = bc.block_header(&block_header.unwrap().parent_hash); + } + assert!(bc.cache_size().blocks > 1024 * 1024); + + bc.collect_garbage(true); + + assert!(bc.cache_size().blocks < 1024 * 1024); + } } From 0a8e091f3ec5b00cab61f07b9b1018822156ae2f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 15:24:16 +0400 Subject: [PATCH 05/19] helper functions for extra data --- src/tests/helpers.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index ad27f75ed..703c8639b 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -45,7 +45,7 @@ pub fn create_test_block(header: &Header) -> Bytes { rlp.out() } -fn create_unverifiable_block(order: usize, parent_hash: H256) -> Bytes { +fn create_unverifiable_block_header(order: usize, parent_hash: H256) -> Header { let mut header = Header::new(); header.gas_limit = x!(0); header.difficulty = x!(order * 100); @@ -54,6 +54,23 @@ fn create_unverifiable_block(order: usize, parent_hash: H256) -> Bytes { header.parent_hash = parent_hash; header.state_root = H256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + header +} + +fn create_unverifiable_block(order: usize, parent_hash: H256) -> Bytes { + create_test_block_header(&create_unverifiable_block_header(order, parent_hash)) +} + +fn create_unverifiable_block_with_extra(order: usize, parent_hash: H256, Option extra) -> Bytes { + let mut header = create_test_block_header(order, parent_hash); + header.extra_data = match extra { + Some(extra_data) => extra_data, + None => { + let base = order as u8; + vec!([1, 2, 3]) + } + } + create_test_block(&header) } @@ -104,4 +121,6 @@ pub fn generate_dummy_blockchain(block_number: usize) -> BlockChain { bc.insert_block(&create_unverifiable_block(block_order, bc.best_block_hash())); } bc -} \ No newline at end of file +} + +pub fn generate_dummy_blockchain_with_extra(block_number: uszie \ No newline at end of file From 673daf0b29583d2b308f18704006cc913fb2e56c Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 18:38:42 +0400 Subject: [PATCH 06/19] refactored to guard --- src/blockchain.rs | 21 +++++++++- src/tests/client.rs | 27 ++++--------- src/tests/helpers.rs | 96 +++++++++++++++++++++++++++++++++++++------- 3 files changed, 109 insertions(+), 35 deletions(-) diff --git a/src/blockchain.rs b/src/blockchain.rs index 818447df1..2610407ac 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -766,13 +766,16 @@ mod tests { #[test] fn can_contain_arbitrary_block_sequence() { - let bc = generate_dummy_blockchain(50); + let bc_result = generate_dummy_blockchain(50); + let bc = bc_result.reference(); assert_eq!(bc.best_block_number(), 49); } #[test] fn can_collect_garbage() { - let bc = generate_dummy_blockchain(3000); + let bc_result = generate_dummy_blockchain(3000); + let bc = bc_result.reference(); + assert_eq!(bc.best_block_number(), 2999); let best_hash = bc.best_block_hash(); let mut block_header = bc.block_header(&best_hash); @@ -786,4 +789,18 @@ mod tests { assert!(bc.cache_size().blocks < 1024 * 1024); } + + #[test] + fn can_contain_arbitrary_block_sequence_with_extra() { + let bc_result = generate_dummy_blockchain_with_extra(25); + let bc = bc_result.reference(); + assert_eq!(bc.best_block_number(), 24); + } + + #[test] + fn can_contain_only_genesis_block() { + let bc_result = generate_dummy_empty_blockchain(); + let bc = bc_result.reference(); + assert_eq!(bc.best_block_number(), 0); + } } diff --git a/src/tests/client.rs b/src/tests/client.rs index f6d603f43..2abeceb0b 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -30,21 +30,6 @@ fn get_bad_state_dummy_block() -> Bytes { create_test_block(&block_header) } - -fn get_test_client_with_blocks(blocks: Vec) -> Arc { - let dir = RandomTempPath::new(); - let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); - for block in &blocks { - if let Err(_) = client.import_block(block.clone()) { - panic!("panic importing block which is well-formed"); - } - } - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); - client -} - - #[test] fn created() { let dir = RandomTempPath::new(); @@ -86,7 +71,8 @@ fn query_none_block() { #[test] fn query_bad_block() { - let client = get_test_client_with_blocks(vec![get_bad_state_dummy_block()]); + let client_result = get_test_client_with_blocks(vec![get_bad_state_dummy_block()]); + let client = client_result.reference(); let bad_block:Option = client.block_header_at(1); assert!(bad_block.is_none()); @@ -95,7 +81,8 @@ fn query_bad_block() { #[test] fn returns_chain_info() { let dummy_block = get_good_dummy_block(); - let client = get_test_client_with_blocks(vec![dummy_block.clone()]); + let client_result = get_test_client_with_blocks(vec![dummy_block.clone()]); + let client = client_result.reference(); let block = BlockView::new(&dummy_block); let info = client.chain_info(); assert_eq!(info.best_block_hash, block.header().hash()); @@ -103,7 +90,8 @@ fn returns_chain_info() { #[test] fn imports_block_sequence() { - let client = generate_dummy_client(6); + let client_result = generate_dummy_client(6); + let client = client_result.reference(); let block = client.block_header_at(5).unwrap(); assert!(!block.is_empty()); @@ -111,7 +99,8 @@ fn imports_block_sequence() { #[test] fn can_collect_garbage() { - let client = generate_dummy_client(100); + let client_result = generate_dummy_client(100); + let client = client_result.reference(); client.tick(); assert!(client.cache_info().blocks < 100 * 1024); } \ No newline at end of file diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 703c8639b..0fb8901fe 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -33,6 +33,18 @@ impl Drop for RandomTempPath { } } +#[allow(dead_code)] +pub struct GuardedTempResult { + result: T, + temp: RandomTempPath +} + +impl GuardedTempResult { + pub fn reference(&self) -> &T { + &self.result + } +} + pub fn get_test_spec() -> Spec { Spec::new_test() } @@ -45,7 +57,7 @@ pub fn create_test_block(header: &Header) -> Bytes { rlp.out() } -fn create_unverifiable_block_header(order: usize, parent_hash: H256) -> Header { +fn create_unverifiable_block_header(order: u32, parent_hash: H256) -> Header { let mut header = Header::new(); header.gas_limit = x!(0); header.difficulty = x!(order * 100); @@ -57,24 +69,24 @@ fn create_unverifiable_block_header(order: usize, parent_hash: H256) -> Header { header } -fn create_unverifiable_block(order: usize, parent_hash: H256) -> Bytes { - create_test_block_header(&create_unverifiable_block_header(order, parent_hash)) +fn create_unverifiable_block(order: u32, parent_hash: H256) -> Bytes { + create_test_block(&create_unverifiable_block_header(order, parent_hash)) } -fn create_unverifiable_block_with_extra(order: usize, parent_hash: H256, Option extra) -> Bytes { - let mut header = create_test_block_header(order, parent_hash); +fn create_unverifiable_block_with_extra(order: u32, parent_hash: H256, extra: Option) -> Bytes { + let mut header = create_unverifiable_block_header(order, parent_hash); header.extra_data = match extra { Some(extra_data) => extra_data, None => { - let base = order as u8; - vec!([1, 2, 3]) + let base = (order & 0x000000ff) as u8; + let generated: Vec = vec![base + 1, base + 2, base + 3]; + generated } - } - + }; create_test_block(&header) } -pub fn generate_dummy_client(block_number: usize) -> Arc { +pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { let dir = RandomTempPath::new(); let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); @@ -106,10 +118,32 @@ pub fn generate_dummy_client(block_number: usize) -> Arc { } client.flush_queue(); client.import_verified_blocks(&IoChannel::disconnected()); - client + + GuardedTempResult::> { + temp: dir, + result: client + } } -pub fn generate_dummy_blockchain(block_number: usize) -> BlockChain { + +pub fn get_test_client_with_blocks(blocks: Vec) -> GuardedTempResult> { + let dir = RandomTempPath::new(); + let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + for block in &blocks { + if let Err(_) = client.import_block(block.clone()) { + panic!("panic importing block which is well-formed"); + } + } + client.flush_queue(); + client.import_verified_blocks(&IoChannel::disconnected()); + + GuardedTempResult::> { + temp: dir, + result: client + } +} + +pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult { let temp = RandomTempPath::new(); let bc = BlockChain::new( &create_unverifiable_block( @@ -120,7 +154,41 @@ pub fn generate_dummy_blockchain(block_number: usize) -> BlockChain { for block_order in 1..block_number { bc.insert_block(&create_unverifiable_block(block_order, bc.best_block_hash())); } - bc + + GuardedTempResult:: { + temp: temp, + result: bc + } } -pub fn generate_dummy_blockchain_with_extra(block_number: uszie \ No newline at end of file +pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempResult { + let temp = RandomTempPath::new(); + let bc = BlockChain::new( + &create_unverifiable_block( + 0, + H256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap()), + temp.as_path()); + + for block_order in 1..block_number { + bc.insert_block(&create_unverifiable_block_with_extra(block_order, bc.best_block_hash(), None)); + } + + GuardedTempResult:: { + temp: temp, + result: bc + } +} + +pub fn generate_dummy_empty_blockchain() -> GuardedTempResult { + let temp = RandomTempPath::new(); + let bc = BlockChain::new( + &create_unverifiable_block( + 0, + H256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap()), + temp.as_path()); + + GuardedTempResult:: { + temp: temp, + result: bc + } +} \ No newline at end of file From 0940e5b1ababcf8b51113f1490f10c21750881a2 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 19:14:47 +0400 Subject: [PATCH 07/19] blockchain general tests final --- res/ethereum/tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/ethereum/tests b/res/ethereum/tests index c670b1d8c..e838fd909 160000 --- a/res/ethereum/tests +++ b/res/ethereum/tests @@ -1 +1 @@ -Subproject commit c670b1d8c9f09593a6758ab2c099360e16c7c25b +Subproject commit e838fd90998fc5502d0b7c9427a4c231f9a6953d From 0407ef619719b53ee2917caebd051e1986b24606 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 19:59:31 +0400 Subject: [PATCH 08/19] intendations --- src/tests/helpers.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 0fb8901fe..79dc4bf24 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -79,8 +79,8 @@ fn create_unverifiable_block_with_extra(order: u32, parent_hash: H256, extra: Op Some(extra_data) => extra_data, None => { let base = (order & 0x000000ff) as u8; - let generated: Vec = vec![base + 1, base + 2, base + 3]; - generated + let generated: Vec = vec![base + 1, base + 2, base + 3]; + generated } }; create_test_block(&header) From 39749728fefe9edfc79174e595acd14cc5c70d90 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 20:15:45 +0400 Subject: [PATCH 09/19] indentations --- src/tests/helpers.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 79dc4bf24..62a9d6252 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -69,10 +69,6 @@ fn create_unverifiable_block_header(order: u32, parent_hash: H256) -> Header { header } -fn create_unverifiable_block(order: u32, parent_hash: H256) -> Bytes { - create_test_block(&create_unverifiable_block_header(order, parent_hash)) -} - fn create_unverifiable_block_with_extra(order: u32, parent_hash: H256, extra: Option) -> Bytes { let mut header = create_unverifiable_block_header(order, parent_hash); header.extra_data = match extra { @@ -86,6 +82,10 @@ fn create_unverifiable_block_with_extra(order: u32, parent_hash: H256, extra: Op create_test_block(&header) } +fn create_unverifiable_block(order: u32, parent_hash: H256) -> Bytes { + create_test_block(&create_unverifiable_block_header(order, parent_hash)) +} + pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { let dir = RandomTempPath::new(); From 26eda382991e84d3770d87072cc606d5fd584fd2 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 20:19:55 +0400 Subject: [PATCH 10/19] h256:zero() --- src/tests/helpers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 62a9d6252..4a37b3d41 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -148,7 +148,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult Date: Thu, 28 Jan 2016 20:26:32 +0400 Subject: [PATCH 11/19] zeroes --- src/tests/helpers.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 4a37b3d41..1c1b1829d 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -64,7 +64,7 @@ fn create_unverifiable_block_header(order: u32, parent_hash: H256) -> Header { header.timestamp = (order * 10) as u64; header.number = order as u64; header.parent_hash = parent_hash; - header.state_root = H256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + header.state_root = H256::zero(); header } @@ -145,12 +145,7 @@ pub fn get_test_client_with_blocks(blocks: Vec) -> GuardedTempResult GuardedTempResult { let temp = RandomTempPath::new(); - let bc = BlockChain::new( - &create_unverifiable_block( - 0, - H256::zero()), - temp.as_path()); - + let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path()); for block_order in 1..block_number { bc.insert_block(&create_unverifiable_block(block_order, bc.best_block_hash())); } @@ -163,12 +158,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult GuardedTempResult { let temp = RandomTempPath::new(); - let bc = BlockChain::new( - &create_unverifiable_block( - 0, - H256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap()), - temp.as_path()); - + let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path()); for block_order in 1..block_number { bc.insert_block(&create_unverifiable_block_with_extra(block_order, bc.best_block_hash(), None)); } From c80018593efe3702c276ea43dd6fc693d50685b0 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 20:29:35 +0400 Subject: [PATCH 12/19] more zeroes --- src/tests/helpers.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 1c1b1829d..b63e4334b 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -171,11 +171,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempRes pub fn generate_dummy_empty_blockchain() -> GuardedTempResult { let temp = RandomTempPath::new(); - let bc = BlockChain::new( - &create_unverifiable_block( - 0, - H256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap()), - temp.as_path()); + let bc = BlockChain::new(&create_unverifiable_block(0, H256::zero()), temp.as_path()); GuardedTempResult:: { temp: temp, From 9645ba862581965173eaf77c91b05b379e4084e2 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 21:08:47 +0400 Subject: [PATCH 13/19] superfluo line --- src/tests/helpers.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index b63e4334b..3bab3fd4c 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -125,7 +125,6 @@ pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult } } - pub fn get_test_client_with_blocks(blocks: Vec) -> GuardedTempResult> { let dir = RandomTempPath::new(); let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); From 64a84b91bc14971da82f0168979ee37c91e90c92 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 22:14:07 +0400 Subject: [PATCH 14/19] queue duplicates error check --- src/block_queue.rs | 37 ++++++++++++++++++++++++++++++++++++- src/tests/client.rs | 28 ---------------------------- src/tests/helpers.rs | 30 +++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 30 deletions(-) diff --git a/src/block_queue.rs b/src/block_queue.rs index 5ce649710..08e22f799 100644 --- a/src/block_queue.rs +++ b/src/block_queue.rs @@ -292,12 +292,47 @@ mod tests { use util::*; use spec::*; use block_queue::*; + use tests::helpers::*; + use error::*; + + fn get_test_queue() -> BlockQueue { + let spec = get_test_spec(); + let engine = spec.to_engine().unwrap(); + BlockQueue::new(Arc::new(engine), IoChannel::disconnected()) + } #[test] - fn test_block_queue() { + fn can_be_created() { // TODO better test let spec = Spec::new_test(); let engine = spec.to_engine().unwrap(); let _ = BlockQueue::new(Arc::new(engine), IoChannel::disconnected()); } + + #[test] + fn can_verify_blocks() { + let mut queue = get_test_queue(); + if let Err(e) = queue.import_block(get_good_dummy_block()) { + panic!("error importing block that is valid by definition({:?})", e); + } + } + + #[test] + fn returns_error_for_duplicates() { + let mut queue = get_test_queue(); + if let Err(e) = queue.import_block(get_good_dummy_block()) { + panic!("error importing block that is valid by definition({:?})", e); + } + let duplicate_import = queue.import_block(get_good_dummy_block()); + + match duplicate_import { + Err(e) => { + match e { + ImportError::AlreadyQueued => {}, + _ => { panic!("must return AlreadyQueued error"); } + } + } + Ok(_) => { panic!("must produce error"); } + } + } } diff --git a/src/tests/client.rs b/src/tests/client.rs index 2abeceb0b..56b6e7db0 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -2,34 +2,6 @@ use client::{BlockChainClient,Client}; use super::test_common::*; use super::helpers::*; -fn get_good_dummy_block() -> Bytes { - let mut block_header = Header::new(); - let test_spec = get_test_spec(); - let test_engine = test_spec.to_engine().unwrap(); - block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); - block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); - block_header.timestamp = 40; - block_header.number = 1; - block_header.parent_hash = test_engine.spec().genesis_header().hash(); - block_header.state_root = test_engine.spec().genesis_header().state_root; - - create_test_block(&block_header) -} - -fn get_bad_state_dummy_block() -> Bytes { - let mut block_header = Header::new(); - let test_spec = get_test_spec(); - let test_engine = test_spec.to_engine().unwrap(); - block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); - block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); - block_header.timestamp = 40; - block_header.number = 1; - block_header.parent_hash = test_engine.spec().genesis_header().hash(); - block_header.state_root = x!(0xbad); - - create_test_block(&block_header) -} - #[test] fn created() { let dir = RandomTempPath::new(); diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 3bab3fd4c..f87138795 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -176,4 +176,32 @@ pub fn generate_dummy_empty_blockchain() -> GuardedTempResult { temp: temp, result: bc } -} \ No newline at end of file +} + +pub fn get_good_dummy_block() -> Bytes { + let mut block_header = Header::new(); + let test_spec = get_test_spec(); + let test_engine = test_spec.to_engine().unwrap(); + block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); + block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); + block_header.timestamp = 40; + block_header.number = 1; + block_header.parent_hash = test_engine.spec().genesis_header().hash(); + block_header.state_root = test_engine.spec().genesis_header().state_root; + + create_test_block(&block_header) +} + +pub fn get_bad_state_dummy_block() -> Bytes { + let mut block_header = Header::new(); + let test_spec = get_test_spec(); + let test_engine = test_spec.to_engine().unwrap(); + block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); + block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); + block_header.timestamp = 40; + block_header.number = 1; + block_header.parent_hash = test_engine.spec().genesis_header().hash(); + block_header.state_root = x!(0xbad); + + create_test_block(&block_header) +} From 7f21b94b973e68e7304315f3252f7239a0b632d5 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 28 Jan 2016 22:43:57 +0400 Subject: [PATCH 15/19] extra queue tests --- src/block_queue.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/block_queue.rs b/src/block_queue.rs index 08e22f799..206388042 100644 --- a/src/block_queue.rs +++ b/src/block_queue.rs @@ -310,7 +310,7 @@ mod tests { } #[test] - fn can_verify_blocks() { + fn can_import_blocks() { let mut queue = get_test_queue(); if let Err(e) = queue.import_block(get_good_dummy_block()) { panic!("error importing block that is valid by definition({:?})", e); @@ -323,8 +323,29 @@ mod tests { if let Err(e) = queue.import_block(get_good_dummy_block()) { panic!("error importing block that is valid by definition({:?})", e); } - let duplicate_import = queue.import_block(get_good_dummy_block()); + let duplicate_import = queue.import_block(get_good_dummy_block()); + match duplicate_import { + Err(e) => { + match e { + ImportError::AlreadyQueued => {}, + _ => { panic!("must return AlreadyQueued error"); } + } + } + Ok(_) => { panic!("must produce error"); } + } + } + + #[test] + fn returns_error_for_verified_duplicates() { + let mut queue = get_test_queue(); + if let Err(e) = queue.import_block(get_good_dummy_block()) { + panic!("error importing block that is valid by definition({:?})", e); + } + queue.drain(10); + queue.flush(); + + let duplicate_import = queue.import_block(get_good_dummy_block()); match duplicate_import { Err(e) => { match e { From a2f4090c059597afc42551e5543c3b55db701d1a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 28 Jan 2016 20:34:06 +0100 Subject: [PATCH 16/19] Fix difficulty calculation algo. --- res/ethereum/frontier.json | 2 +- res/ethereum/homestead_test.json | 2 +- res/ethereum/morden.json | 2 +- src/ethereum/ethash.rs | 20 ++++++++++++++------ src/spec.rs | 2 +- src/tests/chain.rs | 14 ++++++++++++++ 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/res/ethereum/frontier.json b/res/ethereum/frontier.json index 9cb456ce8..43be680d2 100644 --- a/res/ethereum/frontier.json +++ b/res/ethereum/frontier.json @@ -3,7 +3,7 @@ "engineName": "Ethash", "params": { "accountStartNonce": "0x00", - "frontierCompatibilityModeLimit": "0xDBBA0", + "frontierCompatibilityModeLimit": "0xdbba0", "maximumExtraDataSize": "0x20", "tieBreakingGas": false, "minGasLimit": "0x1388", diff --git a/res/ethereum/homestead_test.json b/res/ethereum/homestead_test.json index b11ef9740..1fb5dff80 100644 --- a/res/ethereum/homestead_test.json +++ b/res/ethereum/homestead_test.json @@ -3,7 +3,7 @@ "engineName": "Ethash", "params": { "accountStartNonce": "0x00", - "frontierCompatibilityModeLimit": "0", + "frontierCompatibilityModeLimit": 0, "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "tieBreakingGas": false, diff --git a/res/ethereum/morden.json b/res/ethereum/morden.json index 32fed0cab..cdcf8c7dc 100644 --- a/res/ethereum/morden.json +++ b/res/ethereum/morden.json @@ -3,7 +3,7 @@ "engineName": "Ethash", "params": { "accountStartNonce": "0x0100000", - "frontierCompatibilityModeLimit": "0xDBBA0", + "frontierCompatibilityModeLimit": "0xdbba0", "maximumExtraDataSize": "0x20", "tieBreakingGas": false, "minGasLimit": "0x1388", diff --git a/src/ethereum/ethash.rs b/src/ethereum/ethash.rs index 019d764df..2ececec9b 100644 --- a/src/ethereum/ethash.rs +++ b/src/ethereum/ethash.rs @@ -59,9 +59,14 @@ impl Engine for Ethash { } fn schedule(&self, env_info: &EnvInfo) -> Schedule { + trace!(target: "client", "Creating schedule. param={:?}, fCML={}", self.spec().engine_params.get("frontierCompatibilityModeLimit"), self.u64_param("frontierCompatibilityModeLimit")); match env_info.number < self.u64_param("frontierCompatibilityModeLimit") { - true => Schedule::new_frontier(), - _ => Schedule::new_homestead(), + true => { + Schedule::new_frontier() + }, + _ => { + Schedule::new_homestead() + }, } } @@ -178,12 +183,15 @@ impl Ethash { } } else { - let diff_inc = (header.timestamp - parent.timestamp) / 10; - if diff_inc <= 1 { - parent.difficulty + parent.difficulty / From::from(2048) * From::from(1 - diff_inc) + trace!(target: "ethash", "Calculating difficulty parent.difficulty={}, header.timestamp={}, parent.timestamp={}", parent.difficulty, header.timestamp, parent.timestamp); + //block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) + if header.timestamp >= parent.timestamp + 10 { + let diff_inc = (header.timestamp - parent.timestamp) / 10; + parent.difficulty - parent.difficulty / From::from(2048) * From::from(min(diff_inc - 1, 99)) } else { - parent.difficulty - parent.difficulty / From::from(2048) * From::from(max(diff_inc - 1, 99)) + let minus_diff_inc = if parent.timestamp > header.timestamp {(parent.timestamp - header.timestamp) / 10} else {0}; + parent.difficulty + parent.difficulty / From::from(2048) * From::from(minus_diff_inc + 1) } }; target = max(min_difficulty, target); diff --git a/src/spec.rs b/src/spec.rs index f4166eab2..77073eedd 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -16,7 +16,7 @@ pub fn gzip64res_to_json(source: &[u8]) -> Json { Json::from_str(&s).expect("Json is invalid") } -/// Convert JSON value to equivlaent RLP representation. +/// Convert JSON value to equivalent RLP representation. // TODO: handle container types. fn json_to_rlp(json: &Json) -> Bytes { match *json { diff --git a/src/tests/chain.rs b/src/tests/chain.rs index ca7884315..6518c546d 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -1,4 +1,6 @@ use std::env; +use log::{LogLevelFilter}; +use env_logger::LogBuilder; use super::test_common::*; use client::{BlockChainClient,Client}; use pod_state::*; @@ -10,7 +12,19 @@ pub enum ChainEra { Homestead, } +fn setup_log() { + let mut builder = LogBuilder::new(); + builder.filter(None, LogLevelFilter::Info); + + if env::var("RUST_LOG").is_ok() { + builder.parse(&env::var("RUST_LOG").unwrap()); + } + + builder.init().unwrap(); +} + pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { + setup_log(); let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); let mut failed = Vec::new(); From e8b1af27cd323dbd5247c035b60104221949f3d0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 28 Jan 2016 20:46:33 +0100 Subject: [PATCH 17/19] Simplify code. --- src/ethereum/ethash.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ethereum/ethash.rs b/src/ethereum/ethash.rs index 2ececec9b..4736beb92 100644 --- a/src/ethereum/ethash.rs +++ b/src/ethereum/ethash.rs @@ -185,14 +185,12 @@ impl Ethash { else { trace!(target: "ethash", "Calculating difficulty parent.difficulty={}, header.timestamp={}, parent.timestamp={}", parent.difficulty, header.timestamp, parent.timestamp); //block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) - if header.timestamp >= parent.timestamp + 10 { - let diff_inc = (header.timestamp - parent.timestamp) / 10; + let diff_inc = (header.timestamp - parent.timestamp) / 10; + if diff_inc <= 1 { + parent.difficulty + parent.difficulty / From::from(2048) * From::from(1 - diff_inc) + } else { parent.difficulty - parent.difficulty / From::from(2048) * From::from(min(diff_inc - 1, 99)) } - else { - let minus_diff_inc = if parent.timestamp > header.timestamp {(parent.timestamp - header.timestamp) / 10} else {0}; - parent.difficulty + parent.difficulty / From::from(2048) * From::from(minus_diff_inc + 1) - } }; target = max(min_difficulty, target); let period = ((parent.number + 1) / EXP_DIFF_PERIOD) as usize; From 30aeb5617a031f652ca973f7c8b294ea0d07919e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 28 Jan 2016 21:11:37 +0100 Subject: [PATCH 18/19] Update submodule --- res/ethereum/tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/ethereum/tests b/res/ethereum/tests index e838fd909..c670b1d8c 160000 --- a/res/ethereum/tests +++ b/res/ethereum/tests @@ -1 +1 @@ -Subproject commit e838fd90998fc5502d0b7c9427a4c231f9a6953d +Subproject commit c670b1d8c9f09593a6758ab2c099360e16c7c25b From 6b56363d84f24792653b746a5b8be2245558874c Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 28 Jan 2016 22:06:25 +0100 Subject: [PATCH 19/19] Fix logging in tests. Fix random blockchain tests. Closes #249 --- Cargo.toml | 1 + src/lib.rs | 2 ++ src/spec.rs | 12 ++++++++++-- src/tests/chain.rs | 22 ++++++++++++++-------- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 872e1e675..eef261317 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ ethash = { path = "ethash" } num_cpus = "0.2" clippy = "0.0.37" crossbeam = "0.1.5" +lazy_static = "0.1" [features] jit = ["evmjit"] diff --git a/src/lib.rs b/src/lib.rs index 8dd02b3bc..e084635dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,6 +91,8 @@ extern crate evmjit; #[macro_use] extern crate ethcore_util as util; extern crate crossbeam; +#[macro_use] +extern crate lazy_static; // NOTE: Add doc parser exception for these pub declarations. diff --git a/src/spec.rs b/src/spec.rs index 77073eedd..4d342f713 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -77,6 +77,10 @@ pub struct Spec { pub gas_used: U256, /// TODO [Gav Wood] Please document me pub timestamp: u64, + /// Transactions root of the genesis block. Should be SHA3_NULL_RLP. + pub transactions_root: H256, + /// Receipts root of the genesis block. Should be SHA3_NULL_RLP. + pub receipts_root: H256, /// TODO [arkpar] Please document me pub extra_data: Bytes, /// TODO [Gav Wood] Please document me @@ -120,11 +124,11 @@ impl Spec { timestamp: self.timestamp, number: 0, author: self.author.clone(), - transactions_root: SHA3_NULL_RLP.clone(), + transactions_root: self.transactions_root.clone(), uncles_hash: RlpStream::new_list(0).out().sha3(), extra_data: self.extra_data.clone(), state_root: self.state_root().clone(), - receipts_root: SHA3_NULL_RLP.clone(), + receipts_root: self.receipts_root.clone(), log_bloom: H2048::new().clone(), gas_used: self.gas_used.clone(), gas_limit: self.gas_limit.clone(), @@ -172,6 +176,8 @@ impl Spec { }; self.parent_hash = H256::from_json(&genesis["parentHash"]); + self.transactions_root = genesis.find("transactionsTrie").and_then(|_| Some(H256::from_json(&genesis["transactionsTrie"]))).unwrap_or(SHA3_NULL_RLP.clone()); + self.receipts_root = genesis.find("receiptTrie").and_then(|_| Some(H256::from_json(&genesis["receiptTrie"]))).unwrap_or(SHA3_NULL_RLP.clone()); self.author = Address::from_json(&genesis["coinbase"]); self.difficulty = U256::from_json(&genesis["difficulty"]); self.gas_limit = U256::from_json(&genesis["gasLimit"]); @@ -248,6 +254,8 @@ impl FromJson for Spec { gas_limit: U256::from_str(&genesis["gasLimit"].as_string().unwrap()[2..]).unwrap(), gas_used: U256::from(0u8), timestamp: u64::from_str(&genesis["timestamp"].as_string().unwrap()[2..]).unwrap(), + transactions_root: SHA3_NULL_RLP.clone(), + receipts_root: SHA3_NULL_RLP.clone(), extra_data: genesis["extraData"].as_string().unwrap()[2..].from_hex().unwrap(), genesis_state: state, seal_fields: seal_fields, diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 48b176508..e260deddc 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -13,19 +13,22 @@ pub enum ChainEra { Homestead, } -fn setup_log() { - let mut builder = LogBuilder::new(); - builder.filter(None, LogLevelFilter::Info); +lazy_static! { + static ref LOG_DUMMY: bool = { + let mut builder = LogBuilder::new(); + builder.filter(None, LogLevelFilter::Info); - if env::var("RUST_LOG").is_ok() { - builder.parse(&env::var("RUST_LOG").unwrap()); - } + if env::var("RUST_LOG").is_ok() { + builder.parse(&env::var("RUST_LOG").unwrap()); + } - builder.init().unwrap(); + builder.init().unwrap(); + true + }; } pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { - setup_log(); + let _ = LOG_DUMMY.deref(); let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); let mut failed = Vec::new(); @@ -50,10 +53,13 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { spec.set_genesis_state(s); spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); assert!(spec.is_state_root_valid()); + let genesis_hash = spec.genesis_header().hash(); + assert_eq!(genesis_hash, H256::from_json(&test.find("genesisBlockHeader").unwrap()["hash"])); let temp = RandomTempPath::new(); { let client = Client::new(spec, temp.as_path(), IoChannel::disconnected()).unwrap(); + assert_eq!(client.chain_info().best_block_hash, genesis_hash); for (b, is_valid) in blocks.into_iter() { if Block::is_good(&b) { let _ = client.import_block(b.clone());