From 1a4e95a9dc594abf0108ed9e97ad9788a7dec65f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 29 Feb 2016 18:57:46 +0300 Subject: [PATCH 01/14] u256*u256->u512 --- util/benches/bigint.rs | 13 +++ util/src/uint.rs | 257 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+) diff --git a/util/benches/bigint.rs b/util/benches/bigint.rs index da82084b8..fc41ab628 100644 --- a/util/benches/bigint.rs +++ b/util/benches/bigint.rs @@ -74,6 +74,19 @@ fn u256_mul(b: &mut Bencher) { } +#[bench] +fn u256_full_mul(b: &mut Bencher) { + b.iter(|| { + let n = black_box(10000); + (0..n).fold(U256([rand::random::(), rand::random::(), rand::random::(), rand::random::()]), + |old, new| { + let U512(ref u512words) = old.full_mul(U256([rand::random::(), rand::random::(), rand::random::(), rand::random::()])); + U256([u512words[0], u512words[2], u512words[2], u512words[3]]) + }) + }); +} + + #[bench] fn u128_mul(b: &mut Bencher) { b.iter(|| { diff --git a/util/src/uint.rs b/util/src/uint.rs index 517b7a29f..bbe62e5d4 100644 --- a/util/src/uint.rs +++ b/util/src/uint.rs @@ -1097,6 +1097,157 @@ construct_uint!(U512, 8); construct_uint!(U256, 4); construct_uint!(U128, 2); +impl U256 { + /// Multiplies two 256-bit integers to produce full 512-bit integer + /// No overflow possible + #[cfg(all(x64asm, target_arch="x86_64"))] + pub fn full_mul(self, other: U256) -> U512 { + let self_t: &[u64; 4] = unsafe { &mem::transmute(self) }; + let other_t: &[u64; 4] = unsafe { &mem::transmute(other) }; + let mut result: [u64; 8] = unsafe { mem::uninitialized() }; + unsafe { + asm!(" + mov $8, %rax + mulq $12 + mov %rax, $0 + mov %rdx, $1 + + mov $8, %rax + mulq $13 + add %rax, $1 + adc $$0, %rdx + mov %rdx, $2 + + mov $8, %rax + mulq $14 + add %rax, $2 + adc $$0, %rdx + mov %rdx, $3 + + mov $8, %rax + mulq $15 + add %rax, $3 + adc $$0, %rdx + mov %rdx, $4 + + mov $9, %rax + mulq $12 + add %rax, $1 + adc %rdx, $2 + adc $$0, $3 + adc $$0, $4 + xor $5, $5 + adc $$0, $5 + xor $6, $6 + adc $$0, $6 + xor $7, $7 + adc $$0, $7 + + mov $9, %rax + mulq $13 + add %rax, $2 + adc %rdx, $3 + adc $$0, $4 + adc $$0, $5 + adc $$0, $6 + adc $$0, $7 + + mov $9, %rax + mulq $14 + add %rax, $3 + adc %rdx, $4 + adc $$0, $5 + adc $$0, $6 + adc $$0, $7 + + mov $9, %rax + mulq $15 + add %rax, $4 + adc %rdx, $5 + adc $$0, $6 + adc $$0, $7 + + mov $10, %rax + mulq $12 + add %rax, $2 + adc %rdx, $3 + adc $$0, $4 + adc $$0, $5 + adc $$0, $6 + adc $$0, $7 + + mov $10, %rax + mulq $13 + add %rax, $3 + adc %rdx, $4 + adc $$0, $5 + adc $$0, $6 + adc $$0, $7 + + mov $10, %rax + mulq $14 + add %rax, $4 + adc %rdx, $5 + adc $$0, $6 + adc $$0, $7 + + mov $10, %rax + mulq $15 + add %rax, $5 + adc %rdx, $6 + adc $$0, $7 + + mov $11, %rax + mulq $12 + add %rax, $3 + adc %rdx, $4 + adc $$0, $5 + adc $$0, $6 + adc $$0, $7 + + mov $11, %rax + mulq $13 + add %rax, $4 + adc %rdx, $5 + adc $$0, $6 + adc $$0, $7 + + mov $11, %rax + mulq $14 + add %rax, $5 + adc %rdx, $6 + adc $$0, $7 + + mov $11, %rax + mulq $15 + add %rax, $6 + adc %rdx, $7 + " + : /* $0 */ "={r8}"(result[0]), /* $1 */ "={r9}"(result[1]), /* $2 */ "={r10}"(result[2]), + /* $3 */ "={r11}"(result[3]), /* $4 */ "={r12}"(result[4]), /* $5 */ "={r13}"(result[5]), + /* $6 */ "={r14}"(result[6]), /* $7 */ "={r15}"(result[7]) + + : /* $8 */ "m"(self_t[0]), /* $9 */ "m"(self_t[1]), /* $10 */ "m"(self_t[2]), + /* $11 */ "m"(self_t[3]), /* $12 */ "m"(other_t[0]), /* $13 */ "m"(other_t[1]), + /* $14 */ "m"(other_t[2]), /* $15 */ "m"(other_t[3]) + : "rax", "rdx" + : + ); + } + U512(result) + } + + /// Multiplies two 256-bit integers to produce full 512-bit integer + /// No overflow possible + #[cfg(not(all(x64asm, target_arch="x86_64")))] + pub fn full_mul(self, other: U256) -> U512 { + let self_512 = U512::from(self); + let other_512 = U512::from(other); + let (result, _) = self_512.overflowing_mul(other_512); + result + } +} + impl From for U512 { fn from(value: U256) -> U512 { let U256(ref arr) = value; @@ -1828,5 +1979,111 @@ mod tests { let (_, overflow) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); assert!(overflow); } + + + #[test] + fn u256_multi_full_mul() { + let result = U256([0, 0, 0, 0]).full_mul(U256([0, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([1, 0, 0, 0]).full_mul(U256([1, 0, 0, 0])); + assert_eq!(U512([1, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([5, 0, 0, 0]).full_mul(U256([5, 0, 0, 0])); + assert_eq!(U512([25, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([0, 5, 0, 0]).full_mul(U256([0, 5, 0, 0])); + assert_eq!(U512([0, 0, 25, 0, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 0, 4]).full_mul(U256([4, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 16, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 0, 5]).full_mul(U256([2, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 2, 0]).full_mul(U256([0, 5, 0, 0])); + assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); + + let result = U256([0, 3, 0, 0]).full_mul(U256([0, 0, 3, 0])); + assert_eq!(U512([0, 0, 0, 9, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 8, 0]).full_mul(U256([0, 0, 6, 0])); + assert_eq!(U512([0, 0, 0, 0, 48, 0, 0, 0]), result); + + let result = U256([9, 0, 0, 0]).full_mul(U256([0, 3, 0, 0])); + assert_eq!(U512([0, 27, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, 0, 0, 0]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U512([1, ::std::u64::MAX-1, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([0, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U512([0, 1, ::std::u64::MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, 0, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U512([1, 0, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, 0, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, 0, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); + assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]).full_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U512([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U512([1, 0, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U512([1, 0, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U512([1, 0, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); + assert_eq!(U512([1, 0, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U512([1, 0, 0, ::std::u64::MAX-1, ::std::u64::MAX, ::std::u64::MAX, 0, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); + assert_eq!(U512([1, 0, 0, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, ::std::u64::MAX, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U512([1, 0, 0, ::std::u64::MAX, ::std::u64::MAX-1, ::std::u64::MAX, ::std::u64::MAX, 0]), result); + + let result = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]).full_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); + assert_eq!(U512([1, 0, 0, 0, ::std::u64::MAX-1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); + + let result = U256([0, 0, 0, ::std::u64::MAX]).full_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert_eq!(U512([0, 0, 0, 0, 0, 0, 1, ::std::u64::MAX-1]), result); + + let result = U256([1, 0, 0, 0]).full_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert_eq!(U512([0, 0, 0, ::std::u64::MAX, 0, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([5, 0, 0, 0])); + assert_eq!(U512([5, 10, 15, 20, 0, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 6, 0, 0])); + assert_eq!(U512([0, 6, 12, 18, 24, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 7, 0])); + assert_eq!(U512([0, 0, 7, 14, 21, 28, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 0, 8])); + assert_eq!(U512([0, 0, 0, 8, 16, 24, 32, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([5, 6, 7, 8])); + assert_eq!(U512([5, 16, 34, 60, 61, 52, 32, 0]), result); + } } From b30f066651d480c0e7a5dbd90ed85585de5a6d6c Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 29 Feb 2016 19:15:13 +0300 Subject: [PATCH 02/14] tabified --- util/src/uint.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/util/src/uint.rs b/util/src/uint.rs index bbe62e5d4..88256d5f2 100644 --- a/util/src/uint.rs +++ b/util/src/uint.rs @@ -1105,8 +1105,8 @@ impl U256 { let self_t: &[u64; 4] = unsafe { &mem::transmute(self) }; let other_t: &[u64; 4] = unsafe { &mem::transmute(other) }; let mut result: [u64; 8] = unsafe { mem::uninitialized() }; - unsafe { - asm!(" + unsafe { + asm!(" mov $8, %rax mulq $12 mov %rax, $0 @@ -1230,11 +1230,11 @@ impl U256 { : /* $8 */ "m"(self_t[0]), /* $9 */ "m"(self_t[1]), /* $10 */ "m"(self_t[2]), /* $11 */ "m"(self_t[3]), /* $12 */ "m"(other_t[0]), /* $13 */ "m"(other_t[1]), /* $14 */ "m"(other_t[2]), /* $15 */ "m"(other_t[3]) - : "rax", "rdx" - : - ); - } - U512(result) + : "rax", "rdx" + : + ); + } + U512(result) } /// Multiplies two 256-bit integers to produce full 512-bit integer From 8920bea2418a01f46cd06e2da22e2920dc960af9 Mon Sep 17 00:00:00 2001 From: Wojciech Langiewicz Date: Mon, 29 Feb 2016 21:14:38 +0100 Subject: [PATCH 03/14] ignore out directory --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 58b1895c6..3226ea5a2 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ # jetbrains ide stuff .idea *.iml + +# Build artifacts +out/ From 4bf77c03f526ce58e6a65f2a221e6d9156db8a5e Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Thu, 18 Feb 2016 19:30:58 +0100 Subject: [PATCH 04/14] Moving Table to utils. Fixing couple of small things --- util/src/lib.rs | 1 + util/src/table.rs | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 util/src/table.rs diff --git a/util/src/lib.rs b/util/src/lib.rs index 2a47eb438..ea60418db 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -144,6 +144,7 @@ pub mod network; pub mod log; pub mod panics; pub mod keys; +pub mod table; pub use common::*; pub use misc::*; diff --git a/util/src/table.rs b/util/src/table.rs new file mode 100644 index 000000000..572d81f84 --- /dev/null +++ b/util/src/table.rs @@ -0,0 +1,122 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! A collection associating pair of keys (row and column) with a single value. + +use std::hash::Hash; +use std::collections::HashMap; + +/// Structure to hold double-indexed values +/// +/// You can obviously use `HashMap<(Row,Col), Val>`, but this structure gives +/// you better access to all `Columns` in Specific `Row`. Namely you can get sub-hashmap +/// `HashMap` for specific `Row` +pub struct Table + where Row: Eq + Hash + Clone, + Col: Eq + Hash { + map: HashMap>, +} + +impl Table + where Row: Eq + Hash + Clone, + Col: Eq + Hash { + /// Creates new Table + pub fn new() -> Table { + Table { + map: HashMap::new(), + } + } + + /// Removes all elements from this Table + pub fn clear(&mut self) { + self.map.clear(); + } + + /// Returns length of the Table (number of (row, col, val) tuples) + pub fn len(&self) -> usize { + self.map.iter().fold(0, |acc, (_k, v)| acc + v.len()) + } + + /// Check if there is any element in this Table + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Get mutable reference for single Table row. + pub fn get_row_mut(&mut self, row: &Row) -> Option<&mut HashMap> { + self.map.get_mut(row) + } + + /// Checks if row is defined for that table (note that even if defined it might be empty) + pub fn has_row(&self, row: &Row) -> bool { + self.map.contains_key(row) + } + + /// Get immutable reference for single row in this Table + pub fn get_row(&self, row: &Row) -> Option<&HashMap> { + self.map.get(row) + } + + /// Get element in cell described by `(row, col)` + pub fn get(&self, row: &Row, col: &Col) -> Option<&Val> { + self.map.get(row).and_then(|r| r.get(col)) + } + + /// Remove value from specific cell + /// + /// It will remove the row if it's the last value in it + pub fn remove(&mut self, row: &Row, col: &Col) -> Option { + let (val, is_empty) = { + let row_map = self.map.get_mut(row); + if let None = row_map { + return None; + } + let mut row_map = row_map.unwrap(); + let val = row_map.remove(col); + (val, row_map.is_empty()) + }; + // Clean row + if is_empty { + self.map.remove(row); + } + val + } + + /// Remove given row from Table if there are no values defined in it + /// + /// When using `#get_row_mut` it may happen that all values from some row are drained. + /// Table however will not be aware that row is empty. + /// You can use this method to explicitly remove row entry from the Table. + pub fn clear_if_empty(&mut self, row: &Row) { + let is_empty = self.map.get(row).map_or(false, |m| m.is_empty()); + if is_empty { + self.map.remove(row); + } + } + + /// Inserts new value to specified cell + /// + /// Returns previous value (if any) + pub fn insert(&mut self, row: Row, col: Col, val: Val) -> Option { + if !self.map.contains_key(&row) { + let m = HashMap::new(); + self.map.insert(row.clone(), m); + } + + let mut columns = self.map.get_mut(&row).unwrap(); + columns.insert(col, val) + } +} From f2fdb8b69ba90a5593f60ba1fa3018f77121e60e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 29 Feb 2016 22:56:56 +0100 Subject: [PATCH 05/14] Table tests --- util/src/table.rs | 138 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/util/src/table.rs b/util/src/table.rs index 572d81f84..525002dc3 100644 --- a/util/src/table.rs +++ b/util/src/table.rs @@ -120,3 +120,141 @@ impl Table columns.insert(col, val) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn should_create_empty_table() { + // when + let table : Table = Table::new(); + + // then + assert!(table.is_empty()); + assert_eq!(table.len(), 0); + } + + #[test] + fn should_insert_elements_and_return_previous_if_any() { + // given + let mut table = Table::new(); + + // when + let r1 = table.insert(5, 4, true); + let r2 = table.insert(10, 4, true); + let r3 = table.insert(10, 10, true); + let r4 = table.insert(10, 10, false); + + // then + assert!(r1.is_none()); + assert!(r2.is_none()); + assert!(r3.is_none()); + assert!(r4.is_some()); + assert!(!table.is_empty()); + assert_eq!(r4.unwrap(), true); + assert_eq!(table.len(), 3); + } + + #[test] + fn should_remove_element() { + // given + let mut table = Table::new(); + table.insert(5, 4, true); + assert!(!table.is_empty()); + assert_eq!(table.len(), 1); + + // when + let r = table.remove(&5, &4); + + // then + assert!(table.is_empty()); + assert_eq!(table.len() ,0); + assert_eq!(r.unwrap(), true); + } + + #[test] + fn should_return_none_if_trying_to_remove_non_existing_element() { + // given + let mut table : Table = Table::new(); + assert!(table.is_empty()); + + // when + let r = table.remove(&5, &4); + + // then + assert!(r.is_none()); + } + + #[test] + fn should_clear_row_if_removing_last_element() { + // given + let mut table = Table::new(); + table.insert(5, 4, true); + assert!(table.has_row(&5)); + + // when + let r = table.remove(&5, &4); + + // then + assert!(r.is_some()); + assert!(!table.has_row(&5)); + } + + #[test] + fn should_return_element_given_row_and_col() { + // given + let mut table = Table::new(); + table.insert(1551, 1234, 123); + + // when + let r1 = table.get(&1551, &1234); + let r2 = table.get(&5, &4); + + // then + assert!(r1.is_some()); + assert!(r2.is_none()); + assert_eq!(r1.unwrap(), &123); + } + + #[test] + fn should_clear_table() { + // given + let mut table = Table::new(); + table.insert(1, 1, true); + table.insert(1, 2, false); + table.insert(2, 2, false); + assert_eq!(table.len(), 3); + + // when + table.clear(); + + // then + assert!(table.is_empty()); + assert_eq!(table.len(), 0); + assert_eq!(table.has_row(&1), false); + assert_eq!(table.has_row(&2), false); + } + + #[test] + fn should_return_mutable_row() { + // given + let mut table = Table::new(); + table.insert(1, 1, true); + table.insert(1, 2, false); + table.insert(2, 2, false); + + // when + { + let mut row = table.get_row_mut(&1).unwrap(); + row.remove(&1); + row.remove(&2); + } + assert!(table.has_row(&1)); + table.clear_if_empty(&1); + + // then + assert!(!table.has_row(&1)); + assert_eq!(table.len(), 1); + } +} From 212aac42bdb820f9a030279af9a4b0439d424cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 29 Feb 2016 23:09:51 +0100 Subject: [PATCH 06/14] Removing clippy warnings --- util/src/keys/geth_import.rs | 16 ++++++++-------- util/src/network/host.rs | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/util/src/keys/geth_import.rs b/util/src/keys/geth_import.rs index 2ee3c987c..cdbd9b213 100644 --- a/util/src/keys/geth_import.rs +++ b/util/src/keys/geth_import.rs @@ -46,14 +46,14 @@ pub fn enumerate_geth_keys(path: &Path) -> Result, io::Er #[derive(Debug)] pub enum ImportError { /// Io error reading geth file - IoError(io::Error), + Io(io::Error), /// format error - FormatError, + Format, } impl From for ImportError { fn from (err: io::Error) -> ImportError { - ImportError::IoError(err) + ImportError::Io(err) } } @@ -65,15 +65,15 @@ pub fn import_geth_key(secret_store: &mut SecretStore, geth_keyfile_path: &Path) let mut json_result = Json::from_str(&buf); let mut json = match json_result { - Ok(ref mut parsed_json) => try!(parsed_json.as_object_mut().ok_or(ImportError::FormatError)), - Err(_) => { return Err(ImportError::FormatError); } + Ok(ref mut parsed_json) => try!(parsed_json.as_object_mut().ok_or(ImportError::Format)), + Err(_) => { return Err(ImportError::Format); } }; - let crypto_object = try!(json.get("Crypto").and_then(|crypto| crypto.as_object()).ok_or(ImportError::FormatError)).clone(); + let crypto_object = try!(json.get("Crypto").and_then(|crypto| crypto.as_object()).ok_or(ImportError::Format)).clone(); json.insert("crypto".to_owned(), Json::Object(crypto_object)); json.remove("Crypto"); match KeyFileContent::load(&Json::Object(json.clone())) { Ok(key_file) => try!(secret_store.import_key(key_file)), - Err(_) => { return Err(ImportError::FormatError); } + Err(_) => { return Err(ImportError::Format); } }; Ok(()) } @@ -82,7 +82,7 @@ pub fn import_geth_key(secret_store: &mut SecretStore, geth_keyfile_path: &Path) pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory: &Path) -> Result<(), ImportError> { use std::path::PathBuf; let geth_files = try!(enumerate_geth_keys(geth_keyfiles_directory)); - for &(ref address, ref file_path) in geth_files.iter() { + for &(ref address, ref file_path) in &geth_files { let mut path = PathBuf::new(); path.push(geth_keyfiles_directory); path.push(file_path); diff --git a/util/src/network/host.rs b/util/src/network/host.rs index f54c85855..42e8ff93d 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -376,7 +376,7 @@ impl Host where Message: Send + Sync + Clone { let entry = NodeEntry { endpoint: n.endpoint.clone(), id: n.id.clone() }; self.pinned_nodes.push(n.id.clone()); self.nodes.write().unwrap().add_node(n); - if let &mut Some(ref mut discovery) = self.discovery.lock().unwrap().deref_mut() { + if let Some(ref mut discovery) = *self.discovery.lock().unwrap().deref_mut() { discovery.add_node(entry); } } @@ -418,7 +418,7 @@ impl Host where Message: Send + Sync + Clone { } Some(addr) => NodeEndpoint { address: addr, udp_port: udp_port } }; - + // Setup the server socket *tcp_listener = Some(TcpListener::bind(&listen_address).unwrap()); self.info.write().unwrap().public_endpoint = public_endpoint.clone(); @@ -697,7 +697,7 @@ impl Host where Message: Send + Sync + Clone { let entry = NodeEntry { id: session.id().clone(), endpoint: NodeEndpoint { address: address, udp_port: address.port() } }; self.nodes.write().unwrap().add_node(Node::new(entry.id.clone(), entry.endpoint.clone())); let mut discovery = self.discovery.lock().unwrap(); - if let &mut Some(ref mut discovery) = discovery.deref_mut() { + if let Some(ref mut discovery) = *discovery.deref_mut() { discovery.add_node(entry); } } From 8c60eaa54864b8f7b85faf310430ca7eb657ccb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 29 Feb 2016 23:43:48 +0100 Subject: [PATCH 07/14] Unused variable --- sync/src/tests/helpers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 63a0b88bb..b788e0c2a 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -117,7 +117,7 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn logs(&self, filter: Filter) -> Vec { + fn logs(&self, _filter: Filter) -> Vec { unimplemented!(); } From 2f3b0c9d1cbc5316fb6655049196956c189cc2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 29 Feb 2016 23:57:02 +0100 Subject: [PATCH 08/14] Removing get_ prefix --- util/src/table.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/src/table.rs b/util/src/table.rs index 525002dc3..44b0282e1 100644 --- a/util/src/table.rs +++ b/util/src/table.rs @@ -56,7 +56,7 @@ impl Table } /// Get mutable reference for single Table row. - pub fn get_row_mut(&mut self, row: &Row) -> Option<&mut HashMap> { + pub fn row_mut(&mut self, row: &Row) -> Option<&mut HashMap> { self.map.get_mut(row) } @@ -66,7 +66,7 @@ impl Table } /// Get immutable reference for single row in this Table - pub fn get_row(&self, row: &Row) -> Option<&HashMap> { + pub fn row(&self, row: &Row) -> Option<&HashMap> { self.map.get(row) } @@ -97,7 +97,7 @@ impl Table /// Remove given row from Table if there are no values defined in it /// - /// When using `#get_row_mut` it may happen that all values from some row are drained. + /// When using `#row_mut` it may happen that all values from some row are drained. /// Table however will not be aware that row is empty. /// You can use this method to explicitly remove row entry from the Table. pub fn clear_if_empty(&mut self, row: &Row) { @@ -246,7 +246,7 @@ mod test { // when { - let mut row = table.get_row_mut(&1).unwrap(); + let mut row = table.row_mut(&1).unwrap(); row.remove(&1); row.remove(&2); } From ed6a35f61842bbd5714d8f57a5928ed56cdb3ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 1 Mar 2016 00:00:52 +0100 Subject: [PATCH 09/14] More idiomatic implementations --- util/src/table.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/util/src/table.rs b/util/src/table.rs index 44b0282e1..dd42f847a 100644 --- a/util/src/table.rs +++ b/util/src/table.rs @@ -47,7 +47,7 @@ impl Table /// Returns length of the Table (number of (row, col, val) tuples) pub fn len(&self) -> usize { - self.map.iter().fold(0, |acc, (_k, v)| acc + v.len()) + self.map.values().fold(0, |acc, v| acc + v.len()) } /// Check if there is any element in this Table @@ -111,13 +111,7 @@ impl Table /// /// Returns previous value (if any) pub fn insert(&mut self, row: Row, col: Col, val: Val) -> Option { - if !self.map.contains_key(&row) { - let m = HashMap::new(); - self.map.insert(row.clone(), m); - } - - let mut columns = self.map.get_mut(&row).unwrap(); - columns.insert(col, val) + self.map.entry(row).or_insert_with(|| HashMap::new()).insert(col, val) } } From 816e549d4c9656f3c0d5be5d0ef2afcc97931e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 1 Mar 2016 00:40:55 +0100 Subject: [PATCH 10/14] Changing implementation of is_empty to something more efficient --- util/src/table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/table.rs b/util/src/table.rs index dd42f847a..f04a498f8 100644 --- a/util/src/table.rs +++ b/util/src/table.rs @@ -52,7 +52,7 @@ impl Table /// Check if there is any element in this Table pub fn is_empty(&self) -> bool { - self.len() == 0 + self.map.is_empty() || self.map.values().all(|v| v.is_empty()) } /// Get mutable reference for single Table row. From c45d3560b84e1577cabb546422d7bb065ee06536 Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Tue, 1 Mar 2016 10:09:22 +0800 Subject: [PATCH 11/14] fixup install script It's renamed in upstream. https://github.com/brson/multirust/commit/ae8e470ca6adc3f1c6844b6a23932902e5fd3ebc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8b24f088..4fd2a53cc 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ First (if you don't already have it) get multirust: - Linux: ```bash -curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sudo sh -s -- --yes +curl -sf https://raw.githubusercontent.com/brson/multirust/master/quick-install.sh | sudo sh -s -- --yes ``` - OSX with Homebrew: From ab9fddf6b2e4d00e4961d98bb418679af5325e4e Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 1 Mar 2016 13:44:09 +0100 Subject: [PATCH 12/14] blockchain generator --- ethcore/src/blockchain/blockchain.rs | 41 +++--- ethcore/src/blockchain/helpers/generators.rs | 138 +++++++++++++++++++ ethcore/src/blockchain/helpers/mod.rs | 3 + ethcore/src/blockchain/mod.rs | 2 + 4 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 ethcore/src/blockchain/helpers/generators.rs create mode 100644 ethcore/src/blockchain/helpers/mod.rs diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 8aa0fffdc..cc95b4f3b 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -447,7 +447,7 @@ impl BlockChain { let mut write_details = self.block_details.write().unwrap(); for (hash, details) in update.block_details.into_iter() { - batch.put_extras(&hash, &details); + batch.put_extras(&hash, &details); write_details.insert(hash, details); } @@ -572,7 +572,7 @@ impl BlockChain { /// This function returns modified transaction addresses. fn prepare_transaction_addresses_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap { let block = BlockView::new(block_bytes); - let transaction_hashes = block.transaction_hashes(); + let transaction_hashes = block.transaction_hashes(); transaction_hashes.into_iter() .enumerate() @@ -587,20 +587,20 @@ impl BlockChain { /// This functions returns modified blocks blooms. /// - /// To accelerate blooms lookups, blomms are stored in multiple - /// layers (BLOOM_LEVELS, currently 3). + /// To accelerate blooms lookups, blomms are stored in multiple + /// layers (BLOOM_LEVELS, currently 3). /// ChainFilter is responsible for building and rebuilding these layers. /// It returns them in HashMap, where values are Blooms and /// keys are BloomIndexes. BloomIndex represents bloom location on one /// of these layers. - /// + /// /// To reduce number of queries to databse, block blooms are stored - /// in BlocksBlooms structure which contains info about several + /// in BlocksBlooms structure which contains info about several /// (BLOOM_INDEX_SIZE, currently 16) consecutive blocks blooms. - /// + /// /// Later, BloomIndexer is used to map bloom location on filter layer (BloomIndex) /// to bloom location in database (BlocksBloomLocation). - /// + /// fn prepare_block_blooms_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap { let block = BlockView::new(block_bytes); let header = block.header_view(); @@ -766,32 +766,33 @@ mod tests { use std::str::FromStr; use rustc_serialize::hex::FromHex; use util::hash::*; + use util::sha3::Hashable; use blockchain::{BlockProvider, BlockChain, BlockChainConfig}; use tests::helpers::*; use devtools::*; + use blockchain::helpers::generators::ChainGenerator; + use views::BlockView; #[test] - fn valid_tests_extra32() { - let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a0363659b251bf8b819179874c8cce7b9b983d7f3704cbb58a3b334431f7032871889032d09c281e1236c0c0".from_hex().unwrap(); + fn basic_blockchain_insert() { + let mut canon_chain = ChainGenerator::default(); + let genesis = canon_chain.next().unwrap(); + let first = canon_chain.next().unwrap(); + let genesis_hash = BlockView::new(&genesis).header_view().sha3(); + let first_hash = BlockView::new(&first).header_view().sha3(); let temp = RandomTempPath::new(); let bc = BlockChain::new(BlockChainConfig::default(), &genesis, temp.as_path()); - let genesis_hash = H256::from_str("3caa2203f3d7c136c0295ed128a7d31cea520b1ca5e27afe17d0853331798942").unwrap(); - assert_eq!(bc.genesis_hash(), genesis_hash.clone()); assert_eq!(bc.best_block_number(), 0); assert_eq!(bc.best_block_hash(), genesis_hash.clone()); assert_eq!(bc.block_hash(0), Some(genesis_hash.clone())); assert_eq!(bc.block_hash(1), None); assert_eq!(bc.block_details(&genesis_hash).unwrap().children, vec![]); - - let first = "f90285f90219a03caa2203f3d7c136c0295ed128a7d31cea520b1ca5e27afe17d0853331798942a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0d45893a296c1490a978e0bd321b5f2635d8280365c1fe9f693d65f233e791344a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefd882560b845627cb99a00102030405060708091011121314151617181920212223242526272829303132a08ccb2837fb2923bd97e8f2d08ea32012d6e34be018c73e49a0f98843e8f47d5d88e53be49fec01012ef866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ba0cb088b8d2ff76a7b2c6616c9d02fb6b7a501afbf8b69d7180b09928a1b80b5e4a06448fe7476c606582039bb72a9f6f4b4fad18507b8dfbd00eebbe151cc573cd2c0".from_hex().unwrap(); bc.insert_block(&first, vec![]); - let first_hash = H256::from_str("a940e5af7d146b3b917c953a82e1966b906dace3a4e355b5b0a4560190357ea1").unwrap(); - assert_eq!(bc.block_hash(0), Some(genesis_hash.clone())); assert_eq!(bc.best_block_number(), 1); assert_eq!(bc.best_block_hash(), first_hash.clone()); @@ -961,7 +962,7 @@ mod tests { let temp = RandomTempPath::new(); let bc = BlockChain::new(BlockChainConfig::default(), &genesis, temp.as_path()); bc.insert_block(&b1, vec![]); - + let transactions = bc.transactions(&b1_hash).unwrap(); assert_eq!(transactions.len(), 7); for t in transactions { @@ -981,7 +982,7 @@ mod tests { // prepare for fork (b1a, child of genesis) let b1a = "f902ccf901f9a05716670833ec874362d65fea27a7cd35af5897d275b31a44944113111e4e96d2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c70a5dc56146e5ef025e4e5726a6373c6f12fd2f6784093a19ead0a7d17fb292a040645cbce4fd399e7bb9160b4c30c40d7ee616a030d4e18ef0ed3b02bdb65911a086e608555f63628417032a011d107b36427af37d153f0da02ce3f90fdd5e8c08b90100000000000000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004001832fefd882c0e384562791e880a0e3cc39ff775cc0a32f175995b92e84b729e5c9a3563ff899e3555b908bc21d75887c3cde283f4846a6f8cdf8cb01018304cb2f8080b87e6060604052606e8060106000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063c0406226146037576035565b005b60406004506056565b6040518082815260200191505060405180910390f35b6000600560006000508190555060059050606b565b90561ba05258615c63503c0a600d6994b12ea5750d45b3c69668e2a371b4fbfb9eeff6b8a0a11be762bc90491231274a2945be35a43f23c27775b1ff24dd521702fe15f73ec0".from_hex().unwrap(); - + // fork (b2a, child of b1a, with higher total difficulty) let b2a = "f902ccf901f9a0626b0774a7cbdad7bdce07b87d74b6fa91c1c359d725076215d76348f8399f56a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c70a5dc56146e5ef025e4e5726a6373c6f12fd2f6784093a19ead0a7d17fb292a040645cbce4fd399e7bb9160b4c30c40d7ee616a030d4e18ef0ed3b02bdb65911a086e608555f63628417032a011d107b36427af37d153f0da02ce3f90fdd5e8c08b90100000000000000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd882c0e384562791e880a0e3cc39ff775cc0a32f175995b92e84b729e5c9a3563ff899e3555b908bc21d75887c3cde283f4846a6f8cdf8cb01018304cb2f8080b87e6060604052606e8060106000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063c0406226146037576035565b005b60406004506056565b6040518082815260200191505060405180910390f35b6000600560006000508190555060059050606b565b90561ba05258615c63503c0a600d6994b12ea5750d45b3c69668e2a371b4fbfb9eeff6b8a0a11be762bc90491231274a2945be35a43f23c27775b1ff24dd521702fe15f73ec0".from_hex().unwrap(); @@ -1001,7 +1002,7 @@ mod tests { let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); assert_eq!(blocks_b1, vec![]); assert_eq!(blocks_b2, vec![]); - + bc.insert_block(&b1, vec![]); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); @@ -1043,4 +1044,6 @@ mod tests { } + + } diff --git a/ethcore/src/blockchain/helpers/generators.rs b/ethcore/src/blockchain/helpers/generators.rs new file mode 100644 index 000000000..8416a07ad --- /dev/null +++ b/ethcore/src/blockchain/helpers/generators.rs @@ -0,0 +1,138 @@ +use util::rlp::*; +use util::hash::{H256, H2048}; +use util::uint::{U256}; +use util::bytes::Bytes; +use header::{BlockNumber, Header}; +use transaction::SignedTransaction; + +/// Chain iterator interface. +pub trait ChainIterator: Iterator { + /// Should be called to create a fork of current iterator. + /// Blocks generated by fork will have lower difficulty than current chain. + fn fork(&mut self) -> Self; + /// Should be called to create new block with given bloom. + fn next_with_bloom(&mut self, bloom: H2048) -> Option; +} + +/// Helper structure, used for encoding blocks. +#[derive(Default)] +struct Block { + header: Header, + transactions: Vec, + uncles: Vec
+} + +impl Encodable for Block { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(3); + s.append(&self.header); + s.append(&self.transactions); + s.append(&self.uncles); + } +} + +/// Blockchain generator. +pub struct ChainGenerator { + /// Next block number. + number: BlockNumber, + /// Next block parent hash. + parent_hash: H256, + /// Next block difficulty. + difficulty: U256, + /// Number of forks of current block. + number_of_forks: usize, +} + +impl ChainGenerator { + fn prepare_block(&self) -> Block { + let mut block = Block::default(); + block.header.parent_hash = self.parent_hash.clone(); + block.header.number = self.number; + block.header.difficulty = self.difficulty; + block + } +} + +impl Default for ChainGenerator { + fn default() -> Self { + ChainGenerator { + number: 0, + parent_hash: H256::default(), + difficulty: U256::from(1000), + number_of_forks: 0 + } + } +} + +impl Iterator for ChainGenerator { + type Item = Bytes; + + fn next(&mut self) -> Option { + let block = self.prepare_block(); + self.number += 1; + self.parent_hash = block.header.hash(); + self.number_of_forks = 0; + Some(encode(&block).to_vec()) + } +} + +impl ChainIterator for ChainGenerator { + fn fork(&mut self) -> Self { + self.number_of_forks += 1; + ChainGenerator { + number: self.number, + parent_hash: self.parent_hash.clone(), + difficulty: self.difficulty - U256::from(self.number_of_forks), + number_of_forks: 0 + } + } + + fn next_with_bloom(&mut self, bloom: H2048) -> Option { + let mut block = self.prepare_block(); + block.header.log_bloom = bloom; + self.number += 1; + self.parent_hash = block.header.hash(); + self.number_of_forks = 0; + Some(encode(&block).to_vec()) + } +} + +#[cfg(test)] +mod tests { + use util::hash::H256; + use util::sha3::Hashable; + use views::BlockView; + use super::{ChainIterator, ChainGenerator}; + + #[test] + fn canon_chain_generator() { + let mut canon_chain = ChainGenerator::default(); + + let genesis_rlp = canon_chain.next().unwrap(); + let genesis = BlockView::new(&genesis_rlp); + + assert_eq!(genesis.header_view().parent_hash(), H256::default()); + assert_eq!(genesis.header_view().number(), 0); + + let b1_rlp = canon_chain.next().unwrap(); + let b1 = BlockView::new(&b1_rlp); + + assert_eq!(b1.header_view().parent_hash(), genesis.header_view().sha3()); + assert_eq!(b1.header_view().number(), 1); + + let mut fork_chain = canon_chain.fork(); + + let b2_rlp_fork = fork_chain.next().unwrap(); + let b2_fork = BlockView::new(&b2_rlp_fork); + + assert_eq!(b2_fork.header_view().parent_hash(), b1.header_view().sha3()); + assert_eq!(b2_fork.header_view().number(), 2); + + let b2_rlp = canon_chain.next().unwrap(); + let b2 = BlockView::new(&b2_rlp); + + assert_eq!(b2.header_view().parent_hash(), b1.header_view().sha3()); + assert_eq!(b2.header_view().number(), 2); + assert!(b2.header_view().difficulty() > b2_fork.header_view().difficulty()); + } +} diff --git a/ethcore/src/blockchain/helpers/mod.rs b/ethcore/src/blockchain/helpers/mod.rs new file mode 100644 index 000000000..0240bd00f --- /dev/null +++ b/ethcore/src/blockchain/helpers/mod.rs @@ -0,0 +1,3 @@ +pub mod generators; + +//pub use self::blockchain_builder::BlockChainBuilder; diff --git a/ethcore/src/blockchain/mod.rs b/ethcore/src/blockchain/mod.rs index c1046d960..60a1aeb33 100644 --- a/ethcore/src/blockchain/mod.rs +++ b/ethcore/src/blockchain/mod.rs @@ -23,6 +23,8 @@ mod bloom_indexer; mod cache; mod tree_route; mod update; +#[cfg(test)] +mod helpers; pub use self::blockchain::{BlockProvider, BlockChain, BlockChainConfig}; pub use self::cache::CacheSize; From 063020f5075f245b0c70c1a5c1918229efe25fe4 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 1 Mar 2016 13:46:33 +0100 Subject: [PATCH 13/14] added license headers --- ethcore/src/blockchain/helpers/generators.rs | 16 ++++++++++++++++ ethcore/src/blockchain/helpers/mod.rs | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/ethcore/src/blockchain/helpers/generators.rs b/ethcore/src/blockchain/helpers/generators.rs index 8416a07ad..75e7655eb 100644 --- a/ethcore/src/blockchain/helpers/generators.rs +++ b/ethcore/src/blockchain/helpers/generators.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + use util::rlp::*; use util::hash::{H256, H2048}; use util::uint::{U256}; diff --git a/ethcore/src/blockchain/helpers/mod.rs b/ethcore/src/blockchain/helpers/mod.rs index 0240bd00f..233f8f1f8 100644 --- a/ethcore/src/blockchain/helpers/mod.rs +++ b/ethcore/src/blockchain/helpers/mod.rs @@ -1,3 +1,17 @@ -pub mod generators; +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. -//pub use self::blockchain_builder::BlockChainBuilder; +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +pub mod generators; From 47688e49cd19f68660ddff28c51f437019b3cb7d Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 1 Mar 2016 13:54:14 +0100 Subject: [PATCH 14/14] removed redundant whitespaces --- ethcore/src/blockchain/blockchain.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index cc95b4f3b..0aba36a8e 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1042,8 +1042,4 @@ mod tests { assert_eq!(blocks_b2, vec![2]); assert_eq!(blocks_ba, vec![3]); } - - - - }