From ab131b134bc3bf96371154cd8017c5cdd8f43981 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 4 Feb 2016 22:03:14 +0300 Subject: [PATCH 1/7] first local chain test --- sync/src/chain.rs | 18 ++++++++++++++++++ sync/src/tests/chain.rs | 14 +++++++------- sync/src/tests/helpers.rs | 4 ++-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 40cbd496b..b918c960d 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1016,4 +1016,22 @@ impl ChainSync { #[cfg(test)] mod tests { + use tests::helpers::*; + use super::*; + use util::*; + + #[test] + fn return_receipts() { + let mut client = TestBlockChainClient::new(); + let mut queue:VecDeque = VecDeque::new(); + let mut io = TestIo::new(& mut client, & mut queue, None); + + let sync = ChainSync::new(); + let data = vec![0xc0]; + let rlp = UntrustedRlp::new(&data); + + let result = sync.return_receipts(& mut io, &rlp); + + assert!(result.is_ok()); + } } \ No newline at end of file diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index 083a9bd33..fcd9b6a7b 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -5,7 +5,7 @@ use chain::{SyncState}; use super::helpers::*; #[test] -fn chain_two_peers() { +fn two_peers() { ::env_logger::init().ok(); let mut net = TestNet::new(3); net.peer_mut(1).chain.add_blocks(1000, false); @@ -16,7 +16,7 @@ fn chain_two_peers() { } #[test] -fn chain_status_after_sync() { +fn status_after_sync() { ::env_logger::init().ok(); let mut net = TestNet::new(3); net.peer_mut(1).chain.add_blocks(1000, false); @@ -27,7 +27,7 @@ fn chain_status_after_sync() { } #[test] -fn chain_takes_few_steps() { +fn takes_few_steps() { let mut net = TestNet::new(3); net.peer_mut(1).chain.add_blocks(100, false); net.peer_mut(2).chain.add_blocks(100, false); @@ -36,7 +36,7 @@ fn chain_takes_few_steps() { } #[test] -fn chain_empty_blocks() { +fn empty_blocks() { ::env_logger::init().ok(); let mut net = TestNet::new(3); for n in 0..200 { @@ -49,7 +49,7 @@ fn chain_empty_blocks() { } #[test] -fn chain_forked() { +fn forked() { ::env_logger::init().ok(); let mut net = TestNet::new(3); net.peer_mut(0).chain.add_blocks(300, false); @@ -69,7 +69,7 @@ fn chain_forked() { } #[test] -fn chain_restart() { +fn restart() { let mut net = TestNet::new(3); net.peer_mut(1).chain.add_blocks(1000, false); net.peer_mut(2).chain.add_blocks(1000, false); @@ -85,7 +85,7 @@ fn chain_restart() { } #[test] -fn chain_status_empty() { +fn status_empty() { let net = TestNet::new(2); assert_eq!(net.peer(0).sync.status().state, SyncState::NotSynced); } \ No newline at end of file diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 7fdd695fb..405d1e5c1 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -15,7 +15,7 @@ pub struct TestBlockChainClient { } impl TestBlockChainClient { - fn new() -> TestBlockChainClient { + pub fn new() -> TestBlockChainClient { let mut client = TestBlockChainClient { blocks: RwLock::new(HashMap::new()), @@ -196,7 +196,7 @@ pub struct TestIo<'p> { } impl<'p> TestIo<'p> { - fn new(chain: &'p mut TestBlockChainClient, queue: &'p mut VecDeque, sender: Option) -> TestIo<'p> { + pub fn new(chain: &'p mut TestBlockChainClient, queue: &'p mut VecDeque, sender: Option) -> TestIo<'p> { TestIo { chain: chain, queue: queue, From 8d7523a027bfa7273e8e80181342a05197a23971 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 5 Feb 2016 01:24:36 +0300 Subject: [PATCH 2/7] receipt tests --- sync/src/chain.rs | 111 +++++++++++++++++++++++++------------- sync/src/tests/helpers.rs | 13 ++++- 2 files changed, 87 insertions(+), 37 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index b918c960d..5a3856264 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -177,6 +177,7 @@ pub struct ChainSync { have_common_block: bool, } +type RlpResponseResult = Result, PacketDecodeError>; impl ChainSync { /// Create a new instance of syncing strategy. @@ -845,7 +846,7 @@ impl ChainSync { } /// Respond to GetBlockHeaders request - fn return_block_headers(&self, io: &mut SyncIo, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { + fn return_block_headers(io: &SyncIo, r: &UntrustedRlp) -> RlpResponseResult { // Packet layout: // [ block: { P , B_32 }, maxHeaders: P, skip: P, reverse: P in { 0 , 1 } ] let max_headers: usize = try!(r.val_at(1)); @@ -892,18 +893,16 @@ impl ChainSync { } let mut rlp = RlpStream::new_list(count as usize); rlp.append_raw(&data, count as usize); - io.respond(BLOCK_HEADERS_PACKET, rlp.out()).unwrap_or_else(|e| - debug!(target: "sync", "Error sending headers: {:?}", e)); trace!(target: "sync", "-> GetBlockHeaders: returned {} entries", count); - Ok(()) + Ok(Some((BLOCK_HEADERS_PACKET, rlp))) } /// Respond to GetBlockBodies request - fn return_block_bodies(&self, io: &mut SyncIo, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { + fn return_block_bodies(io: &SyncIo, r: &UntrustedRlp) -> RlpResponseResult { let mut count = r.item_count(); if count == 0 { debug!(target: "sync", "Empty GetBlockBodies request, ignoring."); - return Ok(()); + return Ok(None); } trace!(target: "sync", "-> GetBlockBodies: {} entries", count); count = min(count, MAX_BODIES_TO_SEND); @@ -917,18 +916,16 @@ impl ChainSync { } let mut rlp = RlpStream::new_list(added); rlp.append_raw(&data, added); - io.respond(BLOCK_BODIES_PACKET, rlp.out()).unwrap_or_else(|e| - debug!(target: "sync", "Error sending headers: {:?}", e)); trace!(target: "sync", "-> GetBlockBodies: returned {} entries", added); - Ok(()) + Ok(Some((BLOCK_BODIES_PACKET, rlp))) } /// Respond to GetNodeData request - fn return_node_data(&self, io: &mut SyncIo, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { + fn return_node_data(io: &SyncIo, r: &UntrustedRlp) -> RlpResponseResult { let mut count = r.item_count(); if count == 0 { debug!(target: "sync", "Empty GetNodeData request, ignoring."); - return Ok(()); + return Ok(None); } count = min(count, MAX_NODE_DATA_TO_SEND); let mut added = 0usize; @@ -941,32 +938,43 @@ impl ChainSync { } let mut rlp = RlpStream::new_list(added); rlp.append_raw(&data, added); - io.respond(NODE_DATA_PACKET, rlp.out()).unwrap_or_else(|e| - debug!(target: "sync", "Error sending headers: {:?}", e)); - Ok(()) + Ok(Some((NODE_DATA_PACKET, rlp))) } - /// Respond to GetReceipts request - fn return_receipts(&self, io: &mut SyncIo, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { - let mut count = r.item_count(); + fn return_receipts(io: &SyncIo, rlp: &UntrustedRlp) -> RlpResponseResult { + let mut count = rlp.item_count(); if count == 0 { debug!(target: "sync", "Empty GetReceipts request, ignoring."); - return Ok(()); + return Ok(None); } count = min(count, MAX_RECEIPTS_TO_SEND); let mut added = 0usize; let mut data = Bytes::new(); for i in 0..count { - if let Some(mut hdr) = io.chain().block_receipts(&try!(r.val_at::(i))) { + if let Some(mut hdr) = io.chain().block_receipts(&try!(rlp.val_at::(i))) { data.append(&mut hdr); added += 1; } } - let mut rlp = RlpStream::new_list(added); - rlp.append_raw(&data, added); - io.respond(RECEIPTS_PACKET, rlp.out()).unwrap_or_else(|e| - debug!(target: "sync", "Error sending headers: {:?}", e)); - Ok(()) + let mut rlp_result = RlpStream::new_list(added); + rlp_result.append_raw(&data, added); + Ok(Some((RECEIPTS_PACKET, rlp_result))) + } + + fn return_rlp(&self, io: &mut SyncIo, rlp: &UntrustedRlp, rlp_func: FRlp, error_func: FError) -> Result<(), PacketDecodeError> + where FRlp : Fn(&SyncIo, &UntrustedRlp) -> RlpResponseResult, + FError : FnOnce(UtilError) -> String + { + let response = rlp_func(io, rlp); + match response { + Err(e) => Err(e), + Ok(Some((packet_id, rlp_stream))) => { + io.respond(packet_id, rlp_stream.out()).unwrap_or_else( + |e| debug!(target: "sync", "{:?}", error_func(e))); + Ok(()) + } + _ => Ok(()) + } } /// Dispatch incoming requests and responses @@ -975,14 +983,26 @@ impl ChainSync { let result = match packet_id { STATUS_PACKET => self.on_peer_status(io, peer, &rlp), TRANSACTIONS_PACKET => self.on_peer_transactions(io, peer, &rlp), - GET_BLOCK_HEADERS_PACKET => self.return_block_headers(io, &rlp), BLOCK_HEADERS_PACKET => self.on_peer_block_headers(io, peer, &rlp), - GET_BLOCK_BODIES_PACKET => self.return_block_bodies(io, &rlp), BLOCK_BODIES_PACKET => self.on_peer_block_bodies(io, peer, &rlp), NEW_BLOCK_PACKET => self.on_peer_new_block(io, peer, &rlp), NEW_BLOCK_HASHES_PACKET => self.on_peer_new_hashes(io, peer, &rlp), - GET_NODE_DATA_PACKET => self.return_node_data(io, &rlp), - GET_RECEIPTS_PACKET => self.return_receipts(io, &rlp), + + GET_BLOCK_BODIES_PACKET => self.return_rlp(io, &rlp, + ChainSync::return_block_bodies, + |e| format!("Error sending block bodies: {:?}", e)), + + GET_BLOCK_HEADERS_PACKET => self.return_rlp(io, &rlp, + ChainSync::return_block_headers, + |e| format!("Error sending block headers: {:?}", e)), + + GET_RECEIPTS_PACKET => self.return_rlp(io, &rlp, + ChainSync::return_receipts, + |e| format!("Error sending receipts: {:?}", e)), + + GET_NODE_DATA_PACKET => self.return_rlp(io, &rlp, + ChainSync::return_node_data, + |e| format!("Error sending nodes: {:?}", e)), _ => { debug!(target: "sync", "Unknown packet {}", packet_id); Ok(()) @@ -1021,17 +1041,36 @@ mod tests { use util::*; #[test] - fn return_receipts() { + fn return_receipts_empty() { let mut client = TestBlockChainClient::new(); - let mut queue:VecDeque = VecDeque::new(); - let mut io = TestIo::new(& mut client, & mut queue, None); + let mut queue = VecDeque::new(); + let io = TestIo::new(&mut client, &mut queue, None); - let sync = ChainSync::new(); - let data = vec![0xc0]; - let rlp = UntrustedRlp::new(&data); - - let result = sync.return_receipts(& mut io, &rlp); + let result = ChainSync::return_receipts(&io, &UntrustedRlp::new(&[0xc0])); assert!(result.is_ok()); } + + #[test] + fn return_receipts() { + let mut client = TestBlockChainClient::new(); + let mut queue = VecDeque::new(); + let io = TestIo::new(&mut client, &mut queue, None); + + let mut receipt_list = RlpStream::new_list(4); + receipt_list.append(&H256::from("0000000000000000000000000000000000000000000000005555555555555555")); + receipt_list.append(&H256::from("ff00000000000000000000000000000000000000000000000000000000000000")); + receipt_list.append(&H256::from("fff0000000000000000000000000000000000000000000000000000000000000")); + receipt_list.append(&H256::from("aff0000000000000000000000000000000000000000000000000000000000000")); + + // it returns rlp ONLY for hashes started with "f" + let result = ChainSync::return_receipts(&io, &UntrustedRlp::new(&receipt_list.out())); + + assert!(result.is_ok()); + let rlp_result = result.unwrap(); + assert!(rlp_result.is_some()); + + // the length of two rlp-encoded receipts + assert_eq!(597, rlp_result.unwrap().1.out().len()); + } } \ No newline at end of file diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 405d1e5c1..ce3560d63 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -5,6 +5,7 @@ use ethcore::header::{Header as BlockHeader, BlockNumber}; use ethcore::error::*; use io::SyncIo; use chain::{ChainSync}; +use ethcore::receipt::Receipt; pub struct TestBlockChainClient { pub blocks: RwLock>, @@ -120,7 +121,17 @@ impl BlockChainClient for TestBlockChainClient { None } - fn block_receipts(&self, _h: &H256) -> Option { + fn block_receipts(&self, hash: &H256) -> Option { + // starts with 'f' ? + if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") { + let receipt = Receipt::new( + H256::zero(), + U256::zero(), + vec![]); + let mut rlp = RlpStream::new(); + rlp.append(&receipt); + return Some(rlp.out()); + } None } From c12538b1237c3efede1e938daa6ed9dcdc25fbc4 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 5 Feb 2016 01:58:32 +0300 Subject: [PATCH 3/7] dispatch test as well --- sync/src/chain.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 5a3856264..62bb4b4de 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1055,7 +1055,7 @@ mod tests { fn return_receipts() { let mut client = TestBlockChainClient::new(); let mut queue = VecDeque::new(); - let io = TestIo::new(&mut client, &mut queue, None); + let mut io = TestIo::new(&mut client, &mut queue, None); let mut receipt_list = RlpStream::new_list(4); receipt_list.append(&H256::from("0000000000000000000000000000000000000000000000005555555555555555")); @@ -1063,8 +1063,9 @@ mod tests { receipt_list.append(&H256::from("fff0000000000000000000000000000000000000000000000000000000000000")); receipt_list.append(&H256::from("aff0000000000000000000000000000000000000000000000000000000000000")); + let receipts_request = receipt_list.out(); // it returns rlp ONLY for hashes started with "f" - let result = ChainSync::return_receipts(&io, &UntrustedRlp::new(&receipt_list.out())); + let result = ChainSync::return_receipts(&io, &UntrustedRlp::new(&receipts_request.clone())); assert!(result.is_ok()); let rlp_result = result.unwrap(); @@ -1072,5 +1073,11 @@ mod tests { // the length of two rlp-encoded receipts assert_eq!(597, rlp_result.unwrap().1.out().len()); + + let mut sync = ChainSync::new(); + io.sender = Some(2usize); + sync.on_packet(&mut io, 1usize, super::GET_RECEIPTS_PACKET, &receipts_request); } + + } \ No newline at end of file From 51b41a70804913896c9a4bbfba6feaaa94842b49 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 5 Feb 2016 01:58:58 +0300 Subject: [PATCH 4/7] forgot root changes --- ethcore/src/lib.rs | 2 +- ethcore/src/receipt.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 3df01d898..540b5ea40 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -83,6 +83,7 @@ pub mod header; pub mod service; pub mod spec; pub mod views; +pub mod receipt; mod common; mod basic_types; @@ -98,7 +99,6 @@ mod state; mod account; mod action_params; mod transaction; -mod receipt; mod null_engine; mod builtin; mod extras; diff --git a/ethcore/src/receipt.rs b/ethcore/src/receipt.rs index 43f674aa9..3888a6abc 100644 --- a/ethcore/src/receipt.rs +++ b/ethcore/src/receipt.rs @@ -1,3 +1,5 @@ +//! Receipt + use util::*; use basic_types::LogBloom; use log_entry::LogEntry; From 0c90b75c67f618aa48c6cf426ee26672ba62fcc0 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 5 Feb 2016 02:01:29 +0300 Subject: [PATCH 5/7] excluded test code from coverage --- sync/cov.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sync/cov.sh b/sync/cov.sh index c19dd5689..5e95542fa 100755 --- a/sync/cov.sh +++ b/sync/cov.sh @@ -5,5 +5,5 @@ fi cargo test --no-run || exit $? mkdir -p target/coverage -kcov --exclude-pattern ~/.multirust,rocksdb,secp256k1 --include-pattern sync/src --verify target/coverage target/debug/ethsync* +kcov --exclude-pattern ~/.multirust,rocksdb,secp256k1,sync/src/tests --include-pattern sync/src --verify target/coverage target/debug/ethsync* xdg-open target/coverage/index.html From b0cba757d6f6a71a5529e5a0656ac0a88c80e4ab Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 5 Feb 2016 02:57:51 +0300 Subject: [PATCH 6/7] test effort --- sync/src/chain.rs | 27 +++++++++++++++++++++++++++ sync/src/tests/helpers.rs | 9 ++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 62bb4b4de..869b19bf5 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1077,7 +1077,34 @@ mod tests { let mut sync = ChainSync::new(); io.sender = Some(2usize); sync.on_packet(&mut io, 1usize, super::GET_RECEIPTS_PACKET, &receipts_request); + assert_eq!(1, io.queue.len()); } + #[test] + fn return_nodes() { + let mut client = TestBlockChainClient::new(); + let mut queue = VecDeque::new(); + let mut io = TestIo::new(&mut client, &mut queue, None); + let mut node_list = RlpStream::new_list(3); + node_list.append(&H256::from("0000000000000000000000000000000000000000000000005555555555555555")); + node_list.append(&H256::from("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa")); + node_list.append(&H256::from("aff0000000000000000000000000000000000000000000000000000000000000")); + + let node_request = node_list.out(); + // it returns rlp ONLY for hashes started with "f" + let result = ChainSync::return_node_data(&io, &UntrustedRlp::new(&node_request.clone())); + + assert!(result.is_ok()); + let rlp_result = result.unwrap(); + assert!(rlp_result.is_some()); + + // the length of one rlp-encoded hashe + assert_eq!(34, rlp_result.unwrap().1.out().len()); + + let mut sync = ChainSync::new(); + io.sender = Some(2usize); + sync.on_packet(&mut io, 1usize, super::GET_NODE_DATA_PACKET, &node_request); + assert_eq!(1, io.queue.len()); + } } \ No newline at end of file diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index ce3560d63..c4a4d80cb 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -117,7 +117,14 @@ impl BlockChainClient for TestBlockChainClient { }) } - fn state_data(&self, _h: &H256) -> Option { + // TODO: returns just hashes instead of node state rlp(?) + fn state_data(&self, hash: &H256) -> Option { + // starts with 'f' ? + if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") { + let mut rlp = RlpStream::new(); + rlp.append(&hash.clone()); + return Some(rlp.out()); + } None } From 410d6533e0c6f0f46343513cb7b014a71521dba0 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 5 Feb 2016 03:01:50 +0300 Subject: [PATCH 7/7] indents --- sync/src/chain.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 869b19bf5..e143f20b1 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -997,12 +997,13 @@ impl ChainSync { |e| format!("Error sending block headers: {:?}", e)), GET_RECEIPTS_PACKET => self.return_rlp(io, &rlp, - ChainSync::return_receipts, - |e| format!("Error sending receipts: {:?}", e)), + ChainSync::return_receipts, + |e| format!("Error sending receipts: {:?}", e)), GET_NODE_DATA_PACKET => self.return_rlp(io, &rlp, - ChainSync::return_node_data, - |e| format!("Error sending nodes: {:?}", e)), + ChainSync::return_node_data, + |e| format!("Error sending nodes: {:?}", e)), + _ => { debug!(target: "sync", "Unknown packet {}", packet_id); Ok(())