From 4394c31a219411c5eda741d2149268af2c8a2dbd Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 29 Aug 2016 12:07:30 +0200 Subject: [PATCH 1/8] Disabled counter check --- util/src/journaldb/archivedb.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index 863b490a6..5f1eb71d4 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -163,7 +163,6 @@ impl JournalDB for ArchiveDB { for i in self.overlay.drain().into_iter() { let (key, (value, rc)) = i; if rc > 0 { - assert!(rc == 1); batch.put(self.column, &key, &value); inserts += 1; } @@ -192,7 +191,6 @@ impl JournalDB for ArchiveDB { for i in self.overlay.drain().into_iter() { let (key, (value, rc)) = i; if rc > 0 { - assert!(rc == 1); if try!(self.backing.get(self.column, &key)).is_some() { return Err(BaseDataError::AlreadyExists(key).into()); } From a34bd389ce98625846393bacc26fb71417164c2a Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 30 Aug 2016 11:10:59 +0200 Subject: [PATCH 2/8] builtin trait refactoring --- ethcore/src/builtin.rs | 501 +++++++++++++++++++++++------------------ 1 file changed, 284 insertions(+), 217 deletions(-) diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index d4ea5e30e..bcd02cbf3 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -14,283 +14,350 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use crypto::sha2::Sha256; -use crypto::ripemd160::Ripemd160; +use crypto::sha2::Sha256 as Sha256Digest; +use crypto::ripemd160::Ripemd160 as Ripemd160Digest; use crypto::digest::Digest; use util::*; -use ethkey::{Signature, recover}; +use ethkey::{Signature, recover as ec_recover}; use ethjson; -/// Definition of a contract whose implementation is built-in. -pub struct Builtin { - /// The gas cost of running this built-in for the given size of input data. - pub cost: Box U256>, // TODO: U256 should be bignum. - /// Run this built-in function with the input being the first argument and the output - /// being placed into the second. - pub execute: Box, +/// Native implementation of a built-in contract. +pub trait Impl: Send + Sync { + /// execute this built-in on the given input, writing to the given output. + fn execute(&self, input: &[u8], out: &mut [u8]); } -// Rust does not mark closurer that do not capture as Sync -// We promise that all builtins are thread safe since they only operate on given input. -unsafe impl Sync for Builtin {} -unsafe impl Send for Builtin {} +/// A gas pricing scheme for built-in contracts. +pub trait Pricer: Send + Sync { + /// The gas cost of running this built-in for the given size of input data. + fn cost(&self, in_size: usize) -> U256; +} -impl fmt::Debug for Builtin { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "") +/// A linear pricing model. This computes a price using a base cost and a cost per-word. +struct Linear { + base: usize, + word: usize, +} + +impl Pricer for Linear { + fn cost(&self, in_size: usize) -> U256 { + U256::from(self.base) + U256::from(self.word) * U256::from((in_size + 31) / 32) } } +/// Pricing scheme and execution definition for a built-in contract. +pub struct Builtin { + pricer: Box, + native: Box, +} + impl Builtin { - /// Create a new object from components. - pub fn new(cost: Box U256>, execute: Box) -> Builtin { - Builtin {cost: cost, execute: execute} - } - - /// Create a new object from a builtin-function name with a linear cost associated with input size. - pub fn from_named_linear(name: &str, base_cost: usize, word_cost: usize) -> Builtin { - let cost = Box::new(move|s: usize| -> U256 { - U256::from(base_cost) + U256::from(word_cost) * U256::from((s + 31) / 32) - }); - - Self::new(cost, new_builtin_exec(name)) - } - /// Simple forwarder for cost. - pub fn cost(&self, s: usize) -> U256 { (*self.cost)(s) } + pub fn cost(&self, s: usize) -> U256 { self.pricer.cost(s) } /// Simple forwarder for execute. - pub fn execute(&self, input: &[u8], output: &mut[u8]) { (*self.execute)(input, output); } + pub fn execute(&self, input: &[u8], output: &mut[u8]) { self.native.execute(input, output) } } impl From for Builtin { fn from(b: ethjson::spec::Builtin) -> Self { - match b.pricing { + let pricer = match b.pricing { ethjson::spec::Pricing::Linear(linear) => { - Self::from_named_linear(b.name.as_ref(), linear.base, linear.word) + Box::new(Linear { + base: linear.base, + word: linear.word, + }) } + }; + + Builtin { + pricer: pricer, + native: ethereum_builtin(&b.name), } } } -/// Copy a bunch of bytes to a destination; if the `src` is too small to fill `dest`, -/// leave the rest unchanged. -pub fn copy_to(src: &[u8], dest: &mut[u8]) { - // NICE: optimise - for i in 0..min(src.len(), dest.len()) { - dest[i] = src[i]; +// Ethereum builtin creator. +fn ethereum_builtin(name: &str) -> Box { + match name { + "identity" => Box::new(Identity) as Box, + "ecrecover" => Box::new(EcRecover) as Box, + "sha256" => Box::new(Sha256) as Box, + "ripemd160" => Box::new(Ripemd160) as Box, + _ => panic!("invalid builtin name: {}", name), } } -/// Create a new builtin executor according to `name`. -/// TODO: turn in to a factory with dynamic registration. -pub fn new_builtin_exec(name: &str) -> Box { - match name { - "identity" => Box::new(move|input: &[u8], output: &mut[u8]| { - for i in 0..min(input.len(), output.len()) { - output[i] = input[i]; - } - }), - "ecrecover" => Box::new(move|input: &[u8], output: &mut[u8]| { - #[repr(packed)] - #[derive(Debug, Default)] - struct InType { - hash: H256, - v: H256, - r: H256, - s: H256, - } - let mut it = InType::default(); - it.copy_raw(input); - if it.v == H256::from(&U256::from(27)) || it.v == H256::from(&U256::from(28)) { - let s = Signature::from_rsv(&it.r, &it.s, it.v[31] - 27); - if s.is_valid() { - if let Ok(p) = recover(&s, &it.hash) { - let r = p.as_slice().sha3(); - // NICE: optimise and separate out into populate-like function - for i in 0..min(32, output.len()) { - output[i] = if i < 12 {0} else {r[i]}; - } - } +// Ethereum builtins: +// +// - The identity function +// - ec recovery +// - sha256 +// - ripemd160 + +#[derive(Debug)] +struct Identity; + +#[derive(Debug)] +struct EcRecover; + +#[derive(Debug)] +struct Sha256; + +#[derive(Debug)] +struct Ripemd160; + +impl Impl for Identity { + fn execute(&self, input: &[u8], output: &mut [u8]) { + let len = min(input.len(), output.len()); + output[..len].copy_from_slice(&input[..len]); + } +} + +impl Impl for EcRecover { + fn execute(&self, i: &[u8], output: &mut [u8]) { + let len = min(i.len(), 128); + + let mut input = [0; 128]; + input[..len].copy_from_slice(&i[..len]); + + let hash = H256::from_slice(&input[0..32]); + let v = H256::from_slice(&input[32..64]); + let r = H256::from_slice(&input[64..96]); + let s = H256::from_slice(&input[96..128]); + + let bit = match v[31] { + 27 | 28 if &v.as_slice()[..31] == &[0; 31] => v[31] - 27, + _ => return, + }; + + let s = Signature::from_rsv(&r, &s, bit); + if s.is_valid() { + if let Ok(p) = ec_recover(&s, &hash) { + let r = p.as_slice().sha3(); + + let out_len = min(output.len(), 32); + + for x in &mut output[0.. min(12, out_len)] { + *x = 0; + } + + if out_len > 12 { + output[12..out_len].copy_from_slice(&r[12..out_len]); } } - }), - "sha256" => Box::new(move|input: &[u8], output: &mut[u8]| { - let mut sha = Sha256::new(); - sha.input(input); - if output.len() >= 32 { - sha.result(output); - } else { - let mut ret = H256::new(); - sha.result(ret.as_slice_mut()); - copy_to(&ret, output); - } - }), - "ripemd160" => Box::new(move|input: &[u8], output: &mut[u8]| { - let mut sha = Ripemd160::new(); - sha.input(input); - let mut ret = H256::new(); - sha.result(&mut ret.as_slice_mut()[12..32]); - copy_to(&ret, output); - }), - _ => { - panic!("invalid builtin name {}", name); } } } -#[test] -fn identity() { - let f = new_builtin_exec("identity"); - let i = [0u8, 1, 2, 3]; +impl Impl for Sha256 { + fn execute(&self, input: &[u8], output: &mut [u8]) { + let out_len = min(output.len(), 32); - let mut o2 = [255u8; 2]; - f(&i[..], &mut o2[..]); - assert_eq!(i[0..2], o2); + let mut sha = Sha256Digest::new(); + sha.input(input); - let mut o4 = [255u8; 4]; - f(&i[..], &mut o4[..]); - assert_eq!(i, o4); + if out_len == 32 { + sha.result(&mut output[0..32]); + } else { + let mut out = [0; 32]; + sha.result(&mut out); - let mut o8 = [255u8; 8]; - f(&i[..], &mut o8[..]); - assert_eq!(i, o8[..4]); - assert_eq!([255u8; 4], o8[4..]); + output.copy_from_slice(&out[..out_len]) + } + } } -#[test] -fn sha256() { - use rustc_serialize::hex::FromHex; - let f = new_builtin_exec("sha256"); - let i = [0u8; 0]; +impl Impl for Ripemd160 { + fn execute(&self, input: &[u8], output: &mut [u8]) { + let out_len = min(output.len(), 32); - let mut o = [255u8; 32]; - f(&i[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855").unwrap())[..]); + let mut sha = Ripemd160Digest::new(); + sha.input(input); - let mut o8 = [255u8; 8]; - f(&i[..], &mut o8[..]); - assert_eq!(&o8[..], &(FromHex::from_hex("e3b0c44298fc1c14").unwrap())[..]); + for x in &mut output[0.. min(12, out_len)] { + *x = 0; + } - let mut o34 = [255u8; 34]; - f(&i[..], &mut o34[..]); - assert_eq!(&o34[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ffff").unwrap())[..]); + if out_len >= 32 { + sha.result(&mut output[12..32]); + } else if out_len > 12 { + let mut out = [0; 20]; + sha.result(&mut out); + + output.copy_from_slice(&out[12..out_len]) + } + } } -#[test] -fn ripemd160() { - use rustc_serialize::hex::FromHex; - let f = new_builtin_exec("ripemd160"); - let i = [0u8; 0]; +#[cfg(test)] +mod tests { + use super::{Builtin, Linear, ethereum_builtin, Pricer}; + use ethjson; + use util::U256; - let mut o = [255u8; 32]; - f(&i[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31").unwrap())[..]); + #[test] + fn identity() { + let f = ethereum_builtin("identity"); - let mut o8 = [255u8; 8]; - f(&i[..], &mut o8[..]); - assert_eq!(&o8[..], &(FromHex::from_hex("0000000000000000").unwrap())[..]); + let i = [0u8, 1, 2, 3]; - let mut o34 = [255u8; 34]; - f(&i[..], &mut o34[..]); - assert_eq!(&o34[..], &(FromHex::from_hex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31ffff").unwrap())[..]); -} + let mut o2 = [255u8; 2]; + f.execute(&i[..], &mut o2[..]); + assert_eq!(i[0..2], o2); -#[test] -fn ecrecover() { - use rustc_serialize::hex::FromHex; - /*let k = KeyPair::from_secret(b"test".sha3()).unwrap(); - let a: Address = From::from(k.public().sha3()); - println!("Address: {}", a); - let m = b"hello world".sha3(); - println!("Message: {}", m); - let s = k.sign(&m).unwrap(); - println!("Signed: {}", s);*/ + let mut o4 = [255u8; 4]; + f.execute(&i[..], &mut o4[..]); + assert_eq!(i, o4); - let f = new_builtin_exec("ecrecover"); - let i = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); + let mut o8 = [255u8; 8]; + f.execute(&i[..], &mut o8[..]); + assert_eq!(i, o8[..4]); + assert_eq!([255u8; 4], o8[4..]); + } - let mut o = [255u8; 32]; - f(&i[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("000000000000000000000000c08b5542d177ac6686946920409741463a15dddb").unwrap())[..]); + #[test] + fn sha256() { + use rustc_serialize::hex::FromHex; + let f = ethereum_builtin("sha256"); - let mut o8 = [255u8; 8]; - f(&i[..], &mut o8[..]); - assert_eq!(&o8[..], &(FromHex::from_hex("0000000000000000").unwrap())[..]); + let i = [0u8; 0]; - let mut o34 = [255u8; 34]; - f(&i[..], &mut o34[..]); - assert_eq!(&o34[..], &(FromHex::from_hex("000000000000000000000000c08b5542d177ac6686946920409741463a15dddbffff").unwrap())[..]); + let mut o = [255u8; 32]; + f.execute(&i[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855").unwrap())[..]); - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001a650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); - let mut o = [255u8; 32]; - f(&i_bad[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + let mut o8 = [255u8; 8]; + f.execute(&i[..], &mut o8[..]); + assert_eq!(&o8[..], &(FromHex::from_hex("e3b0c44298fc1c14").unwrap())[..]); - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let mut o = [255u8; 32]; - f(&i_bad[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + let mut o34 = [255u8; 34]; + f.execute(&i[..], &mut o34[..]); + assert_eq!(&o34[..], &(FromHex::from_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ffff").unwrap())[..]); + } - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b").unwrap(); - let mut o = [255u8; 32]; - f(&i_bad[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + #[test] + fn ripemd160() { + use rustc_serialize::hex::FromHex; + let f = ethereum_builtin("ripemd160"); - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001b").unwrap(); - let mut o = [255u8; 32]; - f(&i_bad[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + let i = [0u8; 0]; - let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); - let mut o = [255u8; 32]; - f(&i_bad[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + let mut o = [255u8; 32]; + f.execute(&i[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31").unwrap())[..]); - // TODO: Should this (corrupted version of the above) fail rather than returning some address? -/* let i_bad = FromHex::from_hex("48173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); - let mut o = [255u8; 32]; - f(&i_bad[..], &mut o[..]); - assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]);*/ -} + let mut o8 = [255u8; 8]; + f.execute(&i[..], &mut o8[..]); + assert_eq!(&o8[..], &(FromHex::from_hex("0000000000000000").unwrap())[..]); -#[test] -#[should_panic] -fn from_unknown_linear() { - let _ = Builtin::from_named_linear("dw", 10, 20); -} + let mut o34 = [255u8; 34]; + f.execute(&i[..], &mut o34[..]); + assert_eq!(&o34[..], &(FromHex::from_hex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31ffff").unwrap())[..]); + } -#[test] -fn from_named_linear() { - let b = Builtin::from_named_linear("identity", 10, 20); - assert_eq!((*b.cost)(0), U256::from(10)); - assert_eq!((*b.cost)(1), U256::from(30)); - assert_eq!((*b.cost)(32), U256::from(30)); - assert_eq!((*b.cost)(33), U256::from(50)); + #[test] + fn ecrecover() { + use rustc_serialize::hex::FromHex; + /*let k = KeyPair::from_secret(b"test".sha3()).unwrap(); + let a: Address = From::from(k.public().sha3()); + println!("Address: {}", a); + let m = b"hello world".sha3(); + println!("Message: {}", m); + let s = k.sign(&m).unwrap(); + println!("Signed: {}", s);*/ - let i = [0u8, 1, 2, 3]; - let mut o = [255u8; 4]; - (*b.execute)(&i[..], &mut o[..]); - assert_eq!(i, o); -} + let f = ethereum_builtin("ecrecover"); -#[test] -fn from_json() { - let b = Builtin::from(ethjson::spec::Builtin { - name: "identity".to_owned(), - pricing: ethjson::spec::Pricing::Linear(ethjson::spec::Linear { - base: 10, - word: 20, - }) - }); + let i = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); - assert_eq!((*b.cost)(0), U256::from(10)); - assert_eq!((*b.cost)(1), U256::from(30)); - assert_eq!((*b.cost)(32), U256::from(30)); - assert_eq!((*b.cost)(33), U256::from(50)); + let mut o = [255u8; 32]; + f.execute(&i[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("000000000000000000000000c08b5542d177ac6686946920409741463a15dddb").unwrap())[..]); - let i = [0u8, 1, 2, 3]; - let mut o = [255u8; 4]; - (*b.execute)(&i[..], &mut o[..]); - assert_eq!(i, o); -} + let mut o8 = [255u8; 8]; + f.execute(&i[..], &mut o8[..]); + assert_eq!(&o8[..], &(FromHex::from_hex("0000000000000000").unwrap())[..]); + + let mut o34 = [255u8; 34]; + f.execute(&i[..], &mut o34[..]); + assert_eq!(&o34[..], &(FromHex::from_hex("000000000000000000000000c08b5542d177ac6686946920409741463a15dddbffff").unwrap())[..]); + + let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001a650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); + let mut o = [255u8; 32]; + f.execute(&i_bad[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + + let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let mut o = [255u8; 32]; + f.execute(&i_bad[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + + let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b").unwrap(); + let mut o = [255u8; 32]; + f.execute(&i_bad[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + + let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000001b").unwrap(); + let mut o = [255u8; 32]; + f.execute(&i_bad[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + + let i_bad = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); + let mut o = [255u8; 32]; + f.execute(&i_bad[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]); + + // TODO: Should this (corrupted version of the above) fail rather than returning some address? + /* let i_bad = FromHex::from_hex("48173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); + let mut o = [255u8; 32]; + f.execute(&i_bad[..], &mut o[..]); + assert_eq!(&o[..], &(FromHex::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap())[..]);*/ + } + + #[test] + #[should_panic] + fn from_unknown_linear() { + let _ = ethereum_builtin("foo"); + } + + #[test] + fn from_named_linear() { + let pricer = Box::new(Linear { base: 10, word: 20 }); + let b = Builtin { + pricer: pricer as Box, + native: ethereum_builtin("identity"), + }; + + assert_eq!(b.cost(0), U256::from(10)); + assert_eq!(b.cost(1), U256::from(30)); + assert_eq!(b.cost(32), U256::from(30)); + assert_eq!(b.cost(33), U256::from(50)); + + let i = [0u8, 1, 2, 3]; + let mut o = [255u8; 4]; + b.execute(&i[..], &mut o[..]); + assert_eq!(i, o); + } + + #[test] + fn from_json() { + let b = Builtin::from(ethjson::spec::Builtin { + name: "identity".to_owned(), + pricing: ethjson::spec::Pricing::Linear(ethjson::spec::Linear { + base: 10, + word: 20, + }) + }); + + assert_eq!(b.cost(0), U256::from(10)); + assert_eq!(b.cost(1), U256::from(30)); + assert_eq!(b.cost(32), U256::from(30)); + assert_eq!(b.cost(33), U256::from(50)); + + let i = [0u8, 1, 2, 3]; + let mut o = [255u8; 4]; + b.execute(&i[..], &mut o[..]); + assert_eq!(i, o); + } +} \ No newline at end of file From 76966ab2fc191f3aaa5dbf4bf212cffdc8c63bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 30 Aug 2016 16:05:18 +0200 Subject: [PATCH 3/8] Fixing redirection. Adding tests --- dapps/src/handlers/redirect.rs | 3 +- dapps/src/lib.rs | 9 +- dapps/src/router/mod.rs | 7 +- dapps/src/tests/api.rs | 84 ++++++++++++++ dapps/src/tests/authorization.rs | 79 +++++++++++++ dapps/src/tests/helpers.rs | 123 ++++++++++++++++++++ dapps/src/tests/mod.rs | 25 +++++ dapps/src/tests/redirection.rs | 185 +++++++++++++++++++++++++++++++ dapps/src/tests/validation.rs | 79 +++++++++++++ 9 files changed, 591 insertions(+), 3 deletions(-) create mode 100644 dapps/src/tests/api.rs create mode 100644 dapps/src/tests/authorization.rs create mode 100644 dapps/src/tests/helpers.rs create mode 100644 dapps/src/tests/mod.rs create mode 100644 dapps/src/tests/redirection.rs create mode 100644 dapps/src/tests/validation.rs diff --git a/dapps/src/handlers/redirect.rs b/dapps/src/handlers/redirect.rs index dbe5f6e4a..8b6158266 100644 --- a/dapps/src/handlers/redirect.rs +++ b/dapps/src/handlers/redirect.rs @@ -42,7 +42,8 @@ impl server::Handler for Redirection { } fn on_response(&mut self, res: &mut server::Response) -> Next { - res.set_status(StatusCode::MovedPermanently); + // Don't use `MovedPermanently` here to prevent browser from caching the redirections. + res.set_status(StatusCode::Found); res.headers_mut().set(header::Location(self.to_url.to_owned())); Next::write() } diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index a2c17a42c..2beef0639 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -71,6 +71,8 @@ mod rpc; mod api; mod proxypac; mod url; +#[cfg(test)] +mod tests; pub use self::apps::urlhint::ContractClient; @@ -205,6 +207,11 @@ impl Server { pub fn set_panic_handler(&self, handler: F) where F : Fn() -> () + Send + 'static { *self.panic_handler.lock().unwrap() = Some(Box::new(handler)); } + + /// Returns address that this server is bound to. + pub fn addr(&self) -> &SocketAddr { + self.server.as_ref().unwrap().addr() + } } impl Drop for Server { @@ -239,7 +246,7 @@ pub fn random_filename() -> String { } #[cfg(test)] -mod tests { +mod util_tests { use super::Server; #[test] diff --git a/dapps/src/router/mod.rs b/dapps/src/router/mod.rs index 359337047..94d0a0fc0 100644 --- a/dapps/src/router/mod.rs +++ b/dapps/src/router/mod.rs @@ -83,7 +83,7 @@ impl server::Handler for Router { (Some(ref path), _) if self.endpoints.contains_key(&path.app_id) => { self.endpoints.get(&path.app_id).unwrap().to_handler(path.clone()) }, - // Try to resolve and fetch dapp + // Try to resolve and fetch the dapp (Some(ref path), _) if self.fetch.contains(&path.app_id) => { let control = self.control.take().expect("on_request is called only once, thus control is always defined."); self.fetch.to_handler(path.clone(), control) @@ -93,6 +93,11 @@ impl server::Handler for Router { let address = apps::redirection_address(path.using_dapps_domains, self.main_page); Redirection::new(address.as_str()) }, + // Redirect any GET request to home. + _ if *req.method() == hyper::method::Method::Get => { + let address = apps::redirection_address(false, self.main_page); + Redirection::new(address.as_str()) + }, // RPC by default _ => { self.special.get(&SpecialEndpoint::Rpc).unwrap().to_handler(EndpointPath::default()) diff --git a/dapps/src/tests/api.rs b/dapps/src/tests/api.rs new file mode 100644 index 000000000..a9d3eba3b --- /dev/null +++ b/dapps/src/tests/api.rs @@ -0,0 +1,84 @@ +// 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 tests::helpers::{serve, request}; + +#[test] +fn should_return_error() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + GET /api/empty HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 404 Not Found".to_owned()); + assert_eq!(response.headers.get(0).unwrap(), "Content-Type: application/json"); + assert_eq!(response.body, format!("58\n{}\n0\n\n", r#"{"code":"404","title":"Not Found","detail":"Resource you requested has not been found."}"#)); +} + +#[test] +fn should_serve_apps() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + GET /api/apps HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + assert_eq!(response.headers.get(0).unwrap(), "Content-Type: application/json"); + assert!(response.body.contains("Parity Home Screen")); +} + +#[test] +fn should_handle_ping() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + POST /api/ping HTTP/1.1\r\n\ + Host: home.parity\r\n\ + Connection: close\r\n\ + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + assert_eq!(response.headers.get(0).unwrap(), "Content-Type: application/json"); + assert_eq!(response.body, "0\n\n".to_owned()); +} + diff --git a/dapps/src/tests/authorization.rs b/dapps/src/tests/authorization.rs new file mode 100644 index 000000000..dceb194b7 --- /dev/null +++ b/dapps/src/tests/authorization.rs @@ -0,0 +1,79 @@ +// 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 tests::helpers::{serve_with_auth, request}; + +#[test] +fn should_require_authorization() { + // given + let server = serve_with_auth("test", "test"); + + // when + let response = request(server, + "\ + GET / HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 401 Unauthorized".to_owned()); + assert_eq!(response.headers.get(0).unwrap(), "WWW-Authenticate: Basic realm=\"Parity\""); +} + +#[test] +fn should_reject_on_invalid_auth() { + // given + let server = serve_with_auth("test", "test"); + + // when + let response = request(server, + "\ + GET / HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l\r\n + \r\n\ + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 401 Unauthorized".to_owned()); + assert_eq!(response.body, "15\n

Unauthorized

\n0\n\n".to_owned()); + assert_eq!(response.headers_raw.contains("WWW-Authenticate"), false); +} + +#[test] +fn should_allow_on_valid_auth() { + // given + let server = serve_with_auth("Aladdin", "OpenSesame"); + + // when + let response = request(server, + "\ + GET /home/ HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l\r\n + \r\n\ + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); +} diff --git a/dapps/src/tests/helpers.rs b/dapps/src/tests/helpers.rs new file mode 100644 index 000000000..84f638b34 --- /dev/null +++ b/dapps/src/tests/helpers.rs @@ -0,0 +1,123 @@ +// 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 std::env; +use std::io::{Read, Write}; +use std::str::{self, Lines}; +use std::sync::Arc; +use std::net::TcpStream; +use rustc_serialize::hex::{ToHex, FromHex}; + +use ServerBuilder; +use Server; +use apps::urlhint::ContractClient; +use util::{Bytes, Address, Mutex, ToPretty}; + +const REGISTRAR: &'static str = "8e4e9b13d4b45cb0befc93c3061b1408f67316b2"; +const URLHINT: &'static str = "deadbeefcafe0000000000000000000000000000"; + +pub struct FakeRegistrar { + pub calls: Arc>>, + pub responses: Mutex>>, +} + +impl FakeRegistrar { + fn new() -> Self { + FakeRegistrar { + calls: Arc::new(Mutex::new(Vec::new())), + responses: Mutex::new( + vec![ + Ok(format!("000000000000000000000000{}", URLHINT).from_hex().unwrap()), + Ok(Vec::new()) + ] + ), + } + } +} + +impl ContractClient for FakeRegistrar { + fn registrar(&self) -> Result { + Ok(REGISTRAR.parse().unwrap()) + } + + fn call(&self, address: Address, data: Bytes) -> Result { + self.calls.lock().push((address.to_hex(), data.to_hex())); + self.responses.lock().remove(0) + } +} + +pub fn serve_hosts(hosts: Option>) -> Server { + let registrar = Arc::new(FakeRegistrar::new()); + let mut dapps_path = env::temp_dir(); + dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading"); + let builder = ServerBuilder::new(dapps_path.to_str().unwrap().into(), registrar); + builder.start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), hosts).unwrap() +} + +pub fn serve_with_auth(user: &str, pass: &str) -> Server { + let registrar = Arc::new(FakeRegistrar::new()); + let builder = ServerBuilder::new(env::temp_dir().to_str().unwrap().into(), registrar); + builder.start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), None, user, pass).unwrap() +} + +pub fn serve() -> Server { + serve_hosts(None) +} + +pub struct Response { + pub status: String, + pub headers: Vec, + pub headers_raw: String, + pub body: String, +} + +pub fn read_block(lines: &mut Lines, all: bool) -> String { + let mut block = String::new(); + loop { + let line = lines.next(); + match line { + None => break, + Some("") if !all => break, + Some(v) => { + block.push_str(v); + block.push_str("\n"); + }, + } + } + block +} + +pub fn request(server: Server, request: &str) -> Response { + let mut req = TcpStream::connect(server.addr()).unwrap(); + req.write_all(request.as_bytes()).unwrap(); + + let mut response = String::new(); + req.read_to_string(&mut response).unwrap(); + + let mut lines = response.lines(); + let status = lines.next().unwrap().to_owned(); + let headers_raw = read_block(&mut lines, false); + let headers = headers_raw.split('\n').map(|v| v.to_owned()).collect(); + let body = read_block(&mut lines, true); + + Response { + status: status, + headers: headers, + headers_raw: headers_raw, + body: body, + } +} + diff --git a/dapps/src/tests/mod.rs b/dapps/src/tests/mod.rs new file mode 100644 index 000000000..8c5bf2283 --- /dev/null +++ b/dapps/src/tests/mod.rs @@ -0,0 +1,25 @@ +// 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 . + +//! Dapps server test suite + +mod helpers; + +mod api; +mod authorization; +mod redirection; +mod validation; + diff --git a/dapps/src/tests/redirection.rs b/dapps/src/tests/redirection.rs new file mode 100644 index 000000000..53aa393e2 --- /dev/null +++ b/dapps/src/tests/redirection.rs @@ -0,0 +1,185 @@ +// 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 tests::helpers::{serve, request}; + +#[test] +fn should_redirect_to_home() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + GET / HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 302 Found".to_owned()); + assert_eq!(response.headers.get(0).unwrap(), "Location: /home/"); +} + +#[test] +fn should_redirect_to_home_when_trailing_slash_is_missing() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + GET /app HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 302 Found".to_owned()); + assert_eq!(response.headers.get(0).unwrap(), "Location: /home/"); +} + +#[test] +fn should_redirect_to_home_on_invalid_dapp() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + GET /invaliddapp/ HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 302 Found".to_owned()); + assert_eq!(response.headers.get(0).unwrap(), "Location: /home/"); +} + +#[test] +fn should_redirect_to_home_on_invalid_dapp_with_domain() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + GET / HTTP/1.1\r\n\ + Host: invaliddapp.parity\r\n\ + Connection: close\r\n\ + \r\n\ + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 302 Found".to_owned()); + assert_eq!(response.headers.get(0).unwrap(), "Location: http://home.parity/"); +} + +#[test] +fn should_serve_rpc() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + POST / HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + Content-Type: application/json\r\n + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + assert_eq!(response.body, format!("57\n{}\n0\n\n", r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error","data":null},"id":null}"#)); +} + +#[test] +fn should_serve_rpc_at_slash_rpc() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + POST /rpc HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + Content-Type: application/json\r\n + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + assert_eq!(response.body, format!("57\n{}\n0\n\n", r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error","data":null},"id":null}"#)); +} + + +#[test] +fn should_serve_proxy_pac() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + GET /proxy/proxy.pac HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + assert_eq!(response.body, "86\n\nfunction FindProxyForURL(url, host) {\n\tif (shExpMatch(host, \"*.parity\"))\n\t{\n\t\treturn \"PROXY 127.0.0.1:8080\";\n\t}\n\n\treturn \"DIRECT\";\n}\n\n0\n\n".to_owned()); +} + +#[test] +fn should_serve_utils() { + // given + let server = serve(); + + // when + let response = request(server, + "\ + GET /parity-utils/inject.js HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + assert_eq!(response.body.contains("function(){"), true); +} + diff --git a/dapps/src/tests/validation.rs b/dapps/src/tests/validation.rs new file mode 100644 index 000000000..b233a07d8 --- /dev/null +++ b/dapps/src/tests/validation.rs @@ -0,0 +1,79 @@ +// 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 tests::helpers::{serve_hosts, request}; + +#[test] +fn should_reject_invalid_host() { + // given + let server = serve_hosts(Some(vec!["localhost:8080".into()])); + + // when + let response = request(server, + "\ + GET / HTTP/1.1\r\n\ + Host: 127.0.0.1:8080\r\n\ + Connection: close\r\n\ + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 403 Forbidden".to_owned()); + assert_eq!(response.body, "85\n\n\t\t

Request with disallowed Host header has been blocked.

\n\t\t

Check the URL in your browser address bar.

\n\t\t\n0\n\n".to_owned()); +} + +#[test] +fn should_allow_valid_host() { + // given + let server = serve_hosts(Some(vec!["localhost:8080".into()])); + + // when + let response = request(server, + "\ + GET /home/ HTTP/1.1\r\n\ + Host: localhost:8080\r\n\ + Connection: close\r\n\ + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); +} + +#[test] +fn should_serve_dapps_domains() { + // given + let server = serve_hosts(Some(vec!["localhost:8080".into()])); + + // when + let response = request(server, + "\ + GET / HTTP/1.1\r\n\ + Host: home.parity\r\n\ + Connection: close\r\n\ + \r\n\ + {} + " + ); + + // then + assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); +} + From dcea5c252667c9b474b4d24270d417f9fefc7754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 30 Aug 2016 16:56:46 +0200 Subject: [PATCH 4/8] Adding proof --- dapps/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index 2beef0639..bc54b0f37 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -208,9 +208,10 @@ impl Server { *self.panic_handler.lock().unwrap() = Some(Box::new(handler)); } + #[cfg(test)] /// Returns address that this server is bound to. pub fn addr(&self) -> &SocketAddr { - self.server.as_ref().unwrap().addr() + self.server.as_ref().expect("server is always Some at the start; it's consumed only when object is dropped; qed").addr() } } From c61da07516bfddad7850ec7767a8e5ea362852c2 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 31 Aug 2016 14:28:56 +0200 Subject: [PATCH 5/8] always process trie death row on commit, add more tracing --- ethcore/src/block.rs | 2 +- util/src/trie/triedbmut.rs | 32 ++++++++++++++++++++------------ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 784e71dc0..d3b4ac168 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -498,7 +498,7 @@ pub fn enact( { if ::log::max_log_level() >= ::log::LogLevel::Trace { let s = try!(State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(), factories.clone())); - trace!("enact(): root={}, author={}, author_balance={}\n", s.root(), header.author(), s.balance(&header.author())); + trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n", header.number(), s.root(), header.author(), s.balance(&header.author())); } } diff --git a/util/src/trie/triedbmut.rs b/util/src/trie/triedbmut.rs index ca5fb015f..8d3d7d3d3 100644 --- a/util/src/trie/triedbmut.rs +++ b/util/src/trie/triedbmut.rs @@ -56,11 +56,11 @@ impl From for NodeHandle { } } -fn empty_children() -> [Option; 16] { - [ +fn empty_children() -> Box<[Option; 16]> { + Box::new([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, - ] + ]) } /// Node types in the Trie. @@ -78,7 +78,7 @@ enum Node { /// The child node is always a branch. Extension(Bytes, NodeHandle), /// A branch has up to 16 children and an optional value. - Branch([Option; 16], Option) + Branch(Box<[Option; 16]>, Option) } impl Node { @@ -820,19 +820,19 @@ impl<'a> TrieDBMut<'a> { /// Commit the in-memory changes to disk, freeing their storage and /// updating the state root. pub fn commit(&mut self) { - let handle = match self.root_handle() { - NodeHandle::Hash(_) => return, // no changes necessary. - NodeHandle::InMemory(h) => h, - }; - trace!(target: "trie", "Committing trie changes to db."); - // kill all the nodes on death row. + // always kill all the nodes on death row. trace!(target: "trie", "{:?} nodes to remove from db", self.death_row.len()); for hash in self.death_row.drain() { self.db.remove(&hash); } + let handle = match self.root_handle() { + NodeHandle::Hash(_) => return, // no changes necessary. + NodeHandle::InMemory(h) => h, + }; + match self.storage.destroy(handle) { Stored::New(node) => { let root_rlp = node.into_rlp(|child, stream| self.commit_node(child, stream)); @@ -906,21 +906,29 @@ impl<'a> TrieMut for TrieDBMut<'a> { return self.remove(key); } + trace!(target: "trie", "insert: key={:?}, value={:?}", key.pretty(), value.pretty()); + let root_handle = self.root_handle(); - let (new_handle, _) = try!(self.insert_at(root_handle, NibbleSlice::new(key), value.to_owned())); + let (new_handle, changed) = try!(self.insert_at(root_handle, NibbleSlice::new(key), value.to_owned())); + + trace!(target: "trie", "insert: altered trie={}", changed); self.root_handle = NodeHandle::InMemory(new_handle); Ok(()) } fn remove(&mut self, key: &[u8]) -> super::Result<()> { + trace!(target: "trie", "remove: key={:?}", key.pretty()); + let root_handle = self.root_handle(); let key = NibbleSlice::new(key); match try!(self.remove_at(root_handle, key)) { - Some((handle, _)) => { + Some((handle, changed)) => { + trace!(target: "trie", "remove: altered trie={}", changed); self.root_handle = NodeHandle::InMemory(handle); } None => { + trace!(target: "trie", "remove: obliterated trie"); self.root_handle = NodeHandle::Hash(SHA3_NULL_RLP); *self.root = SHA3_NULL_RLP; } From 996b4b9dc0fca1af6ce576f0bd1957ac29244f65 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 31 Aug 2016 16:55:43 +0200 Subject: [PATCH 6/8] fixed transaction addresses mapping, fixes #1971 --- ethcore/src/blockchain/block_info.rs | 4 +- ethcore/src/blockchain/blockchain.rs | 163 ++++++++++++++++-- ethcore/src/blockchain/extras.rs | 2 +- ethcore/src/blockchain/generator/block.rs | 11 +- ethcore/src/blockchain/generator/generator.rs | 13 +- ethcore/src/blockchain/generator/mod.rs | 1 + .../src/blockchain/generator/transaction.rs | 35 ++++ 7 files changed, 207 insertions(+), 22 deletions(-) create mode 100644 ethcore/src/blockchain/generator/transaction.rs diff --git a/ethcore/src/blockchain/block_info.rs b/ethcore/src/blockchain/block_info.rs index 31f93232b..fee0e825b 100644 --- a/ethcore/src/blockchain/block_info.rs +++ b/ethcore/src/blockchain/block_info.rs @@ -31,7 +31,7 @@ pub struct BlockInfo { } /// Describes location of newly inserted block. -#[derive(Clone)] +#[derive(Debug, Clone)] pub enum BlockLocation { /// It's part of the canon chain. CanonChain, @@ -43,7 +43,7 @@ pub enum BlockLocation { BranchBecomingCanonChain(BranchBecomingCanonChainData), } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct BranchBecomingCanonChainData { /// Hash of the newest common ancestor with old canon chain. pub ancestor: H256, diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index a581e59e9..1ca441e69 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -830,7 +830,7 @@ impl BlockChain { } } - /// Applt pending insertion updates + /// Apply pending insertion updates pub fn commit(&self) { let mut pending_best_block = self.pending_best_block.write(); let mut pending_write_hashes = self.pending_block_hashes.write(); @@ -961,15 +961,45 @@ impl BlockChain { let block = BlockView::new(block_bytes); let transaction_hashes = block.transaction_hashes(); - transaction_hashes.into_iter() - .enumerate() - .fold(HashMap::new(), |mut acc, (i ,tx_hash)| { - acc.insert(tx_hash, TransactionAddress { - block_hash: info.hash.clone(), - index: i - }); - acc - }) + match info.location { + BlockLocation::CanonChain => { + transaction_hashes.into_iter() + .enumerate() + .map(|(i ,tx_hash)| { + (tx_hash, TransactionAddress { + block_hash: info.hash.clone(), + index: i + }) + }) + .collect() + }, + BlockLocation::BranchBecomingCanonChain(ref data) => { + let addresses = data.enacted.iter() + .map(|hash| (hash, self.block_body(hash).unwrap())) + .flat_map(|(hash, bytes)| { + let hashes = BodyView::new(&bytes).transaction_hashes(); + hashes.into_iter() + .enumerate() + .map(|(i, tx_hash)| (tx_hash, TransactionAddress { + block_hash: hash.clone(), + index: i, + })) + .collect::>() + }); + + let current_addresses = transaction_hashes.into_iter() + .enumerate() + .map(|(i ,tx_hash)| { + (tx_hash, TransactionAddress { + block_hash: info.hash.clone(), + index: i + }) + }); + + addresses.chain(current_addresses).collect() + }, + BlockLocation::Branch => HashMap::new(), + } } /// This functions returns modified blocks blooms. @@ -1116,7 +1146,6 @@ impl BlockChain { #[cfg(test)] mod tests { #![cfg_attr(feature="dev", allow(similar_names))] - use std::str::FromStr; use std::sync::Arc; use rustc_serialize::hex::FromHex; use util::{Database, DatabaseConfig}; @@ -1127,7 +1156,9 @@ mod tests { use tests::helpers::*; use devtools::*; use blockchain::generator::{ChainGenerator, ChainIterator, BlockFinalizer}; + use blockchain::extras::TransactionAddress; use views::BlockView; + use transaction::{Transaction, Action}; fn new_db(path: &str) -> Arc { Arc::new(Database::open(&DatabaseConfig::with_columns(::db::NUM_COLUMNS), path).unwrap()) @@ -1262,6 +1293,106 @@ mod tests { // TODO: insert block that already includes one of them as an uncle to check it's not allowed. } + #[test] + fn test_overwriting_transaction_addresses() { + let mut canon_chain = ChainGenerator::default(); + let mut finalizer = BlockFinalizer::default(); + let genesis = canon_chain.generate(&mut finalizer).unwrap(); + let mut fork_chain = canon_chain.fork(1); + let mut fork_finalizer = finalizer.fork(); + + let t1 = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Create, + value: 100.into(), + data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(), + }.sign(&"".sha3()); + + let t2 = Transaction { + nonce: 1.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Create, + value: 100.into(), + data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(), + }.sign(&"".sha3()); + + let t3 = Transaction { + nonce: 2.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Create, + value: 100.into(), + data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(), + }.sign(&"".sha3()); + + let b1a = canon_chain + .with_transaction(t1.clone()) + .with_transaction(t2.clone()) + .generate(&mut finalizer).unwrap(); + + // insert transactions in different order + let b1b = fork_chain + .with_transaction(t2.clone()) + .with_transaction(t1.clone()) + .generate(&mut fork_finalizer).unwrap(); + + let b2 = fork_chain + .with_transaction(t3.clone()) + .generate(&mut fork_finalizer).unwrap(); + + let b1a_hash = BlockView::new(&b1a).header_view().sha3(); + let b1b_hash = BlockView::new(&b1b).header_view().sha3(); + let b2_hash = BlockView::new(&b2).header_view().sha3(); + + let t1_hash = t1.hash(); + let t2_hash = t2.hash(); + let t3_hash = t3.hash(); + + let temp = RandomTempPath::new(); + let db = new_db(temp.as_str()); + let bc = BlockChain::new(Config::default(), &genesis, db.clone()); + + let mut batch = db.transaction(); + let _ = bc.insert_block(&mut batch, &b1a, vec![]); + bc.commit(); + let _ = bc.insert_block(&mut batch, &b1b, vec![]); + bc.commit(); + db.write(batch).unwrap(); + + assert_eq!(bc.best_block_hash(), b1a_hash); + assert_eq!(bc.transaction_address(&t1_hash).unwrap(), TransactionAddress { + block_hash: b1a_hash.clone(), + index: 0, + }); + assert_eq!(bc.transaction_address(&t2_hash).unwrap(), TransactionAddress { + block_hash: b1a_hash.clone(), + index: 1, + }); + + // now let's make forked chain the canon chain + let mut batch = db.transaction(); + let _ = bc.insert_block(&mut batch, &b2, vec![]); + bc.commit(); + db.write(batch).unwrap(); + + assert_eq!(bc.best_block_hash(), b2_hash); + assert_eq!(bc.transaction_address(&t1_hash).unwrap(), TransactionAddress { + block_hash: b1b_hash.clone(), + index: 1, + }); + assert_eq!(bc.transaction_address(&t2_hash).unwrap(), TransactionAddress { + block_hash: b1b_hash.clone(), + index: 0, + }); + assert_eq!(bc.transaction_address(&t3_hash).unwrap(), TransactionAddress { + block_hash: b2_hash.clone(), + index: 0, + }); + } + #[test] #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] fn test_small_fork() { @@ -1286,7 +1417,7 @@ mod tests { let db = new_db(temp.as_str()); let bc = BlockChain::new(Config::default(), &genesis, db.clone()); - let mut batch =db.transaction(); + let mut batch = db.transaction(); let ir1 = bc.insert_block(&mut batch, &b1, vec![]); bc.commit(); let ir2 = bc.insert_block(&mut batch, &b2, vec![]); @@ -1462,7 +1593,7 @@ mod tests { fn find_transaction_by_hash() { let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0".from_hex().unwrap(); let b1 = "f904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a070616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2a05c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023ec683021536845685109780a029f07836e4e59229b3a065913afc27702642c683bba689910b2b2fd45db310d3888957e6d004a31802f902a7f85f800a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecda06baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188f85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba034bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59a078807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616c0".from_hex().unwrap(); - let b1_hash = H256::from_str("f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3").unwrap(); + let b1_hash: H256 = "f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3".into(); let temp = RandomTempPath::new(); let db = new_db(temp.as_str()); @@ -1490,11 +1621,11 @@ mod tests { #[test] fn test_bloom_filter_simple() { // TODO: From here - let bloom_b1 = H2048::from_str("00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000").unwrap(); + let bloom_b1: H2048 = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into(); - let bloom_b2 = H2048::from_str("00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let bloom_b2: H2048 = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); - let bloom_ba = H2048::from_str("00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let bloom_ba: H2048 = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); let mut canon_chain = ChainGenerator::default(); let mut finalizer = BlockFinalizer::default(); diff --git a/ethcore/src/blockchain/extras.rs b/ethcore/src/blockchain/extras.rs index 6bb10276c..e2b4e89b3 100644 --- a/ethcore/src/blockchain/extras.rs +++ b/ethcore/src/blockchain/extras.rs @@ -176,7 +176,7 @@ impl Encodable for BlockDetails { } /// Represents address of certain transaction within block -#[derive(Clone)] +#[derive(Debug, PartialEq, Clone)] pub struct TransactionAddress { /// Block hash pub block_hash: H256, diff --git a/ethcore/src/blockchain/generator/block.rs b/ethcore/src/blockchain/generator/block.rs index 238051d2a..1fb9c13a1 100644 --- a/ethcore/src/blockchain/generator/block.rs +++ b/ethcore/src/blockchain/generator/block.rs @@ -16,7 +16,6 @@ use util::rlp::*; use util::{H256, H2048}; -use util::U256; use util::bytes::Bytes; use header::Header; use transaction::SignedTransaction; @@ -24,6 +23,7 @@ use transaction::SignedTransaction; use super::fork::Forkable; use super::bloom::WithBloom; use super::complete::CompleteBlock; +use super::transaction::WithTransaction; /// Helper structure, used for encoding blocks. #[derive(Default)] @@ -44,7 +44,7 @@ impl Encodable for Block { impl Forkable for Block { fn fork(mut self, fork_number: usize) -> Self where Self: Sized { - let difficulty = self.header.difficulty().clone() - U256::from(fork_number); + let difficulty = self.header.difficulty().clone() - fork_number.into(); self.header.set_difficulty(difficulty); self } @@ -57,6 +57,13 @@ impl WithBloom for Block { } } +impl WithTransaction for Block { + fn with_transaction(mut self, transaction: SignedTransaction) -> Self where Self: Sized { + self.transactions.push(transaction); + self + } +} + impl CompleteBlock for Block { fn complete(mut self, parent_hash: H256) -> Bytes { self.header.set_parent_hash(parent_hash); diff --git a/ethcore/src/blockchain/generator/generator.rs b/ethcore/src/blockchain/generator/generator.rs index 179839b5a..ebe9e22c0 100644 --- a/ethcore/src/blockchain/generator/generator.rs +++ b/ethcore/src/blockchain/generator/generator.rs @@ -16,10 +16,12 @@ use util::{U256, H2048, Bytes}; use header::BlockNumber; +use transaction::SignedTransaction; use super::fork::Fork; use super::bloom::Bloom; use super::complete::{BlockFinalizer, CompleteBlock, Complete}; use super::block::Block; +use super::transaction::Transaction; /// Chain iterator interface. pub trait ChainIterator: Iterator + Sized { @@ -28,6 +30,8 @@ pub trait ChainIterator: Iterator + Sized { fn fork(&self, fork_number: usize) -> Fork where Self: Clone; /// Should be called to make every consecutive block have given bloom. fn with_bloom(&mut self, bloom: H2048) -> Bloom; + /// Should be called to make every consecutive block have given transaction. + fn with_transaction(&mut self, transaction: SignedTransaction) -> Transaction; /// Should be called to complete block. Without complete, block may have incorrect hash. fn complete<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Complete<'a, Self>; /// Completes and generates block. @@ -49,6 +53,13 @@ impl ChainIterator for I where I: Iterator + Sized { } } + fn with_transaction(&mut self, transaction: SignedTransaction) -> Transaction { + Transaction { + iter: self, + transaction: transaction, + } + } + fn complete<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Complete<'a, Self> { Complete { iter: self, @@ -83,7 +94,7 @@ impl Default for ChainGenerator { fn default() -> Self { ChainGenerator { number: 0, - difficulty: U256::from(1000), + difficulty: 1000.into(), } } } diff --git a/ethcore/src/blockchain/generator/mod.rs b/ethcore/src/blockchain/generator/mod.rs index b02030d4e..683ab7dfb 100644 --- a/ethcore/src/blockchain/generator/mod.rs +++ b/ethcore/src/blockchain/generator/mod.rs @@ -21,6 +21,7 @@ mod block; mod complete; mod fork; pub mod generator; +mod transaction; pub use self::complete::BlockFinalizer; pub use self::generator::{ChainIterator, ChainGenerator}; diff --git a/ethcore/src/blockchain/generator/transaction.rs b/ethcore/src/blockchain/generator/transaction.rs new file mode 100644 index 000000000..aa1d3bdd3 --- /dev/null +++ b/ethcore/src/blockchain/generator/transaction.rs @@ -0,0 +1,35 @@ +// 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 transaction::SignedTransaction; + +pub trait WithTransaction { + fn with_transaction(self, transaction: SignedTransaction) -> Self where Self: Sized; +} + +pub struct Transaction<'a, I> where I: 'a { + pub iter: &'a mut I, + pub transaction: SignedTransaction, +} + +impl <'a, I> Iterator for Transaction<'a, I> where I: Iterator, ::Item: WithTransaction { + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|item| item.with_transaction(self.transaction.clone())) + } +} From f5f4736e7c44aa661601119a6481002f389fa5e9 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 31 Aug 2016 17:36:49 +0200 Subject: [PATCH 7/8] simplified iterator --- ethcore/src/blockchain/blockchain.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 1ca441e69..943dc04c5 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -975,8 +975,8 @@ impl BlockChain { }, BlockLocation::BranchBecomingCanonChain(ref data) => { let addresses = data.enacted.iter() - .map(|hash| (hash, self.block_body(hash).unwrap())) - .flat_map(|(hash, bytes)| { + .flat_map(|hash| { + let bytes = self.block_body(hash).expect("Enacted block must be in database."); let hashes = BodyView::new(&bytes).transaction_hashes(); hashes.into_iter() .enumerate() From b4f3c4bd7aa93756bccc152bb7263b2f157ad2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 1 Sep 2016 12:00:00 +0200 Subject: [PATCH 8/8] Asynchronous RPC support (#2017) * Async RPC * Limiting number of transactions in queue * Fixing tests * Bumping serde and jsonrpc-core * serde updated to 0.8 * fixed failing tests * Bumping ipc server * Fixing API for endpoints * Experimenting with tests without --release mode --- .travis.yml | 5 +- Cargo.lock | 271 +++++++++++++++------ dapps/Cargo.toml | 12 +- dapps/src/apps/fetcher.rs | 6 +- dapps/src/endpoint.rs | 6 +- dapps/src/router/mod.rs | 12 +- dapps/src/rpc.rs | 13 +- ethstore/Cargo.toml | 8 +- ethstore/src/json/crypto.rs | 73 ++---- json/Cargo.toml | 8 +- json/src/blockchain/blockchain.rs | 2 +- json/src/bytes.rs | 2 +- json/src/vm/call.rs | 3 +- rpc/Cargo.toml | 10 +- rpc/src/v1/helpers/dispatch.rs | 4 +- rpc/src/v1/helpers/errors.rs | 10 +- rpc/src/v1/helpers/signing_queue.rs | 126 +++++----- rpc/src/v1/impls/eth.rs | 76 +++--- rpc/src/v1/impls/eth_filter.rs | 16 +- rpc/src/v1/impls/eth_signing.rs | 100 +++++--- rpc/src/v1/impls/ethcore.rs | 40 +-- rpc/src/v1/impls/ethcore_set.rs | 22 +- rpc/src/v1/impls/personal.rs | 24 +- rpc/src/v1/impls/personal_signer.rs | 4 +- rpc/src/v1/impls/traces.rs | 14 +- rpc/src/v1/impls/web3.rs | 2 +- rpc/src/v1/tests/eth.rs | 20 +- rpc/src/v1/tests/mocked/eth.rs | 94 +++---- rpc/src/v1/tests/mocked/eth_signing.rs | 36 ++- rpc/src/v1/tests/mocked/ethcore.rs | 28 +-- rpc/src/v1/tests/mocked/ethcore_set.rs | 10 +- rpc/src/v1/tests/mocked/net.rs | 6 +- rpc/src/v1/tests/mocked/personal.rs | 24 +- rpc/src/v1/tests/mocked/personal_signer.rs | 22 +- rpc/src/v1/tests/mocked/rpc.rs | 4 +- rpc/src/v1/tests/mocked/web3.rs | 6 +- rpc/src/v1/traits/eth.rs | 8 +- rpc/src/v1/types/trace.rs | 8 +- signer/Cargo.toml | 2 +- signer/src/ws_server/session.rs | 20 +- stratum/Cargo.toml | 2 +- stratum/src/lib.rs | 6 +- test.sh | 7 +- 43 files changed, 657 insertions(+), 515 deletions(-) diff --git a/.travis.yml b/.travis.yml index 03b4edf9d..6428ccecf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ git: matrix: include: - rust: stable - env: RUN_TESTS="true" + env: RUN_TESTS="true" TEST_OPTIONS="--no-release" - rust: beta env: RUN_COVERAGE="true" - rust: stable @@ -30,6 +30,7 @@ env: - RUN_TESTS="false" - RUN_COVERAGE="false" - RUN_DOCS="false" + - TEST_OPTIONS="" # GH_TOKEN for documentation - secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw= - KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov" @@ -64,7 +65,7 @@ install: ) script: - - if [ "$RUN_TESTS" = "true" ]; then ./test.sh --verbose; fi + - if [ "$RUN_TESTS" = "true" ]; then ./test.sh $TEST_OPTIONS --verbose; fi - if [ "$RUN_COVERAGE" = "true" ]; then ./scripts/cov.sh "$KCOV_CMD"; fi after_success: | diff --git a/Cargo.lock b/Cargo.lock index 79bb6dba9..980b2dbf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,14 @@ dependencies = [ "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aster" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bigint" version = "0.1.0" @@ -173,7 +181,7 @@ version = "1.1.1" source = "git+https://github.com/ethcore/rust-ctrlc.git#f4927770f89eca80ec250911eea3adcbf579ac48" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -182,7 +190,7 @@ name = "daemonize" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -203,6 +211,11 @@ dependencies = [ "strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dtoa" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" version = "0.4.0" @@ -224,21 +237,21 @@ source = "git+https://github.com/ethcore/rust-secp256k1#a9a0b1be1f39560ca86e8fc8 dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethabi" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -289,11 +302,11 @@ name = "ethcore-dapps" version = "1.4.0" dependencies = [ "clippy 0.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-rpc 1.4.0", "ethcore-util 1.4.0", "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -304,9 +317,9 @@ dependencies = [ "parity-dapps-wallet 1.4.0 (git+https://github.com/ethcore/parity-ui.git)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zip 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -410,7 +423,7 @@ dependencies = [ "ethcrypto 0.1.0", "ethkey 0.2.0", "igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", "parking_lot 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -438,13 +451,13 @@ dependencies = [ "ethstore 0.1.0", "ethsync 1.4.0", "json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)", - "jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -458,7 +471,7 @@ dependencies = [ "ethcore-io 1.4.0", "ethcore-rpc 1.4.0", "ethcore-util 1.4.0", - "jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-signer 1.4.0 (git+https://github.com/ethcore/parity-ui.git)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -477,7 +490,7 @@ dependencies = [ "ethcore-ipc-nano 1.4.0", "ethcore-util 1.4.0", "json-tcp-server 0.1.0 (git+https://github.com/ethcore/json-tcp-server)", - "jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", @@ -499,7 +512,7 @@ dependencies = [ "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -533,9 +546,9 @@ version = "0.1.0" dependencies = [ "ethcore-util 1.4.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -558,13 +571,13 @@ dependencies = [ "ethkey 0.2.0", "itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -594,7 +607,7 @@ dependencies = [ name = "fdlimit" version = "0.1.0" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -602,7 +615,7 @@ name = "flate2" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -711,7 +724,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -720,14 +733,19 @@ name = "itertools" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "itoa" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "json-ipc-server" version = "0.2.4" -source = "git+https://github.com/ethcore/json-ipc-server.git#56b6307130710ebc73cb9be087b6ed0b6c400bcf" +source = "git+https://github.com/ethcore/json-ipc-server.git#5fbd0253750d3097b9a8fb27effa84c18d630bbb" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -738,11 +756,11 @@ dependencies = [ [[package]] name = "json-tcp-server" version = "0.1.0" -source = "git+https://github.com/ethcore/json-tcp-server#05c186ea100e2107c1f9f83ca4c62cb6ed2c68bd" +source = "git+https://github.com/ethcore/json-tcp-server#c2858522274ae56042472bb5d22845a1b85e5338" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -751,22 +769,24 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "2.1.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-http-server" version = "6.1.0" -source = "git+https://github.com/ethcore/jsonrpc-http-server.git#4e3f93eb79125e91a46e04d77c25ff8885498b86" +source = "git+https://github.com/ethcore/jsonrpc-http-server.git#339f7209b01d26aea01722b3a69127235287d6a9" dependencies = [ "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -791,7 +811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -814,7 +834,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -842,7 +862,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -851,7 +871,7 @@ version = "0.5.1" source = "git+https://github.com/ethcore/mio?branch=v0.5.x#3842d3b250ffd7bd9b16f9586b875ddcbac2b0dd" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -867,7 +887,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -883,7 +903,7 @@ version = "0.6.0-dev" source = "git+https://github.com/carllerche/mio?rev=62ec763c9cc34d8a452ed0392c575c50ddd5fc8d#62ec763c9cc34d8a452ed0392c575c50ddd5fc8d" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -918,7 +938,7 @@ name = "nanomsg" version = "0.5.1" source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)", ] @@ -928,7 +948,7 @@ version = "0.5.0" source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -938,7 +958,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -949,7 +969,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -959,7 +979,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1049,7 +1069,7 @@ name = "num_cpus" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1117,7 +1137,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1210,6 +1230,15 @@ dependencies = [ "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quasi" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quasi_codegen" version = "0.11.0" @@ -1220,6 +1249,17 @@ dependencies = [ "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quasi_codegen" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.1.0" @@ -1235,7 +1275,7 @@ name = "rand" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1270,7 +1310,7 @@ name = "rocksdb" version = "0.4.5" source = "git+https://github.com/ethcore/rust-rocksdb#485dd747a2c9a9f910fc8ac696fc9edf5fa22aa3" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)", ] @@ -1280,7 +1320,7 @@ version = "0.3.0" source = "git+https://github.com/ethcore/rust-rocksdb#485dd747a2c9a9f910fc8ac696fc9edf5fa22aa3" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1300,7 +1340,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1311,7 +1351,7 @@ version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1345,28 +1385,40 @@ dependencies = [ [[package]] name = "serde" -version = "0.7.9" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_codegen" -version = "0.7.9" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_codegen 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_codegen_internals" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1433,19 +1485,64 @@ dependencies = [ "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syntex" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_errors" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_pos" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syntex_syntax" version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syntex_syntax" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "table" version = "0.1.0" @@ -1464,12 +1561,21 @@ dependencies = [ "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "term" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termios" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1478,7 +1584,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1495,7 +1601,7 @@ version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1663,6 +1769,7 @@ dependencies = [ "checksum ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1f46cd5b1d660c938e3f92dfe7a73d832b3281479363dd0cd9c1c2fbf60f7962" "checksum arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "16e3bdb2f54b3ace0285975d59a97cf8ed3855294b2b6bc651fcf22a9c352975" "checksum aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07d344974f0a155f091948aa389fb1b912d3a58414fbdb9c8d446d193ee3496a" +"checksum aster 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4df293303e8a52e1df7984ac1415e195f5fcbf51e4bb7bda54557861a3954a08" "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" @@ -1680,10 +1787,11 @@ dependencies = [ "checksum daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "271ec51b7e0bee92f0d04601422c73eb76ececf197026711c97ad25038a010cf" "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf" "checksum docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc0acb4ce0828c6a5a11d47baa432fe885881c27428c3a4e473e454ffe57a76" +"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d" "checksum elastic-array 0.4.0 (git+https://github.com/ethcore/elastic-array)" = "" "checksum env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aba65b63ffcc17ffacd6cf5aa843da7c5a25e3bd4bbe0b7def8b214e411250e5" "checksum eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)" = "" -"checksum ethabi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bc7789d1518abba0c61606826a5229284d47a9d0934feb62a1ee218882780a9b" +"checksum ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0c53453517f620847be51943db329276ae52f2e210cfc659e81182864be2f" "checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb" "checksum gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)" = "3da3a2cbaeb01363c8e3704fd9fd0eb2ceb17c6f27abd4c1ef040fb57d20dc79" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" @@ -1697,14 +1805,15 @@ dependencies = [ "checksum igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8c12b1795b8b168f577c45fa10379b3814dcb11b7ab702406001f0d63f40484" "checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c" "checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76" +"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" "checksum json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)" = "" "checksum json-tcp-server 0.1.0 (git+https://github.com/ethcore/json-tcp-server)" = "" -"checksum jsonrpc-core 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec4477e4e8218da23caa5dd31f4eb39999aa0ea9035660617eccfb19a23bf5ad" +"checksum jsonrpc-core 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e913b3c809aab9378889da8b990b4a46b98bd4794c8117946a1cf63c5f87bcde" "checksum jsonrpc-http-server 6.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)" = "" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" -"checksum libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "97def9dc7ce1d8e153e693e3a33020bc69972181adb2f871e87e888876feae49" +"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2" "checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e" @@ -1751,7 +1860,9 @@ dependencies = [ "checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5" "checksum primal-sieve 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7aa73fd87e5984a00bdb4c1b14d3d5d6d0bad01b2caaaf924c16ab7260ac946c" "checksum quasi 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b26543b563704e7d87f3ec7cfafb713010a905c5f1b155a8ab66863af43ca578" +"checksum quasi 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb7eaef226a434a570fa336bc99502c4f5878208c1ebdd83b2d0bc37b1b1c34c" "checksum quasi_codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0881d9a45d5f9ebe4a7e77742f8c604f3658c212baf8dd711a692dd000bc648c" +"checksum quasi_codegen 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62e90381b315dfd00bfe6efbfeeec9f03a6d66159c3a5c8411b6c550d24b08fd" "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c" "checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a" "checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5" @@ -1767,9 +1878,10 @@ dependencies = [ "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f" -"checksum serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b76133a8a02f1c6ebd3fb9a2ecaab3d54302565a51320e80931adba571aadb1b" -"checksum serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c5b74ff4fb34013cc0b917dd182fefc05ee9af233b9d0d557078334554284d0e" -"checksum serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c88a751caa8f0000058fb971cd443ed2e6b653f33f5a47f29892a8bd44ca4c1" +"checksum serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b1dfda9ebb31d29fa8b94d7eb3031a86a8dcec065f0fe268a30f98867bf45775" +"checksum serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e422ae53d7933f59c6ff57e7b5870b5c9094b1f473f78ec33d89f8a692c3ec02" +"checksum serde_codegen_internals 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f877e2781ed0a323295d1c9f0e26556117b5a11489fc47b1848dfb98b3173d21" +"checksum serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e10f8a9d94b06cf5d3bef66475f04c8ff90950f1be7004c357ff9472ccbaebc" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" "checksum slab 0.2.0 (git+https://github.com/carllerche/slab?rev=5476efcafb)" = "" @@ -1780,9 +1892,14 @@ dependencies = [ "checksum stable-heap 0.1.0 (git+https://github.com/carllerche/stable-heap?rev=3c5cd1ca47)" = "" "checksum strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4d73a2c36a4d095ed1a6df5cbeac159863173447f7a82b3f4757426844ab825" "checksum syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393b6dd0889df2b064beeea954cfda6bc2571604ac460deeae0fed55a53988af" +"checksum syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a30b08a6b383a22e5f6edc127d169670d48f905bb00ca79a00ea3e442ebe317" +"checksum syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04c48f32867b6114449155b2a82114b86d4b09e1bddb21c47ff104ab9172b646" +"checksum syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd49988e52451813c61fecbe9abb5cfd4e1b7bb6cdbb980a6fbcbab859171a6" "checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e" +"checksum syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7628a0506e8f9666fdabb5f265d0059b059edac9a3f810bda077abb5d826bd8d" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" +"checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a" "checksum termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0694f51610ef7cfac7a1b81de7f1602ee5356e76541bcd62c40e71933338cab1" diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index 1f5a0c491..6344d67d6 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -11,17 +11,17 @@ build = "build.rs" [dependencies] rand = "0.3.14" log = "0.3" -jsonrpc-core = "2.1" +jsonrpc-core = "3.0" jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" } hyper = { default-features = false, git = "https://github.com/ethcore/hyper" } unicase = "1.3" url = "1.0" rustc-serialize = "0.3" -serde = "0.7.0" -serde_json = "0.7.0" -serde_macros = { version = "0.7.0", optional = true } +serde = "0.8" +serde_json = "0.8" +serde_macros = { version = "0.8", optional = true } zip = { version = "0.1", default-features = false } -ethabi = "0.2.1" +ethabi = "0.2.2" linked-hash-map = "0.3" ethcore-rpc = { path = "../rpc" } ethcore-util = { path = "../util" } @@ -34,7 +34,7 @@ mime_guess = { version = "1.6.1" } clippy = { version = "0.0.85", optional = true} [build-dependencies] -serde_codegen = { version = "0.7.0", optional = true } +serde_codegen = { version = "0.8", optional = true } [features] default = ["serde_codegen", "extra-dapps"] diff --git a/dapps/src/apps/fetcher.rs b/dapps/src/apps/fetcher.rs index e31aae55d..939022e7f 100644 --- a/dapps/src/apps/fetcher.rs +++ b/dapps/src/apps/fetcher.rs @@ -26,7 +26,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool}; use rustc_serialize::hex::FromHex; -use hyper::Control; +use hyper; use hyper::status::StatusCode; use random_filename; @@ -85,7 +85,7 @@ impl AppFetcher { } } - pub fn to_handler(&self, path: EndpointPath, control: Control) -> Box { + pub fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box { let mut dapps = self.dapps.lock(); let app_id = path.app_id.clone(); @@ -94,7 +94,7 @@ impl AppFetcher { match status { // Just server dapp Some(&mut ContentStatus::Ready(ref endpoint)) => { - (None, endpoint.to_handler(path)) + (None, endpoint.to_async_handler(path, control)) }, // App is already being fetched Some(&mut ContentStatus::Fetching(_)) => { diff --git a/dapps/src/endpoint.rs b/dapps/src/endpoint.rs index dbb02a3d3..51e863f19 100644 --- a/dapps/src/endpoint.rs +++ b/dapps/src/endpoint.rs @@ -16,7 +16,7 @@ //! URL Endpoint traits -use hyper::{server, net}; +use hyper::{self, server, net}; use std::collections::BTreeMap; #[derive(Debug, PartialEq, Default, Clone)] @@ -43,4 +43,8 @@ pub trait Endpoint : Send + Sync { fn info(&self) -> Option<&EndpointInfo> { None } fn to_handler(&self, path: EndpointPath) -> Box; + + fn to_async_handler(&self, path: EndpointPath, _control: hyper::Control) -> Box { + self.to_handler(path) + } } diff --git a/dapps/src/router/mod.rs b/dapps/src/router/mod.rs index 94d0a0fc0..9eae83b36 100644 --- a/dapps/src/router/mod.rs +++ b/dapps/src/router/mod.rs @@ -73,20 +73,20 @@ impl server::Handler for Router
{ // Choose proper handler depending on path / domain let url = extract_url(&req); let endpoint = extract_endpoint(&url); + let control = self.control.take().expect("on_request is called only once; control is always defined at start; qed"); self.handler = match endpoint { // First check special endpoints (ref path, ref endpoint) if self.special.contains_key(endpoint) => { - self.special.get(endpoint).unwrap().to_handler(path.clone().unwrap_or_default()) + self.special.get(endpoint).unwrap().to_async_handler(path.clone().unwrap_or_default(), control) }, // Then delegate to dapp (Some(ref path), _) if self.endpoints.contains_key(&path.app_id) => { - self.endpoints.get(&path.app_id).unwrap().to_handler(path.clone()) + self.endpoints.get(&path.app_id).unwrap().to_async_handler(path.clone(), control) }, // Try to resolve and fetch the dapp (Some(ref path), _) if self.fetch.contains(&path.app_id) => { - let control = self.control.take().expect("on_request is called only once, thus control is always defined."); - self.fetch.to_handler(path.clone(), control) + self.fetch.to_async_handler(path.clone(), control) }, // Redirection to main page (maybe 404 instead?) (Some(ref path), _) if *req.method() == hyper::method::Method::Get => { @@ -100,7 +100,7 @@ impl server::Handler for Router { }, // RPC by default _ => { - self.special.get(&SpecialEndpoint::Rpc).unwrap().to_handler(EndpointPath::default()) + self.special.get(&SpecialEndpoint::Rpc).unwrap().to_async_handler(EndpointPath::default(), control) } }; @@ -135,7 +135,7 @@ impl Router { allowed_hosts: Option>, ) -> Self { - let handler = special.get(&SpecialEndpoint::Rpc).unwrap().to_handler(EndpointPath::default()); + let handler = special.get(&SpecialEndpoint::Api).unwrap().to_handler(EndpointPath::default()); Router { control: Some(control), main_page: main_page, diff --git a/dapps/src/rpc.rs b/dapps/src/rpc.rs index 04470bcc1..4fbc37772 100644 --- a/dapps/src/rpc.rs +++ b/dapps/src/rpc.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . use std::sync::{Arc, Mutex}; +use hyper; use jsonrpc_core::IoHandler; use jsonrpc_http_server::{ServerHandler, PanicHandler, AccessControlAllowOrigin}; use endpoint::{Endpoint, EndpointPath, Handler}; @@ -38,7 +39,17 @@ struct RpcEndpoint { impl Endpoint for RpcEndpoint { fn to_handler(&self, _path: EndpointPath) -> Box { + panic!("RPC Endpoint is asynchronous and requires Control object."); + } + + fn to_async_handler(&self, _path: EndpointPath, control: hyper::Control) -> Box { let panic_handler = PanicHandler { handler: self.panic_handler.clone() }; - Box::new(ServerHandler::new(self.handler.clone(), self.cors_domain.clone(), self.allowed_hosts.clone(), panic_handler)) + Box::new(ServerHandler::new( + self.handler.clone(), + self.cors_domain.clone(), + self.allowed_hosts.clone(), + panic_handler, + control, + )) } } diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml index 1842456fd..7fa2a6890 100644 --- a/ethstore/Cargo.toml +++ b/ethstore/Cargo.toml @@ -8,9 +8,9 @@ build = "build.rs" libc = "0.2.11" rand = "0.3.14" ethkey = { path = "../ethkey" } -serde = "0.7" -serde_json = "0.7" -serde_macros = { version = "0.7", optional = true } +serde = "0.8" +serde_json = "0.8" +serde_macros = { version = "0.8", optional = true } rustc-serialize = "0.3" rust-crypto = "0.2.36" tiny-keccak = "1.0" @@ -21,7 +21,7 @@ itertools = "0.4" ethcrypto = { path = "../ethcrypto" } [build-dependencies] -serde_codegen = { version = "0.7", optional = true } +serde_codegen = { version = "0.8", optional = true } [features] default = ["serde_codegen"] diff --git a/ethstore/src/json/crypto.rs b/ethstore/src/json/crypto.rs index 9ff8c1e44..e6ecef81f 100644 --- a/ethstore/src/json/crypto.rs +++ b/ethstore/src/json/crypto.rs @@ -16,7 +16,6 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer, Error}; use serde::de::{Visitor, MapVisitor}; -use serde::ser; use super::{Cipher, CipherSer, CipherSerParams, Kdf, KdfSer, KdfSerParams, H256}; #[derive(Debug, PartialEq)] @@ -141,60 +140,26 @@ impl Serialize for Crypto { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - serializer.serialize_struct("Crypto", CryptoMapVisitor { - value: self, - state: 0, - }) - } -} - -struct CryptoMapVisitor<'a> { - value: &'a Crypto, - state: u8, -} - -impl<'a> ser::MapVisitor for CryptoMapVisitor<'a> { - fn visit(&mut self, serializer: &mut S) -> Result, S::Error> - where S: Serializer - { - match self.state { - 0 => { - self.state += 1; - match self.value.cipher { - Cipher::Aes128Ctr(_) => Ok(Some(try!(serializer.serialize_struct_elt("cipher", &CipherSer::Aes128Ctr)))), - } + let mut state = try!(serializer.serialize_struct("Crypto", 6)); + match self.cipher { + Cipher::Aes128Ctr(ref params) => { + try!(serializer.serialize_struct_elt(&mut state, "cipher", &CipherSer::Aes128Ctr)); + try!(serializer.serialize_struct_elt(&mut state, "cipherparams", params)); }, - 1 => { - self.state += 1; - match self.value.cipher { - Cipher::Aes128Ctr(ref params) => Ok(Some(try!(serializer.serialize_struct_elt("cipherparams", params)))), - } - }, - 2 => { - self.state += 1; - Ok(Some(try!(serializer.serialize_struct_elt("ciphertext", &self.value.ciphertext)))) - }, - 3 => { - self.state += 1; - match self.value.kdf { - Kdf::Pbkdf2(_) => Ok(Some(try!(serializer.serialize_struct_elt("kdf", &KdfSer::Pbkdf2)))), - Kdf::Scrypt(_) => Ok(Some(try!(serializer.serialize_struct_elt("kdf", &KdfSer::Scrypt)))), - } - }, - 4 => { - self.state += 1; - match self.value.kdf { - Kdf::Pbkdf2(ref params) => Ok(Some(try!(serializer.serialize_struct_elt("kdfparams", params)))), - Kdf::Scrypt(ref params) => Ok(Some(try!(serializer.serialize_struct_elt("kdfparams", params)))), - } - }, - 5 => { - self.state += 1; - Ok(Some(try!(serializer.serialize_struct_elt("mac", &self.value.mac)))) - }, - _ => { - Ok(None) - } } + try!(serializer.serialize_struct_elt(&mut state, "ciphertext", &self.ciphertext)); + match self.kdf { + Kdf::Pbkdf2(ref params) => { + try!(serializer.serialize_struct_elt(&mut state, "kdf", &KdfSer::Pbkdf2)); + try!(serializer.serialize_struct_elt(&mut state, "kdfparams", params)); + }, + Kdf::Scrypt(ref params) => { + try!(serializer.serialize_struct_elt(&mut state, "kdf", &KdfSer::Scrypt)); + try!(serializer.serialize_struct_elt(&mut state, "kdfparams", params)); + }, + } + + try!(serializer.serialize_struct_elt(&mut state, "mac", &self.mac)); + serializer.serialize_struct_end(state) } } diff --git a/json/Cargo.toml b/json/Cargo.toml index b5eb7afdd..3c66e1317 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -7,13 +7,13 @@ build = "build.rs" [dependencies] ethcore-util = { path = "../util" } rustc-serialize = "0.3" -serde = "0.7.0" -serde_json = "0.7.0" -serde_macros = { version = "0.7.0", optional = true } +serde = "0.8" +serde_json = "0.8" +serde_macros = { version = "0.8", optional = true } clippy = { version = "0.0.85", optional = true} [build-dependencies] -serde_codegen = { version = "0.7.0", optional = true } +serde_codegen = { version = "0.8", optional = true } [features] default = ["serde_codegen"] diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 5d8933a07..3899f23e8 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -178,5 +178,5 @@ mod tests { }"#; let _deserialized: BlockChain = serde_json::from_str(s).unwrap(); // TODO: validate all fields - //} + } } diff --git a/json/src/bytes.rs b/json/src/bytes.rs index 8772cd207..c162d08ce 100644 --- a/json/src/bytes.rs +++ b/json/src/bytes.rs @@ -56,7 +56,7 @@ impl FromStr for Bytes { 2 if value.starts_with("0x") => vec![], _ if value.starts_with("0x") && value.len() % 2 == 1 => { let v = "0".to_owned() + &value[2..]; - FromHex::from_hex(v.as_ref() as &str).unwrap_or(vec![]), + FromHex::from_hex(v.as_str()).unwrap_or(vec![]) }, _ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]), _ => FromHex::from_hex(value).unwrap_or(vec![]), diff --git a/json/src/vm/call.rs b/json/src/vm/call.rs index 855853c40..ad226048e 100644 --- a/json/src/vm/call.rs +++ b/json/src/vm/call.rs @@ -39,9 +39,8 @@ pub struct Call { mod tests { use serde_json; use vm::Call; - use util::U256; + use util::{U256, H160 as Hash160}; use uint::Uint; - use util::hash::Address as Hash160; use hash::Address; use maybe::MaybeEmpty; use std::str::FromStr; diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index ac1fd96c5..11dc0bbe3 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -10,9 +10,9 @@ build = "build.rs" [dependencies] log = "0.3" -serde = "0.7.0" -serde_json = "0.7.0" -jsonrpc-core = "2.1" +serde = "0.8" +serde_json = "0.8" +jsonrpc-core = "3.0" jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" } ethcore-io = { path = "../util/io" } ethcore-util = { path = "../util" } @@ -25,14 +25,14 @@ ethjson = { path = "../json" } ethcore-devtools = { path = "../devtools" } rustc-serialize = "0.3" transient-hashmap = "0.1" -serde_macros = { version = "0.7.0", optional = true } +serde_macros = { version = "0.8.0", optional = true } clippy = { version = "0.0.85", optional = true} json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } ethcore-ipc = { path = "../ipc/rpc" } time = "0.1" [build-dependencies] -serde_codegen = { version = "0.7.0", optional = true } +serde_codegen = { version = "0.8.0", optional = true } [features] default = ["serde_codegen"] diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index b26dca8dc..f96ba8f08 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -50,13 +50,13 @@ pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: Sig import .map_err(errors::from_transaction_error) - .and_then(|_| to_value(&hash)) + .map(|_| to_value(&hash)) } pub fn signature_with_password(accounts: &AccountProvider, address: Address, hash: H256, pass: String) -> Result { accounts.sign_with_password(address, pass, hash) .map_err(errors::from_password_error) - .and_then(|hash| to_value(&RpcH520::from(hash))) + .map(|hash| to_value(&RpcH520::from(hash))) } pub fn unlock_sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, password: String) -> Result diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index fbd134e33..8a11f2466 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -38,7 +38,8 @@ mod codes { pub const ACCOUNT_ERROR: i64 = -32023; pub const SIGNER_DISABLED: i64 = -32030; pub const REQUEST_REJECTED: i64 = -32040; - pub const REQUEST_NOT_FOUND: i64 = -32041; + pub const REQUEST_REJECTED_LIMIT: i64 = -32041; + pub const REQUEST_NOT_FOUND: i64 = -32042; pub const COMPILATION_ERROR: i64 = -32050; } @@ -66,6 +67,13 @@ pub fn request_rejected() -> Error { } } +pub fn request_rejected_limit() -> Error { + Error { + code: ErrorCode::ServerError(codes::REQUEST_REJECTED_LIMIT), + message: "Request has been rejected because of queue limit.".into(), + data: None, + } +} pub fn account(error: &str, details: T) -> Error { Error { diff --git a/rpc/src/v1/helpers/signing_queue.rs b/rpc/src/v1/helpers/signing_queue.rs index 616d35364..22e15d0d6 100644 --- a/rpc/src/v1/helpers/signing_queue.rs +++ b/rpc/src/v1/helpers/signing_queue.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::thread; -use std::time::{Instant, Duration}; +use std::mem; +use std::cell::RefCell; use std::sync::{mpsc, Arc}; use std::collections::BTreeMap; use jsonrpc_core; @@ -47,14 +47,23 @@ pub enum QueueError { ReceiverError(mpsc::RecvError), } +/// Defines possible errors when inserting to queue +#[derive(Debug, PartialEq)] +pub enum QueueAddError { + LimitReached, +} + /// Message Receiver type pub type QueueEventReceiver = mpsc::Receiver; +// TODO [todr] to consider: timeout instead of limit? +const QUEUE_LIMIT: usize = 50; + /// A queue of transactions awaiting to be confirmed and signed. pub trait SigningQueue: Send + Sync { /// Add new request to the queue. /// Returns a `ConfirmationPromise` that can be used to await for resolution of given request. - fn add_request(&self, request: ConfirmationPayload) -> ConfirmationPromise; + fn add_request(&self, request: ConfirmationPayload) -> Result; /// Removes a request from the queue. /// Notifies possible token holders that request was rejected. @@ -88,42 +97,45 @@ pub enum ConfirmationResult { Confirmed(RpcResult), } -/// Time you need to confirm the request in UI. -/// This is the amount of time token holder will wait before -/// returning `None`. -/// Unless we have a multi-threaded RPC this will lock -/// any other incoming call! -const QUEUE_TIMEOUT_DURATION_SEC : u64 = 20; +type Listener = Box) + Send>; /// A handle to submitted request. /// Allows to block and wait for a resolution of that request. pub struct ConfirmationToken { result: Arc>, - handle: thread::Thread, + listeners: Arc>>, request: ConfirmationRequest, - timeout: Duration, } pub struct ConfirmationPromise { id: U256, result: Arc>, - timeout: Duration, + listeners: Arc>>, } impl ConfirmationToken { /// Submit solution to all listeners fn resolve(&self, result: Option) { - let mut res = self.result.lock(); - *res = result.map_or(ConfirmationResult::Rejected, |h| ConfirmationResult::Confirmed(h)); + let wrapped = result.clone().map_or(ConfirmationResult::Rejected, |h| ConfirmationResult::Confirmed(h)); + { + let mut res = self.result.lock(); + *res = wrapped.clone(); + } // Notify listener - self.handle.unpark(); + let listeners = { + let mut listeners = self.listeners.lock(); + mem::replace(&mut *listeners, Vec::new()) + }; + for mut listener in listeners { + listener(result.clone()); + } } fn as_promise(&self) -> ConfirmationPromise { ConfirmationPromise { id: self.request.id, result: self.result.clone(), - timeout: self.timeout, + listeners: self.listeners.clone(), } } } @@ -132,49 +144,31 @@ impl ConfirmationPromise { /// Get the ID for this request. pub fn id(&self) -> U256 { self.id } - /// Blocks current thread and awaits for - /// resolution of the transaction (rejected / confirmed) - /// Returns `None` if transaction was rejected or timeout reached. - /// Returns `Some(result)` if transaction was confirmed. - pub fn wait_with_timeout(&self) -> Option { - let res = self.wait_until(Instant::now() + self.timeout); - match res { - ConfirmationResult::Confirmed(h) => Some(h), - ConfirmationResult::Rejected | ConfirmationResult::Waiting => None, - } + /// Just get the result, assuming it exists. + pub fn result(&self) -> ConfirmationResult { + self.result.lock().clone() } - /// Just get the result, assuming it exists. - pub fn result(&self) -> ConfirmationResult { self.wait_until(Instant::now()) } - - /// Blocks current thread and awaits for - /// resolution of the request (rejected / confirmed) - /// Returns `None` if request was rejected or timeout reached. - /// Returns `Some(result)` if request was confirmed. - pub fn wait_until(&self, deadline: Instant) -> ConfirmationResult { + pub fn wait_for_result(self, callback: F) where F: FnOnce(Option) + Send + 'static { trace!(target: "own_tx", "Signer: Awaiting confirmation... ({:?}).", self.id); - loop { - let now = Instant::now(); - // Check the result... - match *self.result.lock() { - // Waiting and deadline not yet passed continue looping. - ConfirmationResult::Waiting if now < deadline => {} - // Anything else - return. - ref a => return a.clone(), - } - // wait a while longer - maybe the solution will arrive. - thread::park_timeout(deadline - now); - } + let _result = self.result.lock(); + let mut listeners = self.listeners.lock(); + // TODO [todr] Overcoming FnBox unstability + let callback = RefCell::new(Some(callback)); + listeners.push(Box::new(move |result| { + let ref mut f = *callback.borrow_mut(); + f.take().expect("Callbacks are called only once.")(result) + })); } } + /// Queue for all unconfirmed requests. pub struct ConfirmationsQueue { id: Mutex, queue: RwLock>, sender: Mutex>, receiver: Mutex>>, - timeout: Duration, } impl Default for ConfirmationsQueue { @@ -186,19 +180,11 @@ impl Default for ConfirmationsQueue { queue: RwLock::new(BTreeMap::new()), sender: Mutex::new(send), receiver: Mutex::new(Some(recv)), - timeout: Duration::from_secs(QUEUE_TIMEOUT_DURATION_SEC), } } } impl ConfirmationsQueue { - #[cfg(test)] - /// Creates new confirmations queue with specified timeout - pub fn with_timeout(timeout: Duration) -> Self { - let mut queue = Self::default(); - queue.timeout = timeout; - queue - } /// Blocks the thread and starts listening for notifications regarding all actions in the queue. /// For each event, `listener` callback will be invoked. @@ -260,7 +246,11 @@ impl Drop for ConfirmationsQueue { } impl SigningQueue for ConfirmationsQueue { - fn add_request(&self, request: ConfirmationPayload) -> ConfirmationPromise { + fn add_request(&self, request: ConfirmationPayload) -> Result { + if self.len() > QUEUE_LIMIT { + return Err(QueueAddError::LimitReached); + } + // Increment id let id = { let mut last_id = self.id.lock(); @@ -275,19 +265,17 @@ impl SigningQueue for ConfirmationsQueue { let mut queue = self.queue.write(); queue.insert(id, ConfirmationToken { result: Arc::new(Mutex::new(ConfirmationResult::Waiting)), - handle: thread::current(), + listeners: Default::default(), request: ConfirmationRequest { id: id, payload: request, }, - timeout: self.timeout, }); queue.get(&id).map(|token| token.as_promise()).expect("Token was just inserted.") }; // Notify listeners self.notify(QueueEvent::NewRequest(id)); - res - + Ok(res) } fn peek(&self, id: &U256) -> Option { @@ -325,7 +313,7 @@ impl SigningQueue for ConfirmationsQueue { mod test { use std::time::Duration; use std::thread; - use std::sync::Arc; + use std::sync::{mpsc, Arc}; use util::{Address, U256, H256, Mutex}; use v1::helpers::{SigningQueue, ConfirmationsQueue, QueueEvent, FilledTransactionRequest, ConfirmationPayload}; use v1::types::H256 as NH256; @@ -352,8 +340,12 @@ mod test { // when let q = queue.clone(); let handle = thread::spawn(move || { - let v = q.add_request(request); - v.wait_with_timeout().expect("Should return hash") + let v = q.add_request(request).unwrap(); + let (tx, rx) = mpsc::channel(); + v.wait_for_result(move |res| { + tx.send(res).unwrap(); + }); + rx.recv().unwrap().expect("Should return hash") }); let id = U256::from(1); @@ -361,10 +353,10 @@ mod test { // Just wait for the other thread to start thread::sleep(Duration::from_millis(100)); } - queue.request_confirmed(id, to_value(&NH256::from(H256::from(1)))); + queue.request_confirmed(id, Ok(to_value(&NH256::from(H256::from(1))))); // then - assert_eq!(handle.join().expect("Thread should finish nicely"), to_value(&NH256::from(H256::from(1)))); + assert_eq!(handle.join().expect("Thread should finish nicely"), Ok(to_value(&NH256::from(H256::from(1))))); } #[test] @@ -383,7 +375,7 @@ mod test { *v = Some(notification); }).expect("Should be closed nicely.") }); - queue.add_request(request); + queue.add_request(request).unwrap(); queue.finish(); // then @@ -399,7 +391,7 @@ mod test { let request = request(); // when - queue.add_request(request.clone()); + queue.add_request(request.clone()).unwrap(); let all = queue.requests(); // then diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index d805d57ee..be69a221d 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -131,7 +131,7 @@ impl EthClient where }, extra_data: Bytes::new(view.extra_data()) }; - to_value(&block) + Ok(to_value(&block)) }, _ => Ok(Value::Null) } @@ -139,7 +139,7 @@ impl EthClient where fn transaction(&self, id: TransactionID) -> Result { match take_weak!(self.client).transaction(id) { - Some(t) => to_value(&Transaction::from(t)), + Some(t) => Ok(to_value(&Transaction::from(t))), None => Ok(Value::Null) } } @@ -177,7 +177,7 @@ impl EthClient where uncles: vec![], transactions: BlockTransactions::Hashes(vec![]), }; - to_value(&block) + Ok(to_value(&block)) } fn sign_call(&self, request: CRequest) -> Result { @@ -270,28 +270,28 @@ impl Eth for EthClient where } } }; - to_value(&res) + Ok(to_value(&res)) } fn author(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&RpcH160::from(take_weak!(self.miner).author())) + Ok(to_value(&RpcH160::from(take_weak!(self.miner).author()))) } fn is_mining(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&(take_weak!(self.miner).is_sealing())) + Ok(to_value(&(take_weak!(self.miner).is_sealing()))) } fn hashrate(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&RpcU256::from(self.external_miner.hashrate())) + Ok(to_value(&RpcU256::from(self.external_miner.hashrate()))) } fn gas_price(&self, params: Params) -> Result { @@ -299,7 +299,7 @@ impl Eth for EthClient where try!(expect_no_params(params)); let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); - to_value(&RpcU256::from(default_gas_price(&*client, &*miner))) + Ok(to_value(&RpcU256::from(default_gas_price(&*client, &*miner)))) } fn accounts(&self, params: Params) -> Result { @@ -308,14 +308,14 @@ impl Eth for EthClient where let store = take_weak!(self.accounts); let accounts = try!(store.accounts().map_err(|e| errors::internal("Could not fetch accounts.", e))); - to_value(&accounts.into_iter().map(Into::into).collect::>()) + Ok(to_value(&accounts.into_iter().map(Into::into).collect::>())) } fn block_number(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&RpcU256::from(take_weak!(self.client).chain_info().best_block_number)) + Ok(to_value(&RpcU256::from(take_weak!(self.client).chain_info().best_block_number))) } fn balance(&self, params: Params) -> Result { @@ -324,9 +324,9 @@ impl Eth for EthClient where .and_then(|(address, block_number,)| { let address: Address = RpcH160::into(address); match block_number { - BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).balance(&*take_weak!(self.client), &address))), + BlockNumber::Pending => Ok(to_value(&RpcU256::from(take_weak!(self.miner).balance(&*take_weak!(self.client), &address)))), id => match take_weak!(self.client).balance(&address, id.into()) { - Some(balance) => to_value(&RpcU256::from(balance)), + Some(balance) => Ok(to_value(&RpcU256::from(balance))), None => Err(errors::state_pruned()), } } @@ -340,9 +340,9 @@ impl Eth for EthClient where let address: Address = RpcH160::into(address); let position: U256 = RpcU256::into(position); match block_number { - BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).storage_at(&*take_weak!(self.client), &address, &H256::from(position)))), + BlockNumber::Pending => Ok(to_value(&RpcU256::from(take_weak!(self.miner).storage_at(&*take_weak!(self.client), &address, &H256::from(position))))), id => match take_weak!(self.client).storage_at(&address, &H256::from(position), id.into()) { - Some(s) => to_value(&RpcH256::from(s)), + Some(s) => Ok(to_value(&RpcH256::from(s))), None => Err(errors::state_pruned()), } } @@ -356,9 +356,9 @@ impl Eth for EthClient where .and_then(|(address, block_number,)| { let address: Address = RpcH160::into(address); match block_number { - BlockNumber::Pending => to_value(&RpcU256::from(take_weak!(self.miner).nonce(&*take_weak!(self.client), &address))), + BlockNumber::Pending => Ok(to_value(&RpcU256::from(take_weak!(self.miner).nonce(&*take_weak!(self.client), &address)))), id => match take_weak!(self.client).nonce(&address, id.into()) { - Some(nonce) => to_value(&RpcU256::from(nonce)), + Some(nonce) => Ok(to_value(&RpcU256::from(nonce))), None => Err(errors::state_pruned()), } } @@ -370,18 +370,18 @@ impl Eth for EthClient where from_params::<(RpcH256,)>(params) .and_then(|(hash,)| // match take_weak!(self.client).block(BlockID::Hash(hash.into())) - .map_or(Ok(Value::Null), |bytes| to_value(&RpcU256::from(BlockView::new(&bytes).transactions_count())))) + .map_or(Ok(Value::Null), |bytes| Ok(to_value(&RpcU256::from(BlockView::new(&bytes).transactions_count()))))) } fn block_transaction_count_by_number(&self, params: Params) -> Result { try!(self.active()); from_params::<(BlockNumber,)>(params) .and_then(|(block_number,)| match block_number { - BlockNumber::Pending => to_value( + BlockNumber::Pending => Ok(to_value( &RpcU256::from(take_weak!(self.miner).status().transactions_in_pending_block) - ), + )), _ => take_weak!(self.client).block(block_number.into()) - .map_or(Ok(Value::Null), |bytes| to_value(&RpcU256::from(BlockView::new(&bytes).transactions_count()))) + .map_or(Ok(Value::Null), |bytes| Ok(to_value(&RpcU256::from(BlockView::new(&bytes).transactions_count())))) }) } @@ -390,16 +390,16 @@ impl Eth for EthClient where from_params::<(RpcH256,)>(params) .and_then(|(hash,)| take_weak!(self.client).block(BlockID::Hash(hash.into())) - .map_or(Ok(Value::Null), |bytes| to_value(&RpcU256::from(BlockView::new(&bytes).uncles_count())))) + .map_or(Ok(Value::Null), |bytes| Ok(to_value(&RpcU256::from(BlockView::new(&bytes).uncles_count()))))) } fn block_uncles_count_by_number(&self, params: Params) -> Result { try!(self.active()); from_params::<(BlockNumber,)>(params) .and_then(|(block_number,)| match block_number { - BlockNumber::Pending => to_value(&RpcU256::from(0)), + BlockNumber::Pending => Ok(to_value(&RpcU256::from(0))), _ => take_weak!(self.client).block(block_number.into()) - .map_or(Ok(Value::Null), |bytes| to_value(&RpcU256::from(BlockView::new(&bytes).uncles_count()))) + .map_or(Ok(Value::Null), |bytes| Ok(to_value(&RpcU256::from(BlockView::new(&bytes).uncles_count())))) }) } @@ -409,9 +409,9 @@ impl Eth for EthClient where .and_then(|(address, block_number,)| { let address: Address = RpcH160::into(address); match block_number { - BlockNumber::Pending => to_value(&take_weak!(self.miner).code(&*take_weak!(self.client), &address).map_or_else(Bytes::default, Bytes::new)), + BlockNumber::Pending => Ok(to_value(&take_weak!(self.miner).code(&*take_weak!(self.client), &address).map_or_else(Bytes::default, Bytes::new))), _ => match take_weak!(self.client).code(&address, block_number.into()) { - Some(code) => to_value(&code.map_or_else(Bytes::default, Bytes::new)), + Some(code) => Ok(to_value(&code.map_or_else(Bytes::default, Bytes::new))), None => Err(errors::state_pruned()), }, } @@ -437,7 +437,7 @@ impl Eth for EthClient where let miner = take_weak!(self.miner); let hash: H256 = hash.into(); match miner.transaction(&hash) { - Some(pending_tx) => to_value(&Transaction::from(pending_tx)), + Some(pending_tx) => Ok(to_value(&Transaction::from(pending_tx))), None => self.transaction(TransactionID::Hash(hash)) } }) @@ -462,11 +462,11 @@ impl Eth for EthClient where let miner = take_weak!(self.miner); let hash: H256 = hash.into(); match (miner.pending_receipt(&hash), self.options.allow_pending_receipt_query) { - (Some(receipt), true) => to_value(&Receipt::from(receipt)), + (Some(receipt), true) => Ok(to_value(&Receipt::from(receipt))), _ => { let client = take_weak!(self.client); let receipt = client.transaction_receipt(TransactionID::Hash(hash)); - to_value(&receipt.map(Receipt::from)) + Ok(to_value(&receipt.map(Receipt::from))) } } }) @@ -492,7 +492,7 @@ impl Eth for EthClient where if Command::new(SOLC).output().is_ok() { compilers.push("solidity".to_owned()) } - to_value(&compilers) + Ok(to_value(&compilers)) } fn logs(&self, params: Params) -> Result { @@ -511,7 +511,7 @@ impl Eth for EthClient where logs.extend(pending); } - to_value(&logs) + Ok(to_value(&logs)) }) } @@ -550,9 +550,9 @@ impl Eth for EthClient where Err(errors::no_new_work()) } else if self.options.send_block_number_in_get_work { let block_number = RpcU256::from(b.block().header().number()); - to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target), block_number)) + Ok(to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target), block_number))) } else { - to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target))) + Ok(to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target)))) } }).unwrap_or(Err(Error::internal_error())) // no work found. } @@ -568,7 +568,7 @@ impl Eth for EthClient where let client = take_weak!(self.client); let seal = vec![encode(&mix_hash).to_vec(), encode(&nonce).to_vec()]; let r = miner.submit_seal(&*client, pow_hash, seal); - to_value(&r.is_ok()) + Ok(to_value(&r.is_ok())) }) } @@ -576,7 +576,7 @@ impl Eth for EthClient where try!(self.active()); from_params::<(RpcU256, RpcH256)>(params).and_then(|(rate, id)| { self.external_miner.submit_hashrate(rate.into(), id.into()); - to_value(&true) + Ok(to_value(&true)) }) } @@ -587,7 +587,7 @@ impl Eth for EthClient where let raw_transaction = raw_transaction.to_vec(); match UntrustedRlp::new(&raw_transaction).as_val() { Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction), - Err(_) => to_value(&RpcH256::from(H256::from(0))), + Err(_) => Ok(to_value(&RpcH256::from(H256::from(0)))), } }) } @@ -602,7 +602,7 @@ impl Eth for EthClient where BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()), block_number => take_weak!(self.client).call(&signed, block_number.into(), Default::default()), }; - to_value(&r.map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![]))) + Ok(to_value(&r.map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![])))) }) } @@ -616,7 +616,7 @@ impl Eth for EthClient where BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()), block => take_weak!(self.client).call(&signed, block.into(), Default::default()), }; - to_value(&RpcU256::from(r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0)))) + Ok(to_value(&RpcU256::from(r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0))))) }) } @@ -653,7 +653,7 @@ impl Eth for EthClient where let s = String::from_utf8_lossy(&output.stdout); if let Some(hex) = s.lines().skip_while(|ref l| !l.contains("Binary")).skip(1).next() { - to_value(&Bytes::new(hex.from_hex().unwrap_or(vec![]))) + Ok(to_value(&Bytes::new(hex.from_hex().unwrap_or(vec![])))) } else { Err(errors::compilation("Unexpected output.")) } diff --git a/rpc/src/v1/impls/eth_filter.rs b/rpc/src/v1/impls/eth_filter.rs index 973e23e0b..a4c834e99 100644 --- a/rpc/src/v1/impls/eth_filter.rs +++ b/rpc/src/v1/impls/eth_filter.rs @@ -70,7 +70,7 @@ impl EthFilter for EthFilterClient where let mut polls = self.polls.lock(); let block_number = take_weak!(self.client).chain_info().best_block_number; let id = polls.create_poll(PollFilter::Logs(block_number, Default::default(), filter)); - to_value(&RpcU256::from(id)) + Ok(to_value(&RpcU256::from(id))) }) } @@ -80,7 +80,7 @@ impl EthFilter for EthFilterClient where let mut polls = self.polls.lock(); let id = polls.create_poll(PollFilter::Block(take_weak!(self.client).chain_info().best_block_number)); - to_value(&RpcU256::from(id)) + Ok(to_value(&RpcU256::from(id))) } fn new_pending_transaction_filter(&self, params: Params) -> Result { @@ -91,7 +91,7 @@ impl EthFilter for EthFilterClient where let pending_transactions = take_weak!(self.miner).pending_transactions_hashes(); let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions)); - to_value(&RpcU256::from(id)) + Ok(to_value(&RpcU256::from(id))) } fn filter_changes(&self, params: Params) -> Result { @@ -114,7 +114,7 @@ impl EthFilter for EthFilterClient where *block_number = current_number; - to_value(&hashes) + Ok(to_value(&hashes)) }, PollFilter::PendingTransaction(ref mut previous_hashes) => { // get hashes of pending transactions @@ -137,7 +137,7 @@ impl EthFilter for EthFilterClient where *previous_hashes = current_hashes; // return new hashes - to_value(&new_hashes) + Ok(to_value(&new_hashes)) }, PollFilter::Logs(ref mut block_number, ref mut previous_logs, ref filter) => { // retrive the current block number @@ -178,7 +178,7 @@ impl EthFilter for EthFilterClient where // we want to get logs *block_number = current_number + 1; - to_value(&logs) + Ok(to_value(&logs)) } } } @@ -203,7 +203,7 @@ impl EthFilter for EthFilterClient where logs.extend(pending_logs(&*take_weak!(self.miner), &filter)); } - to_value(&logs) + Ok(to_value(&logs)) }, // just empty array _ => Ok(Value::Array(vec![] as Vec)), @@ -214,7 +214,7 @@ impl EthFilter for EthFilterClient where fn uninstall_filter(&self, params: Params) -> Result { try!(self.active()); from_params::<(Index,)>(params) - .and_then(|(index,)| { + .map(|(index,)| { self.polls.lock().remove_poll(&index.value()); to_value(&true) }) diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index 98aec52a2..c19b5819d 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -53,6 +53,11 @@ pub struct EthSigningQueueClient where C: MiningBlockChainClient, M: Miner const MAX_PENDING_DURATION: u64 = 60 * 60; +pub enum DispatchResult { + Promise(ConfirmationPromise), + Value(Value), +} + impl EthSigningQueueClient where C: MiningBlockChainClient, M: MinerService { /// Creates a new signing queue client given shared signing queue. pub fn new(queue: &Arc, client: &Arc, miner: &Arc, accounts: &Arc) -> Self { @@ -71,23 +76,24 @@ impl EthSigningQueueClient where C: MiningBlockChainClient, M: Miner Ok(()) } - fn dispatch_sign Result>(&self, params: Params, f: F) -> Result { + fn dispatch_sign(&self, params: Params) -> Result { from_params::<(RpcH160, RpcH256)>(params).and_then(|(address, msg)| { let address: Address = address.into(); let msg: H256 = msg.into(); let accounts = take_weak!(self.accounts); if accounts.is_unlocked(address) { - return to_value(&accounts.sign(address, msg).ok().map_or_else(RpcH520::default, Into::into)); + return Ok(DispatchResult::Value(to_value(&accounts.sign(address, msg).ok().map_or_else(RpcH520::default, Into::into)))) } let queue = take_weak!(self.queue); - let promise = queue.add_request(ConfirmationPayload::Sign(address, msg)); - f(promise) + queue.add_request(ConfirmationPayload::Sign(address, msg)) + .map(DispatchResult::Promise) + .map_err(|_| errors::request_rejected_limit()) }) } - fn dispatch_transaction Result>(&self, params: Params, f: F) -> Result { + fn dispatch_transaction(&self, params: Params) -> Result { from_params::<(TransactionRequest, )>(params) .and_then(|(request, )| { let request: TRequest = request.into(); @@ -96,13 +102,14 @@ impl EthSigningQueueClient where C: MiningBlockChainClient, M: Miner if accounts.is_unlocked(request.from) { let sender = request.from; - return sign_and_dispatch(&*client, &*miner, request, &*accounts, sender); + return sign_and_dispatch(&*client, &*miner, request, &*accounts, sender).map(DispatchResult::Value); } let queue = take_weak!(self.queue); let request = fill_optional_fields(request, &*client, &*miner); - let promise = queue.add_request(ConfirmationPayload::Transaction(request)); - f(promise) + queue.add_request(ConfirmationPayload::Transaction(request)) + .map(DispatchResult::Promise) + .map_err(|_| errors::request_rejected_limit()) }) } } @@ -111,35 +118,53 @@ impl EthSigning for EthSigningQueueClient where C: MiningBlockChainClient + 'static, M: MinerService + 'static { - fn sign(&self, params: Params) -> Result { - try!(self.active()); - self.dispatch_sign(params, |promise| { - promise.wait_with_timeout().unwrap_or_else(|| to_value(&RpcH520::default())) - }) + fn sign(&self, params: Params, ready: Ready) { + let res = self.active().and_then(|_| self.dispatch_sign(params)); + match res { + Ok(DispatchResult::Promise(promise)) => { + promise.wait_for_result(move |result| { + ready.ready(result.unwrap_or_else(|| Err(errors::request_rejected()))) + }) + }, + Ok(DispatchResult::Value(v)) => ready.ready(Ok(v)), + Err(e) => ready.ready(Err(e)), + } } fn post_sign(&self, params: Params) -> Result { try!(self.active()); - self.dispatch_sign(params, |promise| { - let id = promise.id(); - self.pending.lock().insert(id, promise); - to_value(&RpcU256::from(id)) + self.dispatch_sign(params).map(|result| match result { + DispatchResult::Value(v) => v, + DispatchResult::Promise(promise) => { + let id = promise.id(); + self.pending.lock().insert(id, promise); + to_value(&RpcU256::from(id)) + }, }) } - fn send_transaction(&self, params: Params) -> Result { - try!(self.active()); - self.dispatch_transaction(params, |promise| { - promise.wait_with_timeout().unwrap_or_else(|| to_value(&RpcH256::default())) - }) + fn send_transaction(&self, params: Params, ready: Ready) { + let res = self.active().and_then(|_| self.dispatch_transaction(params)); + match res { + Ok(DispatchResult::Promise(promise)) => { + promise.wait_for_result(move |result| { + ready.ready(result.unwrap_or_else(|| Err(errors::request_rejected()))) + }) + }, + Ok(DispatchResult::Value(v)) => ready.ready(Ok(v)), + Err(e) => ready.ready(Err(e)), + } } fn post_transaction(&self, params: Params) -> Result { try!(self.active()); - self.dispatch_transaction(params, |promise| { - let id = promise.id(); - self.pending.lock().insert(id, promise); - to_value(&RpcU256::from(id)) + self.dispatch_transaction(params).map(|result| match result { + DispatchResult::Value(v) => v, + DispatchResult::Promise(promise) => { + let id = promise.id(); + self.pending.lock().insert(id, promise); + to_value(&RpcU256::from(id)) + }, }) } @@ -196,23 +221,24 @@ impl EthSigning for EthSigningUnsafeClient where C: MiningBlockChainClient + 'static, M: MinerService + 'static { - fn sign(&self, params: Params) -> Result { - try!(self.active()); - from_params::<(RpcH160, RpcH256)>(params).and_then(|(address, msg)| { - let address: Address = address.into(); - let msg: H256 = msg.into(); - to_value(&take_weak!(self.accounts).sign(address, msg).ok().map_or_else(RpcH520::default, Into::into)) - }) + fn sign(&self, params: Params, ready: Ready) { + ready.ready(self.active() + .and_then(|_| from_params::<(RpcH160, RpcH256)>(params)) + .and_then(|(address, msg)| { + let address: Address = address.into(); + let msg: H256 = msg.into(); + Ok(to_value(&take_weak!(self.accounts).sign(address, msg).ok().map_or_else(RpcH520::default, Into::into))) + })) } - fn send_transaction(&self, params: Params) -> Result { - try!(self.active()); - from_params::<(TransactionRequest, )>(params) + fn send_transaction(&self, params: Params, ready: Ready) { + ready.ready(self.active() + .and_then(|_| from_params::<(TransactionRequest, )>(params)) .and_then(|(request, )| { let request: TRequest = request.into(); let sender = request.from; sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, &*take_weak!(self.accounts), sender) - }) + })) } fn post_sign(&self, _: Params) -> Result { diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index 16b0f1931..ee352e65a 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -82,50 +82,50 @@ impl Ethcore for EthcoreClient where M: MinerService + fn transactions_limit(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&take_weak!(self.miner).transactions_limit()) + Ok(to_value(&take_weak!(self.miner).transactions_limit())) } fn min_gas_price(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&U256::from(take_weak!(self.miner).minimal_gas_price())) + Ok(to_value(&U256::from(take_weak!(self.miner).minimal_gas_price()))) } fn extra_data(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&Bytes::new(take_weak!(self.miner).extra_data())) + Ok(to_value(&Bytes::new(take_weak!(self.miner).extra_data()))) } fn gas_floor_target(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&U256::from(take_weak!(self.miner).gas_floor_target())) + Ok(to_value(&U256::from(take_weak!(self.miner).gas_floor_target()))) } fn gas_ceil_target(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&U256::from(take_weak!(self.miner).gas_ceil_target())) + Ok(to_value(&U256::from(take_weak!(self.miner).gas_ceil_target()))) } fn dev_logs(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); let logs = self.logger.logs(); - to_value(&logs.as_slice()) + Ok(to_value(&logs.as_slice())) } fn dev_logs_levels(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&self.logger.levels()) + Ok(to_value(&self.logger.levels())) } fn net_chain(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&self.settings.chain) + Ok(to_value(&self.settings.chain)) } fn net_peers(&self, params: Params) -> Result { @@ -135,23 +135,23 @@ impl Ethcore for EthcoreClient where M: MinerService + let sync_status = take_weak!(self.sync).status(); let net_config = take_weak!(self.net).network_config(); - to_value(&Peers { + Ok(to_value(&Peers { active: sync_status.num_active_peers, connected: sync_status.num_peers, max: sync_status.current_max_peers(net_config.min_peers, net_config.max_peers), - }) + })) } fn net_port(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&self.settings.network_port) + Ok(to_value(&self.settings.network_port)) } fn node_name(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&self.settings.name) + Ok(to_value(&self.settings.name)) } fn registry_address(&self, params: Params) -> Result { @@ -162,7 +162,7 @@ impl Ethcore for EthcoreClient where M: MinerService + .get("registrar") .and_then(|s| Address::from_str(s).ok()) .map(|s| H160::from(s)); - to_value(&r) + Ok(to_value(&r)) } fn rpc_settings(&self, params: Params) -> Result { @@ -178,7 +178,7 @@ impl Ethcore for EthcoreClient where M: MinerService + fn default_extra_data(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); - to_value(&Bytes::new(version_data())) + Ok(to_value(&Bytes::new(version_data()))) } fn gas_price_statistics(&self, params: Params) -> Result { @@ -186,10 +186,10 @@ impl Ethcore for EthcoreClient where M: MinerService + try!(expect_no_params(params)); match take_weak!(self.client).gas_price_statistics(100, 8) { - Ok(stats) => to_value(&stats + Ok(stats) => Ok(to_value(&stats .into_iter() - .map(|x| to_value(&U256::from(x)).expect("x must be U256; qed")) - .collect::>()), + .map(|x| to_value(&U256::from(x))) + .collect::>())), _ => Err(Error::internal_error()), } } @@ -200,7 +200,7 @@ impl Ethcore for EthcoreClient where M: MinerService + match self.confirmations_queue { None => Err(errors::signer_disabled()), - Some(ref queue) => to_value(&queue.len()), + Some(ref queue) => Ok(to_value(&queue.len())), } } @@ -208,12 +208,12 @@ impl Ethcore for EthcoreClient where M: MinerService + try!(self.active()); try!(expect_no_params(params)); - to_value(&random_phrase(12)) + Ok(to_value(&random_phrase(12))) } fn phrase_to_address(&self, params: Params) -> Result { try!(self.active()); - from_params::<(String,)>(params).and_then(|(phrase,)| + from_params::<(String,)>(params).map(|(phrase,)| to_value(&H160::from(Brain::new(phrase).generate().unwrap().address())) ) } diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index a5e037b5f..35b97f785 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -62,7 +62,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(U256,)>(params).and_then(|(gas_price,)| { take_weak!(self.miner).set_minimal_gas_price(gas_price.into()); - to_value(&true) + Ok(to_value(&true)) }) } @@ -70,7 +70,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(U256,)>(params).and_then(|(target,)| { take_weak!(self.miner).set_gas_floor_target(target.into()); - to_value(&true) + Ok(to_value(&true)) }) } @@ -78,7 +78,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(U256,)>(params).and_then(|(target,)| { take_weak!(self.miner).set_gas_ceil_target(target.into()); - to_value(&true) + Ok(to_value(&true)) }) } @@ -86,7 +86,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(Bytes,)>(params).and_then(|(extra_data,)| { take_weak!(self.miner).set_extra_data(extra_data.to_vec()); - to_value(&true) + Ok(to_value(&true)) }) } @@ -94,7 +94,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(H160,)>(params).and_then(|(author,)| { take_weak!(self.miner).set_author(author.into()); - to_value(&true) + Ok(to_value(&true)) }) } @@ -102,7 +102,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(usize,)>(params).and_then(|(limit,)| { take_weak!(self.miner).set_transactions_limit(limit); - to_value(&true) + Ok(to_value(&true)) }) } @@ -110,7 +110,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(U256,)>(params).and_then(|(limit,)| { take_weak!(self.miner).set_tx_gas_limit(limit.into()); - to_value(&true) + Ok(to_value(&true)) }) } @@ -118,7 +118,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(String,)>(params).and_then(|(peer,)| { match take_weak!(self.net).add_reserved_peer(peer) { - Ok(()) => to_value(&true), + Ok(()) => Ok(to_value(&true)), Err(e) => Err(errors::invalid_params("Peer address", e)), } }) @@ -128,7 +128,7 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); from_params::<(String,)>(params).and_then(|(peer,)| { match take_weak!(self.net).remove_reserved_peer(peer) { - Ok(()) => to_value(&true), + Ok(()) => Ok(to_value(&true)), Err(e) => Err(errors::invalid_params("Peer address", e)), } }) @@ -138,14 +138,14 @@ impl EthcoreSet for EthcoreSetClient where try!(self.active()); try!(expect_no_params(params)); take_weak!(self.net).deny_unreserved_peers(); - to_value(&true) + Ok(to_value(&true)) } fn accept_non_reserved_peers(&self, params: Params) -> Result { try!(self.active()); try!(expect_no_params(params)); take_weak!(self.net).accept_unreserved_peers(); - to_value(&true) + Ok(to_value(&true)) } fn start_network(&self, params: Params) -> Result { diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 4d7008e09..009f173b3 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -63,9 +63,9 @@ impl Personal for PersonalClient where C: MiningBl try!(self.active()); try!(expect_no_params(params)); - self.signer_port + Ok(self.signer_port .map(|v| to_value(&v)) - .unwrap_or_else(|| to_value(&false)) + .unwrap_or_else(|| to_value(&false))) } fn accounts(&self, params: Params) -> Result { @@ -74,7 +74,7 @@ impl Personal for PersonalClient where C: MiningBl let store = take_weak!(self.accounts); let accounts = try!(store.accounts().map_err(|e| errors::internal("Could not fetch accounts.", e))); - to_value(&accounts.into_iter().map(Into::into).collect::>()) + Ok(to_value(&accounts.into_iter().map(Into::into).collect::>())) } fn new_account(&self, params: Params) -> Result { @@ -83,7 +83,7 @@ impl Personal for PersonalClient where C: MiningBl |(pass, )| { let store = take_weak!(self.accounts); match store.new_account(&pass) { - Ok(address) => to_value(&RpcH160::from(address)), + Ok(address) => Ok(to_value(&RpcH160::from(address))), Err(e) => Err(errors::account("Could not create account.", e)), } } @@ -96,7 +96,7 @@ impl Personal for PersonalClient where C: MiningBl |(phrase, pass, )| { let store = take_weak!(self.accounts); match store.insert_account(*Brain::new(phrase).generate().unwrap().secret(), &pass) { - Ok(address) => to_value(&RpcH160::from(address)), + Ok(address) => Ok(to_value(&RpcH160::from(address))), Err(e) => Err(errors::account("Could not create account.", e)), } } @@ -109,7 +109,7 @@ impl Personal for PersonalClient where C: MiningBl |(json, pass, )| { let store = take_weak!(self.accounts); match store.import_presale(json.as_bytes(), &pass).or_else(|_| store.import_wallet(json.as_bytes(), &pass)) { - Ok(address) => to_value(&RpcH160::from(address)), + Ok(address) => Ok(to_value(&RpcH160::from(address))), Err(e) => Err(errors::account("Could not create account.", e)), } } @@ -174,10 +174,10 @@ impl Personal for PersonalClient where C: MiningBl let other = store.addresses_info().expect("addresses_info always returns Ok; qed"); Ok(Value::Object(info.into_iter().chain(other.into_iter()).map(|(a, v)| { let m = map![ - "name".to_owned() => to_value(&v.name).unwrap(), - "meta".to_owned() => to_value(&v.meta).unwrap(), + "name".to_owned() => to_value(&v.name), + "meta".to_owned() => to_value(&v.meta), "uuid".to_owned() => if let &Some(ref uuid) = &v.uuid { - to_value(uuid).unwrap() + to_value(uuid) } else { Value::Null } @@ -190,16 +190,16 @@ impl Personal for PersonalClient where C: MiningBl try!(self.active()); try!(expect_no_params(params)); let store = take_weak!(self.accounts); - to_value(&store.list_geth_accounts(false).into_iter().map(Into::into).collect::>()) + Ok(to_value(&store.list_geth_accounts(false).into_iter().map(Into::into).collect::>())) } fn import_geth_accounts(&self, params: Params) -> Result { from_params::<(Vec,)>(params).and_then(|(addresses,)| { let store = take_weak!(self.accounts); - to_value(&try!(store + Ok(to_value(&try!(store .import_geth_accounts(addresses.into_iter().map(Into::into).collect(), false) .map_err(|e| errors::account("Couldn't import Geth accounts", e)) - ).into_iter().map(Into::into).collect::>()) + ).into_iter().map(Into::into).collect::>())) }) } } diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs index bd58fde7d..5cfda9a65 100644 --- a/rpc/src/v1/impls/personal_signer.rs +++ b/rpc/src/v1/impls/personal_signer.rs @@ -60,7 +60,7 @@ impl PersonalSigner for SignerClient where C: Mini try!(self.active()); try!(expect_no_params(params)); let queue = take_weak!(self.queue); - to_value(&queue.requests().into_iter().map(From::from).collect::>()) + Ok(to_value(&queue.requests().into_iter().map(From::from).collect::>())) } fn confirm_request(&self, params: Params) -> Result { @@ -104,7 +104,7 @@ impl PersonalSigner for SignerClient where C: Mini |(id, )| { let queue = take_weak!(self.queue); let res = queue.request_rejected(id.into()); - to_value(&res.is_some()) + Ok(to_value(&res.is_some())) } ) } diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index e5f84d9ef..acbedd3c2 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -80,7 +80,7 @@ impl Traces for TracesClient where C: BlockChainClient + 'static, M: let client = take_weak!(self.client); let traces = client.filter_traces(filter.into()); let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - to_value(&traces) + Ok(to_value(&traces)) }) } @@ -91,7 +91,7 @@ impl Traces for TracesClient where C: BlockChainClient + 'static, M: let client = take_weak!(self.client); let traces = client.block_traces(block_number.into()); let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - to_value(&traces) + Ok(to_value(&traces)) }) } @@ -102,7 +102,7 @@ impl Traces for TracesClient where C: BlockChainClient + 'static, M: let client = take_weak!(self.client); let traces = client.transaction_traces(TransactionID::Hash(transaction_hash.into())); let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - to_value(&traces) + Ok(to_value(&traces)) }) } @@ -117,7 +117,7 @@ impl Traces for TracesClient where C: BlockChainClient + 'static, M: }; let trace = client.trace(id); let trace = trace.map(LocalizedTrace::from); - to_value(&trace) + Ok(to_value(&trace)) }) } @@ -128,7 +128,7 @@ impl Traces for TracesClient where C: BlockChainClient + 'static, M: let request = CallRequest::into(request); let signed = try!(self.sign_call(request)); match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) { - Ok(e) => to_value(&TraceResults::from(e)), + Ok(e) => Ok(to_value(&TraceResults::from(e))), _ => Ok(Value::Null), } }) @@ -141,7 +141,7 @@ impl Traces for TracesClient where C: BlockChainClient + 'static, M: let raw_transaction = Bytes::to_vec(raw_transaction); match UntrustedRlp::new(&raw_transaction).as_val() { Ok(signed) => match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) { - Ok(e) => to_value(&TraceResults::from(e)), + Ok(e) => Ok(to_value(&TraceResults::from(e))), _ => Ok(Value::Null), }, Err(e) => Err(errors::invalid_params("Transaction is not valid RLP", e)), @@ -154,7 +154,7 @@ impl Traces for TracesClient where C: BlockChainClient + 'static, M: from_params::<(H256, _)>(params) .and_then(|(transaction_hash, flags)| { match take_weak!(self.client).replay(TransactionID::Hash(transaction_hash.into()), to_call_analytics(flags)) { - Ok(e) => to_value(&TraceResults::from(e)), + Ok(e) => Ok(to_value(&TraceResults::from(e))), _ => Ok(Value::Null), } }) diff --git a/rpc/src/v1/impls/web3.rs b/rpc/src/v1/impls/web3.rs index d4ff4f7aa..3f987d27e 100644 --- a/rpc/src/v1/impls/web3.rs +++ b/rpc/src/v1/impls/web3.rs @@ -37,7 +37,7 @@ impl Web3 for Web3Client { } fn sha3(&self, params: Params) -> Result { - from_params::<(Bytes,)>(params).and_then( + from_params::<(Bytes,)>(params).map( |(data,)| { let Bytes(ref vec) = data; let sha3 = vec.sha3(); diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 301492540..117b783db 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -157,7 +157,7 @@ fn eth_get_balance() { "id": 1 }"#; let res_latest = r#"{"jsonrpc":"2.0","result":"0x09","id":1}"#.to_owned(); - assert_eq!(tester.handler.handle_request(req_latest).unwrap(), res_latest); + assert_eq!(tester.handler.handle_request_sync(req_latest).unwrap(), res_latest); // non-existant account let req_new_acc = r#"{ @@ -168,7 +168,7 @@ fn eth_get_balance() { }"#; let res_new_acc = r#"{"jsonrpc":"2.0","result":"0x00","id":3}"#.to_owned(); - assert_eq!(tester.handler.handle_request(req_new_acc).unwrap(), res_new_acc); + assert_eq!(tester.handler.handle_request_sync(req_new_acc).unwrap(), res_new_acc); } #[test] @@ -183,7 +183,7 @@ fn eth_block_number() { }"#; let res_number = r#"{"jsonrpc":"2.0","result":"0x20","id":1}"#.to_owned(); - assert_eq!(tester.handler.handle_request(req_number).unwrap(), res_number); + assert_eq!(tester.handler.handle_request_sync(req_number).unwrap(), res_number); } // a frontier-like test with an expanded gas limit and balance on known account. @@ -299,7 +299,7 @@ fn eth_transaction_count() { let res_before = r#"{"jsonrpc":"2.0","result":"0x00","id":15}"#; - assert_eq!(tester.handler.handle_request(&req_before).unwrap(), res_before); + assert_eq!(tester.handler.handle_request_sync(&req_before).unwrap(), res_before); let req_send_trans = r#"{ "jsonrpc": "2.0", @@ -315,7 +315,7 @@ fn eth_transaction_count() { }"#; // dispatch the transaction. - tester.handler.handle_request(&req_send_trans).unwrap(); + tester.handler.handle_request_sync(&req_send_trans).unwrap(); // we have submitted the transaction -- but this shouldn't be reflected in a "latest" query. let req_after_latest = r#"{ @@ -327,7 +327,7 @@ fn eth_transaction_count() { let res_after_latest = r#"{"jsonrpc":"2.0","result":"0x00","id":17}"#; - assert_eq!(&tester.handler.handle_request(&req_after_latest).unwrap(), res_after_latest); + assert_eq!(&tester.handler.handle_request_sync(&req_after_latest).unwrap(), res_after_latest); // the pending transactions should have been updated. let req_after_pending = r#"{ @@ -339,7 +339,7 @@ fn eth_transaction_count() { let res_after_pending = r#"{"jsonrpc":"2.0","result":"0x01","id":18}"#; - assert_eq!(&tester.handler.handle_request(&req_after_pending).unwrap(), res_after_pending); + assert_eq!(&tester.handler.handle_request_sync(&req_after_pending).unwrap(), res_after_pending); } fn verify_transaction_counts(name: String, chain: BlockChain) { @@ -400,12 +400,12 @@ fn verify_transaction_counts(name: String, chain: BlockChain) { let number = b.header_view().number(); let (req, res) = by_hash(hash, count, &mut id); - assert_eq!(tester.handler.handle_request(&req), Some(res)); + assert_eq!(tester.handler.handle_request_sync(&req), Some(res)); // uncles can share block numbers, so skip them. if tester.client.block_hash(BlockID::Number(number)) == Some(hash) { let (req, res) = by_number(number, count, &mut id); - assert_eq!(tester.handler.handle_request(&req), Some(res)); + assert_eq!(tester.handler.handle_request_sync(&req), Some(res)); } } } @@ -415,7 +415,7 @@ fn starting_nonce_test() { let tester = EthTester::from_spec(Spec::load(POSITIVE_NONCE_SPEC)); let address = Address::from(10); - let sample = tester.handler.handle_request(&(r#" + let sample = tester.handler.handle_request_sync(&(r#" { "jsonrpc": "2.0", "method": "eth_getTransactionCount", diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index d7d93137f..a6b5a1ef7 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -97,7 +97,7 @@ fn rpc_eth_protocol_version() { let request = r#"{"jsonrpc": "2.0", "method": "eth_protocolVersion", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"63","id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -107,7 +107,7 @@ fn rpc_eth_syncing() { let tester = EthTester::default(); let false_res = r#"{"jsonrpc":"2.0","result":false,"id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(false_res.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(false_res.to_owned())); { let mut status = tester.sync.status.write(); @@ -123,7 +123,7 @@ fn rpc_eth_syncing() { } let true_res = r#"{"jsonrpc":"2.0","result":{"currentBlock":"0x03e8","highestBlock":"0x09c4","startingBlock":"0x00"},"id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(true_res.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(true_res.to_owned())); { // finish "syncing" @@ -133,7 +133,7 @@ fn rpc_eth_syncing() { } } - assert_eq!(tester.io.handle_request(request), Some(false_res.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(false_res.to_owned())); } #[test] @@ -146,7 +146,7 @@ fn rpc_eth_hashrate() { let request = r#"{"jsonrpc": "2.0", "method": "eth_hashrate", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0xfffc","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -163,7 +163,7 @@ fn rpc_eth_submit_hashrate() { }"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(tester.hashrates.lock().get(&H256::from("0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c")).cloned().unwrap().1, U256::from(0x500_000)); } @@ -188,7 +188,7 @@ fn rpc_eth_sign() { }"#; let res = r#"{"jsonrpc":"2.0","result":""#.to_owned() + &format!("0x{}", signed) + r#"","id":1}"#; - assert_eq!(tester.io.handle_request(&req), Some(res)); + assert_eq!(tester.io.handle_request_sync(&req), Some(res)); } #[test] @@ -203,13 +203,13 @@ fn rpc_eth_author() { "id": 1 }"#; - assert_eq!(tester.io.handle_request(req), Some(make_res(Address::zero()))); + assert_eq!(tester.io.handle_request_sync(req), Some(make_res(Address::zero()))); for i in 0..20 { let addr = tester.accounts_provider.new_account(&format!("{}", i)).unwrap(); tester.miner.set_author(addr.clone()); - assert_eq!(tester.io.handle_request(req), Some(make_res(addr))); + assert_eq!(tester.io.handle_request_sync(req), Some(make_res(addr))); } } @@ -220,7 +220,7 @@ fn rpc_eth_mining() { let request = r#"{"jsonrpc": "2.0", "method": "eth_mining", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -228,7 +228,7 @@ fn rpc_eth_gas_price() { let request = r#"{"jsonrpc": "2.0", "method": "eth_gasPrice", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x04a817c800","id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -239,7 +239,7 @@ fn rpc_eth_accounts() { let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:?}", address) + r#""],"id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -250,7 +250,7 @@ fn rpc_eth_block_number() { let request = r#"{"jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x0a","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -266,7 +266,7 @@ fn rpc_eth_balance() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x05","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -286,7 +286,7 @@ fn rpc_eth_balance_pending() { // miner. let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -302,7 +302,7 @@ fn rpc_eth_storage_at() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000007","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -315,7 +315,7 @@ fn rpc_eth_transaction_count() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -328,7 +328,7 @@ fn rpc_eth_block_transaction_count_by_hash() { }"#; let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -341,7 +341,7 @@ fn rpc_eth_transaction_count_by_number() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -354,7 +354,7 @@ fn rpc_eth_transaction_count_by_number_pending() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x01","id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -375,7 +375,7 @@ fn rpc_eth_pending_transaction_by_hash() { "params": ["0x0000000000000000000000000000000000000000000000000000000000000000"], "id": 1 }"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } @@ -389,7 +389,7 @@ fn rpc_eth_uncle_count_by_block_hash() { }"#; let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -402,7 +402,7 @@ fn rpc_eth_uncle_count_by_block_number() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -418,7 +418,7 @@ fn rpc_eth_code() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0xff21","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -453,7 +453,7 @@ fn rpc_eth_call_latest() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -488,7 +488,7 @@ fn rpc_eth_call() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -522,7 +522,7 @@ fn rpc_eth_call_default_block() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -557,7 +557,7 @@ fn rpc_eth_estimate_gas() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -591,7 +591,7 @@ fn rpc_eth_estimate_gas_default_block() { }"#; let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -625,7 +625,7 @@ fn rpc_eth_send_transaction() { let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; - assert_eq!(tester.io.handle_request(&request), Some(response)); + assert_eq!(tester.io.handle_request_sync(&request), Some(response)); tester.miner.last_nonces.write().insert(address.clone(), U256::zero()); @@ -642,7 +642,7 @@ fn rpc_eth_send_transaction() { let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; - assert_eq!(tester.io.handle_request(&request), Some(response)); + assert_eq!(tester.io.handle_request_sync(&request), Some(response)); } #[test] fn rpc_eth_send_transaction_with_bad_to() { @@ -663,7 +663,7 @@ fn rpc_eth_send_transaction_with_bad_to() { let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params","data":null},"id":1}"#; - assert_eq!(tester.io.handle_request(&request), Some(response.into())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); } @@ -685,7 +685,7 @@ fn rpc_eth_send_transaction_error() { }"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32020,"message":"Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.","data":"NotUnlocked"},"id":1}"#; - assert_eq!(tester.io.handle_request(&request), Some(response.into())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); } #[test] @@ -718,7 +718,7 @@ fn rpc_eth_send_raw_transaction() { let res = r#"{"jsonrpc":"2.0","result":""#.to_owned() + &format!("0x{:?}", t.hash()) + r#"","id":1}"#; - assert_eq!(tester.io.handle_request(&req), Some(res)); + assert_eq!(tester.io.handle_request_sync(&req), Some(res)); } #[test] @@ -760,7 +760,7 @@ fn rpc_eth_transaction_receipt() { }"#; let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","data":"0x","logIndex":"0x01","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00","type":"mined"}],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00"},"id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -775,7 +775,7 @@ fn rpc_eth_transaction_receipt_null() { }"#; let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } // These tests are incorrect: their output is undefined as long as eth_getCompilers is []. @@ -788,7 +788,7 @@ fn rpc_eth_compilers() { let request = r#"{"jsonrpc": "2.0", "method": "eth_getCompilers", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[ignore] @@ -797,7 +797,7 @@ fn rpc_eth_compile_lll() { let request = r#"{"jsonrpc": "2.0", "method": "eth_compileLLL", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[ignore] @@ -806,7 +806,7 @@ fn rpc_eth_compile_solidity() { let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSolidity", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[ignore] @@ -815,7 +815,7 @@ fn rpc_eth_compile_serpent() { let request = r#"{"jsonrpc": "2.0", "method": "eth_compileSerpent", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#; - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -826,7 +826,7 @@ fn rpc_get_work_returns_no_work_if_cant_mine() { let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32001,"message":"Still syncing.","data":null},"id":1}"#; - assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(eth_tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -837,7 +837,7 @@ fn rpc_get_work_returns_correct_work_package() { let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["0x3bbe93f74e7b97ae00784aeff8819c5cb600dd87e8b282a5d3446f3f871f0347","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000","0x01"],"id":1}"#; - assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(eth_tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -851,7 +851,7 @@ fn rpc_get_work_should_not_return_block_number() { let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["0x3bbe93f74e7b97ae00784aeff8819c5cb600dd87e8b282a5d3446f3f871f0347","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000"],"id":1}"#; - assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(eth_tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -867,7 +867,7 @@ fn rpc_get_work_should_timeout() { r#"{{"jsonrpc":"2.0","result":["0x{:?}","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000","0x01"],"id":1}}"#, hash, ); - assert_eq!(eth_tester.io.handle_request(request), Some(work_response.to_owned())); + assert_eq!(eth_tester.io.handle_request_sync(request), Some(work_response.to_owned())); // Request with timeout of 0 seconds. This should work since we're disabling timeout. let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": ["0"], "id": 1}"#; @@ -875,14 +875,14 @@ fn rpc_get_work_should_timeout() { r#"{{"jsonrpc":"2.0","result":["0x{:?}","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000","0x01"],"id":1}}"#, hash, ); - assert_eq!(eth_tester.io.handle_request(request), Some(work_response.to_owned())); + assert_eq!(eth_tester.io.handle_request_sync(request), Some(work_response.to_owned())); // Request with timeout of 10K seconds. This should work. let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": ["10000"], "id": 1}"#; - assert_eq!(eth_tester.io.handle_request(request), Some(work_response.to_owned())); + assert_eq!(eth_tester.io.handle_request_sync(request), Some(work_response.to_owned())); // Request with timeout of 10 seconds. This should fail. let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": ["10"], "id": 1}"#; let err_response = r#"{"jsonrpc":"2.0","error":{"code":-32003,"message":"Work has not changed.","data":null},"id":1}"#; - assert_eq!(eth_tester.io.handle_request(request), Some(err_response.to_owned())); + assert_eq!(eth_tester.io.handle_request_sync(request), Some(err_response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs index 96cb1ec92..e9316da61 100644 --- a/rpc/src/v1/tests/mocked/eth_signing.rs +++ b/rpc/src/v1/tests/mocked/eth_signing.rs @@ -16,13 +16,13 @@ use std::str::FromStr; use std::sync::Arc; -use std::time::Duration; use jsonrpc_core::{IoHandler, to_value}; use v1::impls::EthSigningQueueClient; use v1::traits::EthSigning; use v1::helpers::{ConfirmationsQueue, SigningQueue}; +use v1::types::{H256 as RpcH256, H520 as RpcH520}; use v1::tests::helpers::TestMinerService; -use util::{Address, FixedHash, Uint, U256, H256}; +use util::{Address, FixedHash, Uint, U256, H256, H520}; use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; use ethcore::transaction::{Transaction, Action}; @@ -37,7 +37,7 @@ struct EthSigningTester { impl Default for EthSigningTester { fn default() -> Self { - let queue = Arc::new(ConfirmationsQueue::with_timeout(Duration::from_millis(1))); + let queue = Arc::new(ConfirmationsQueue::default()); let client = Arc::new(TestBlockChainClient::default()); let miner = Arc::new(TestMinerService::default()); let accounts = Arc::new(AccountProvider::transient_provider()); @@ -78,8 +78,13 @@ fn should_add_sign_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + let async_result = tester.io.handle_request(&request).unwrap(); assert_eq!(tester.queue.requests().len(), 1); + // respond + tester.queue.request_confirmed(U256::from(1), Ok(to_value(&RpcH520::from(H520::default())))); + assert!(async_result.on_result(move |res| { + assert_eq!(res, response.to_owned()); + })); } #[test] @@ -102,7 +107,7 @@ fn should_post_sign_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x01","id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); assert_eq!(tester.queue.requests().len(), 1); } @@ -120,7 +125,7 @@ fn should_check_status_of_request() { ], "id": 1 }"#; - tester.io.handle_request(&request).expect("Sent"); + tester.io.handle_request_sync(&request).expect("Sent"); // when let request = r#"{ @@ -132,7 +137,7 @@ fn should_check_status_of_request() { let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); } #[test] @@ -149,8 +154,8 @@ fn should_check_status_of_request_when_its_resolved() { ], "id": 1 }"#; - tester.io.handle_request(&request).expect("Sent"); - tester.queue.request_confirmed(U256::from(1), to_value(&"Hello World!")); + tester.io.handle_request_sync(&request).expect("Sent"); + tester.queue.request_confirmed(U256::from(1), Ok(to_value(&"Hello World!"))); // when let request = r#"{ @@ -162,7 +167,7 @@ fn should_check_status_of_request_when_its_resolved() { let response = r#"{"jsonrpc":"2.0","result":"Hello World!","id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); } #[test] @@ -186,7 +191,7 @@ fn should_sign_if_account_is_unlocked() { "id": 1 }"#; let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{}", signature).as_ref() + r#"","id":1}"#; - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); assert_eq!(tester.queue.requests().len(), 0); } @@ -213,8 +218,13 @@ fn should_add_transaction_to_queue() { let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + let async_result = tester.io.handle_request(&request).unwrap(); assert_eq!(tester.queue.requests().len(), 1); + // respond + tester.queue.request_confirmed(U256::from(1), Ok(to_value(&RpcH256::from(H256::default())))); + assert!(async_result.on_result(move |res| { + assert_eq!(res, response.to_owned()); + })); } #[test] @@ -251,5 +261,5 @@ fn should_dispatch_transaction_if_account_is_unlock() { let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs index cf7bb8eb1..056bdf25d 100644 --- a/rpc/src/v1/tests/mocked/ethcore.rs +++ b/rpc/src/v1/tests/mocked/ethcore.rs @@ -80,7 +80,7 @@ fn rpc_ethcore_extra_data() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_extraData", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x01020304","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -98,7 +98,7 @@ fn rpc_ethcore_default_extra_data() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_defaultExtraData", "params": [], "id": 1}"#; let response = format!(r#"{{"jsonrpc":"2.0","result":"0x{}","id":1}}"#, misc::version_data().to_hex()); - assert_eq!(io.handle_request(request), Some(response)); + assert_eq!(io.handle_request_sync(request), Some(response)); } #[test] @@ -113,7 +113,7 @@ fn rpc_ethcore_gas_floor_target() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_gasFloorTarget", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x3039","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -128,7 +128,7 @@ fn rpc_ethcore_min_gas_price() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_minGasPrice", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x01312d00","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -147,7 +147,7 @@ fn rpc_ethcore_dev_logs() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogs", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["b","a"],"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -162,7 +162,7 @@ fn rpc_ethcore_dev_logs_levels() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"rpc=trace","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -177,7 +177,7 @@ fn rpc_ethcore_transactions_limit() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_transactionsLimit", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":1024,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -192,7 +192,7 @@ fn rpc_ethcore_net_chain() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netChain", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"testchain","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -207,7 +207,7 @@ fn rpc_ethcore_net_peers() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPeers", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"active":0,"connected":120,"max":50},"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -222,7 +222,7 @@ fn rpc_ethcore_net_port() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPort", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":30303,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -237,7 +237,7 @@ fn rpc_ethcore_rpc_settings() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_rpcSettings", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"enabled":true,"interface":"all","port":8545},"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -252,7 +252,7 @@ fn rpc_ethcore_node_name() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_nodeName", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"mynode","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -269,7 +269,7 @@ fn rpc_ethcore_unsigned_transactions_count() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":0,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -284,5 +284,5 @@ fn rpc_ethcore_unsigned_transactions_count_when_signer_disabled() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/ethcore_set.rs b/rpc/src/v1/tests/mocked/ethcore_set.rs index 2582b85b7..eaa4cb0cb 100644 --- a/rpc/src/v1/tests/mocked/ethcore_set.rs +++ b/rpc/src/v1/tests/mocked/ethcore_set.rs @@ -53,7 +53,7 @@ fn rpc_ethcore_set_min_gas_price() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(miner.minimal_gas_price(), U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); } @@ -68,7 +68,7 @@ fn rpc_ethcore_set_gas_floor_target() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(miner.gas_floor_target(), U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); } @@ -83,7 +83,7 @@ fn rpc_ethcore_set_extra_data() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(miner.extra_data(), "cd1722f3947def4cf144679da39c4c32bdc35681".from_hex().unwrap()); } @@ -98,7 +98,7 @@ fn rpc_ethcore_set_author() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(miner.author(), Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); } @@ -113,6 +113,6 @@ fn rpc_ethcore_set_transactions_limit() { let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(miner.transactions_limit(), 10_240_240); } diff --git a/rpc/src/v1/tests/mocked/net.rs b/rpc/src/v1/tests/mocked/net.rs index 836246686..3bc341dcb 100644 --- a/rpc/src/v1/tests/mocked/net.rs +++ b/rpc/src/v1/tests/mocked/net.rs @@ -36,7 +36,7 @@ fn rpc_net_version() { let request = r#"{"jsonrpc": "2.0", "method": "net_version", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"3","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -49,7 +49,7 @@ fn rpc_net_peer_count() { let request = r#"{"jsonrpc": "2.0", "method": "net_peerCount", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x78","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -62,5 +62,5 @@ fn rpc_net_listening() { let request = r#"{"jsonrpc": "2.0", "method": "net_listening", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 3c6a28d74..aa4bf29c1 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -76,7 +76,7 @@ fn should_return_false_if_signer_is_disabled() { // then - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -90,7 +90,7 @@ fn should_return_port_number_if_signer_is_enabled() { // then - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -100,7 +100,7 @@ fn accounts() { let request = r#"{"jsonrpc": "2.0", "method": "personal_listAccounts", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:?}", address) + r#""],"id":1}"#; - assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -108,7 +108,7 @@ fn new_account() { let tester = setup(None); let request = r#"{"jsonrpc": "2.0", "method": "personal_newAccount", "params": ["pass"], "id": 1}"#; - let res = tester.io.handle_request(request); + let res = tester.io.handle_request_sync(request); let accounts = tester.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 1); @@ -131,7 +131,7 @@ fn should_be_able_to_get_account_info() { tester.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap(); let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#; - let res = tester.io.handle_request(request); + let res = tester.io.handle_request_sync(request); let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid); assert_eq!(res, Some(response)); } @@ -146,13 +146,13 @@ fn should_be_able_to_set_name() { let request = format!(r#"{{"jsonrpc": "2.0", "method": "personal_setAccountName", "params": ["0x{}", "Test"], "id": 1}}"#, address.hex()); let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; - let res = tester.io.handle_request(&request); + let res = tester.io.handle_request_sync(&request); assert_eq!(res, Some(response.into())); let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone(); let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#; - let res = tester.io.handle_request(request); + let res = tester.io.handle_request_sync(request); let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid); assert_eq!(res, Some(response)); } @@ -167,13 +167,13 @@ fn should_be_able_to_set_meta() { let request = format!(r#"{{"jsonrpc": "2.0", "method": "personal_setAccountMeta", "params": ["0x{}", "{{foo: 69}}"], "id": 1}}"#, address.hex()); let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; - let res = tester.io.handle_request(&request); + let res = tester.io.handle_request_sync(&request); assert_eq!(res, Some(response.into())); let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone(); let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#; - let res = tester.io.handle_request(request); + let res = tester.io.handle_request_sync(request); let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"{}\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid, uuid); assert_eq!(res, Some(response)); } @@ -197,7 +197,7 @@ fn sign_and_send_transaction_with_invalid_password() { let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidPassword)"},"id":1}"#; - assert_eq!(tester.io.handle_request(request.as_ref()), Some(response.into())); + assert_eq!(tester.io.handle_request_sync(request.as_ref()), Some(response.into())); } #[test] @@ -232,7 +232,7 @@ fn sign_and_send_transaction() { let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; - assert_eq!(tester.io.handle_request(request.as_ref()), Some(response)); + assert_eq!(tester.io.handle_request_sync(request.as_ref()), Some(response)); tester.miner.last_nonces.write().insert(address.clone(), U256::zero()); @@ -250,5 +250,5 @@ fn sign_and_send_transaction() { let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; - assert_eq!(tester.io.handle_request(request.as_ref()), Some(response)); + assert_eq!(tester.io.handle_request_sync(request.as_ref()), Some(response)); } diff --git a/rpc/src/v1/tests/mocked/personal_signer.rs b/rpc/src/v1/tests/mocked/personal_signer.rs index 9410ab84e..eacbf2404 100644 --- a/rpc/src/v1/tests/mocked/personal_signer.rs +++ b/rpc/src/v1/tests/mocked/personal_signer.rs @@ -79,8 +79,8 @@ fn should_return_list_of_items_to_confirm() { value: U256::from(1), data: vec![], nonce: None, - })); - tester.queue.add_request(ConfirmationPayload::Sign(1.into(), 5.into())); + })).unwrap(); + tester.queue.add_request(ConfirmationPayload::Sign(1.into(), 5.into())).unwrap(); // when let request = r#"{"jsonrpc":"2.0","method":"personal_requestsToConfirm","params":[],"id":1}"#; @@ -92,7 +92,7 @@ fn should_return_list_of_items_to_confirm() { ); // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); } @@ -108,7 +108,7 @@ fn should_reject_transaction_from_queue_without_dispatching() { value: U256::from(1), data: vec![], nonce: None, - })); + })).unwrap(); assert_eq!(tester.queue.requests().len(), 1); // when @@ -116,7 +116,7 @@ fn should_reject_transaction_from_queue_without_dispatching() { let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); assert_eq!(tester.queue.requests().len(), 0); assert_eq!(tester.miner.imported_transactions.lock().len(), 0); } @@ -133,7 +133,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { value: U256::from(1), data: vec![], nonce: None, - })); + })).unwrap(); assert_eq!(tester.queue.requests().len(), 1); // when @@ -141,7 +141,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidAccount)"},"id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); assert_eq!(tester.queue.requests().len(), 1); } @@ -149,7 +149,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { fn should_not_remove_sign_if_password_is_invalid() { // given let tester = signer_tester(); - tester.queue.add_request(ConfirmationPayload::Sign(0.into(), 5.into())); + tester.queue.add_request(ConfirmationPayload::Sign(0.into(), 5.into())).unwrap(); assert_eq!(tester.queue.requests().len(), 1); // when @@ -157,7 +157,7 @@ fn should_not_remove_sign_if_password_is_invalid() { let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidAccount)"},"id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); assert_eq!(tester.queue.requests().len(), 1); } @@ -175,7 +175,7 @@ fn should_confirm_transaction_and_dispatch() { value: U256::from(1), data: vec![], nonce: None, - })); + })).unwrap(); let t = Transaction { nonce: U256::zero(), @@ -201,7 +201,7 @@ fn should_confirm_transaction_and_dispatch() { let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; // then - assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned())); assert_eq!(tester.queue.requests().len(), 0); assert_eq!(tester.miner.imported_transactions.lock().len(), 1); } diff --git a/rpc/src/v1/tests/mocked/rpc.rs b/rpc/src/v1/tests/mocked/rpc.rs index 4415f39e5..b2c340d94 100644 --- a/rpc/src/v1/tests/mocked/rpc.rs +++ b/rpc/src/v1/tests/mocked/rpc.rs @@ -36,7 +36,7 @@ fn modules() { let request = r#"{"jsonrpc": "2.0", "method": "modules", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"rpc":"1.0","web3":"1.0"},"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -48,5 +48,5 @@ fn rpc_modules() { let request = r#"{"jsonrpc": "2.0", "method": "rpc_modules", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"ethcore":"1.0","rpc":"1.0","web3":"1.0"},"id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/rpc/src/v1/tests/mocked/web3.rs b/rpc/src/v1/tests/mocked/web3.rs index bb77b24a2..b9f80b0a8 100644 --- a/rpc/src/v1/tests/mocked/web3.rs +++ b/rpc/src/v1/tests/mocked/web3.rs @@ -29,7 +29,7 @@ fn rpc_web3_version() { let request = r#"{"jsonrpc": "2.0", "method": "web3_clientVersion", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"VER","id":1}"#.to_owned().replace("VER", v.as_ref()); - assert_eq!(io.handle_request(request), Some(response)); + assert_eq!(io.handle_request_sync(request), Some(response)); } #[test] @@ -41,7 +41,7 @@ fn rpc_web3_sha3() { let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x00"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } #[test] @@ -53,5 +53,5 @@ fn rpc_web3_sha3_wiki() { let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x68656c6c6f20776f726c64"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad","id":1}"#; - assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 60b482916..610591f1f 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -204,7 +204,7 @@ pub trait EthFilter: Sized + Send + Sync + 'static { /// Signing methods implementation relying on unlocked accounts. pub trait EthSigning: Sized + Send + Sync + 'static { /// Signs the data with given address signature. - fn sign(&self, _: Params) -> Result; + fn sign(&self, _: Params, _: Ready); /// Posts sign request asynchronously. /// Will return a confirmation ID for later use with check_transaction. @@ -214,7 +214,7 @@ pub trait EthSigning: Sized + Send + Sync + 'static { /// transaction hash. /// If it cannot yet be signed, it will return a transaction ID for /// later use with check_transaction. - fn send_transaction(&self, _: Params) -> Result; + fn send_transaction(&self, _: Params, _: Ready); /// Posts transaction asynchronously. /// Will return a transaction ID for later use with check_transaction. @@ -230,8 +230,8 @@ pub trait EthSigning: Sized + Send + Sync + 'static { /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); - delegate.add_method("eth_sign", EthSigning::sign); - delegate.add_method("eth_sendTransaction", EthSigning::send_transaction); + delegate.add_async_method("eth_sign", EthSigning::sign); + delegate.add_async_method("eth_sendTransaction", EthSigning::send_transaction); delegate.add_method("eth_postSign", EthSigning::post_sign); delegate.add_method("eth_postTransaction", EthSigning::post_transaction); delegate.add_method("eth_checkRequest", EthSigning::check_request); diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index f4380b0a3..cee96e0c7 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -549,7 +549,7 @@ mod tests { block_hash: H256::from(14), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"action":{"call":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x06","gas":"0x07","input":"0x1234","callType":{"call":[]}}},"result":{"call":{"gasUsed":"0x08","output":"0x5678"}},"traceAddress":["0x0a"],"subtraces":"0x01","transactionPosition":"0x0b","transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":"0x0d","blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"action":{"call":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x06","gas":"0x07","input":"0x1234","callType":"call"}},"result":{"call":{"gasUsed":"0x08","output":"0x5678"}},"traceAddress":["0x0a"],"subtraces":"0x01","transactionPosition":"0x0b","transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":"0x0d","blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] @@ -614,7 +614,7 @@ mod tests { } ]); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"0x000000000000000000000000000000000000002a":{"balance":{"=":[]},"nonce":{"+":"0x01"},"code":{"=":[]},"storage":{"0x000000000000000000000000000000000000000000000000000000000000002a":{"=":[]}}},"0x0000000000000000000000000000000000000045":{"balance":{"=":[]},"nonce":{"*":{"from":"0x01","to":"0x00"}},"code":{"-":"0x60"},"storage":{}}}"#); + assert_eq!(serialized, r#"{"0x000000000000000000000000000000000000002a":{"balance":"=","nonce":{"+":"0x01"},"code":"=","storage":{"0x000000000000000000000000000000000000000000000000000000000000002a":"="}},"0x0000000000000000000000000000000000000045":{"balance":"=","nonce":{"*":{"from":"0x01","to":"0x00"}},"code":{"-":"0x60"},"storage":{}}}"#); } #[test] @@ -634,7 +634,7 @@ mod tests { })]; let serialized = serde_json::to_string(&actions).unwrap(); - assert_eq!(serialized, r#"[{"call":{"from":"0x0000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000002","value":"0x03","gas":"0x04","input":"0x1234","callType":{"call":[]}}},{"create":{"from":"0x0000000000000000000000000000000000000005","value":"0x06","gas":"0x07","init":"0x5678"}}]"#); + assert_eq!(serialized, r#"[{"call":{"from":"0x0000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000002","value":"0x03","gas":"0x04","input":"0x1234","callType":"call"}},{"create":{"from":"0x0000000000000000000000000000000000000005","value":"0x06","gas":"0x07","init":"0x5678"}}]"#); } #[test] @@ -654,6 +654,6 @@ mod tests { ]; let serialized = serde_json::to_string(&results).unwrap(); - assert_eq!(serialized, r#"[{"call":{"gasUsed":"0x01","output":"0x1234"}},{"create":{"gasUsed":"0x02","code":"0x4556","address":"0x0000000000000000000000000000000000000003"}},{"failedCall":[]},{"failedCreate":[]}]"#); + assert_eq!(serialized, r#"[{"call":{"gasUsed":"0x01","output":"0x1234"}},{"create":{"gasUsed":"0x02","code":"0x4556","address":"0x0000000000000000000000000000000000000003"}},"failedCall","failedCreate"]"#); } } diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 5bb6325f1..a8ad0582c 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -12,7 +12,7 @@ rustc_version = "0.1" [dependencies] rand = "0.3.14" -jsonrpc-core = "2.1" +jsonrpc-core = "3.0" log = "0.3" env_logger = "0.3" ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "mio-upstream-stable" } diff --git a/signer/src/ws_server/session.rs b/signer/src/ws_server/session.rs index e7abea833..d2d336d87 100644 --- a/signer/src/ws_server/session.rs +++ b/signer/src/ws_server/session.rs @@ -22,7 +22,7 @@ use std::path::{PathBuf, Path}; use std::sync::Arc; use std::str::FromStr; use jsonrpc_core::IoHandler; -use util::H256; +use util::{H256, Mutex}; #[cfg(feature = "ui")] mod signer { @@ -95,7 +95,7 @@ fn add_headers(mut response: ws::Response, mime: &str) -> ws::Response { } pub struct Session { - out: ws::Sender, + out: Arc>, skip_origin_validation: bool, self_origin: String, authcodes_path: PathBuf, @@ -145,12 +145,16 @@ impl ws::Handler for Session { fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> { let req = try!(msg.as_text()); - match self.handler.handle_request(req) { - Some(res) => { - self.out.send(res) - }, - None => Ok(()), + if let Some(async) = self.handler.handle_request(req) { + let out = self.out.clone(); + async.on_result(move |result| { + let res = out.lock().send(result); + if let Err(e) = res { + warn!(target: "signer", "Error while sending response: {:?}", e); + } + }); } + Ok(()) } } @@ -177,7 +181,7 @@ impl ws::Factory for Factory { fn connection_made(&mut self, sender: ws::Sender) -> Self::Handler { Session { - out: sender, + out: Arc::new(Mutex::new(sender)), handler: self.handler.clone(), skip_origin_validation: self.skip_origin_validation, self_origin: self.self_origin.clone(), diff --git a/stratum/Cargo.toml b/stratum/Cargo.toml index 958e807be..d300106aa 100644 --- a/stratum/Cargo.toml +++ b/stratum/Cargo.toml @@ -12,7 +12,7 @@ ethcore-ipc-codegen = { path = "../ipc/codegen" } [dependencies] log = "0.3" json-tcp-server = { git = "https://github.com/ethcore/json-tcp-server" } -jsonrpc-core = "2.1" +jsonrpc-core = "3.0" mio = { git = "https://github.com/ethcore/mio", branch = "v0.5.x" } ethcore-util = { path = "../util" } ethcore-devtools = { path = "../devtools" } diff --git a/stratum/src/lib.rs b/stratum/src/lib.rs index c54eeea62..ecec535c2 100644 --- a/stratum/src/lib.rs +++ b/stratum/src/lib.rs @@ -108,15 +108,15 @@ impl Stratum { Ok(val) => val, Err(e) => { warn!(target: "stratum", "Invalid payload: '{}' ({:?})", &initial, e); - try!(to_value(&[0u8; 0])) + to_value(&[0u8; 0]) }, }, - None => try!(to_value(&[0u8; 0])), + None => to_value(&[0u8; 0]), }) } fn authorize(&self, params: Params) -> std::result::Result { - from_params::<(String, String)>(params).and_then(|(worker_id, secret)|{ + from_params::<(String, String)>(params).map(|(worker_id, secret)|{ if let Some(valid_secret) = self.secret { let hash = secret.sha3(); if hash != valid_secret { diff --git a/test.sh b/test.sh index 666f10d06..a873d870b 100755 --- a/test.sh +++ b/test.sh @@ -2,17 +2,22 @@ # Running Parity Full Test Sute FEATURES="json-tests ipc" +OPTIONS="--release" case $1 in --no-json) FEATURES="ipc" shift # past argument=value ;; + --no-release) + OPTIONS="" + shift + ;; *) # unknown option ;; esac . ./scripts/targets.sh -cargo test --release --features "$FEATURES" $TARGETS $1 \ +cargo test $OPTIONS --features "$FEATURES" $TARGETS $1 \