diff --git a/devtools/src/lib.rs b/devtools/src/lib.rs index f310cca30..3ab585d93 100644 --- a/devtools/src/lib.rs +++ b/devtools/src/lib.rs @@ -20,5 +20,7 @@ extern crate rand; pub mod random_path; +pub mod test_socket; pub use random_path::*; +pub use test_socket::*; diff --git a/ipc/tests/socket.rs b/devtools/src/test_socket.rs similarity index 100% rename from ipc/tests/socket.rs rename to devtools/src/test_socket.rs diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 0081cdf1e..fe26846c7 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -905,7 +905,7 @@ mod tests { gas: U256::from(100_000), gas_price: U256::zero(), nonce: U256::zero() - }.fake_sign(); + }.invalid_sign(); let mut state_result = get_temp_state(); let mut state = state_result.reference_mut(); let mut info = EnvInfo::default(); diff --git a/ethcore/src/transaction.rs b/ethcore/src/transaction.rs index a51824494..02507da21 100644 --- a/ethcore/src/transaction.rs +++ b/ethcore/src/transaction.rs @@ -134,7 +134,7 @@ impl Transaction { /// Useful for test incorrectly signed transactions. #[cfg(test)] - pub fn fake_sign(self) -> SignedTransaction { + pub fn invalid_sign(self) -> SignedTransaction { SignedTransaction { unsigned: self, r: U256::zero(), @@ -145,6 +145,18 @@ impl Transaction { } } + /// Specify the sender; this won't survive the serialize/deserialize process, but can be cloned. + pub fn fake_sign(self, from: Address) -> SignedTransaction { + SignedTransaction { + unsigned: self, + r: U256::zero(), + s: U256::zero(), + v: 0, + hash: Cell::new(None), + sender: Cell::new(Some(from)), + } + } + /// Get the transaction cost in gas for the given params. pub fn gas_required_for(is_create: bool, data: &[u8], schedule: &Schedule) -> u64 { data.iter().fold( @@ -342,3 +354,19 @@ fn signing() { }.sign(&key.secret()); assert_eq!(Address::from(key.public().sha3()), t.sender().unwrap()); } + +#[test] +fn fake_signing() { + let t = Transaction { + action: Action::Create, + nonce: U256::from(42), + gas_price: U256::from(3000), + gas: U256::from(50_000), + value: U256::from(1), + data: b"Hello!".to_vec() + }.fake_sign(Address::from(0x69)); + assert_eq!(Address::from(0x69), t.sender().unwrap()); + + let t = t.clone(); + assert_eq!(Address::from(0x69), t.sender().unwrap()); +} diff --git a/ipc/tests/Cargo.toml b/ipc/tests/Cargo.toml index a4d07ae57..1d2bc35b4 100644 --- a/ipc/tests/Cargo.toml +++ b/ipc/tests/Cargo.toml @@ -11,6 +11,7 @@ path = "run.rs" "ethcore-ipc" = { path = "../rpc" } bincode = "*" serde = "0.7.0" +ethcore-devtools = { path = "../../devtools" } [build-dependencies] syntex = "0.30.0" diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index 5a6fc69bf..280e25d08 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -17,9 +17,9 @@ #[cfg(test)] mod tests { - use super::super::socket::*; use super::super::service::*; use ipc::*; + use devtools::*; #[test] fn call_service() { diff --git a/ipc/tests/run.rs b/ipc/tests/run.rs index 187b52d9d..7aac809ed 100644 --- a/ipc/tests/run.rs +++ b/ipc/tests/run.rs @@ -17,7 +17,7 @@ extern crate bincode; extern crate ethcore_ipc as ipc; extern crate serde; +extern crate ethcore_devtools as devtools; -pub mod socket; pub mod service; mod examples; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index ed800d829..2a27764bc 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -24,7 +24,6 @@ use jsonrpc_core::*; use util::numbers::*; use util::sha3::*; use util::rlp::{encode, UntrustedRlp, View}; -use util::crypto::KeyPair; use ethcore::client::*; use ethcore::block::IsBlock; use ethcore::views::*; @@ -35,6 +34,7 @@ use v1::traits::{Eth, EthFilter}; use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, TransactionRequest, CallRequest, OptionalValue, Index, Filter, Log, Receipt}; use v1::helpers::{PollFilter, PollManager, ExternalMinerService, ExternalMiner}; use util::keys::store::AccountProvider; +use serde; fn default_gas() -> U256 { U256::from(21_000) @@ -167,38 +167,42 @@ impl EthClient } } - fn sign_call(client: &Arc, accounts: &Arc, request: CallRequest) -> Option { - match request.from { - Some(ref from) => { - let transaction = EthTransaction { - nonce: request.nonce.unwrap_or_else(|| client.nonce(from)), - action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or_else(default_gas), - gas_price: request.gas_price.unwrap_or_else(default_gas_price), - value: request.value.unwrap_or_else(U256::zero), - data: request.data.map_or_else(Vec::new, |d| d.to_vec()) - }; - - accounts.account_secret(from).ok().map(|secret| transaction.sign(&secret)) - }, - None => { - let transaction = EthTransaction { - nonce: request.nonce.unwrap_or_else(U256::zero), - action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or_else(default_gas), - gas_price: request.gas_price.unwrap_or_else(default_gas_price), - value: request.value.unwrap_or_else(U256::zero), - data: request.data.map_or_else(Vec::new, |d| d.to_vec()) - }; - - KeyPair::create().ok().map(|kp| transaction.sign(kp.secret())) - } - } + fn sign_call(client: &Arc, request: CallRequest) -> SignedTransaction { + let from = request.from.unwrap_or(Address::zero()); + EthTransaction { + nonce: request.nonce.unwrap_or_else(|| client.nonce(&from)), + action: request.to.map_or(Action::Create, Action::Call), + gas: request.gas.unwrap_or_else(default_gas), + gas_price: request.gas_price.unwrap_or_else(default_gas_price), + value: request.value.unwrap_or_else(U256::zero), + data: request.data.map_or_else(Vec::new, |d| d.to_vec()) + }.fake_sign(from) } } const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6. +fn params_len(params: &Params) -> usize { + match params { + &Params::Array(ref vec) => vec.len(), + _ => 0, + } +} + +fn from_params_discard_second(params: Params) -> Result<(F,), Error> where F: serde::de::Deserialize { + match params_len(¶ms) { + 1 => from_params::<(F, )>(params), + _ => from_params::<(F, BlockNumber)>(params).map(|(f, _block_number)| (f, )), + } +} + +fn from_params_discard_third(params: Params) -> Result<(F1, F2,), Error> where F1: serde::de::Deserialize, F2: serde::de::Deserialize { + match params_len(¶ms) { + 2 => from_params::<(F1, F2, )>(params), + _ => from_params::<(F1, F2, BlockNumber)>(params).map(|(f1, f2, _block_number)| (f1, f2, )), + } +} + impl Eth for EthClient where C: BlockChainClient + 'static, S: SyncProvider + 'static, @@ -278,19 +282,18 @@ impl Eth for EthClient } fn balance(&self, params: Params) -> Result { - from_params::<(Address, BlockNumber)>(params) - .and_then(|(address, _block_number)| to_value(&take_weak!(self.client).balance(&address))) + from_params_discard_second(params).and_then(|(address, )| + to_value(&take_weak!(self.client).balance(&address))) } fn storage_at(&self, params: Params) -> Result { - from_params::<(Address, U256, BlockNumber)>(params) - .and_then(|(address, position, _block_number)| - to_value(&U256::from(take_weak!(self.client).storage_at(&address, &H256::from(position))))) + from_params_discard_third::(params).and_then(|(address, position, )| + to_value(&U256::from(take_weak!(self.client).storage_at(&address, &H256::from(position))))) } fn transaction_count(&self, params: Params) -> Result { - from_params::<(Address, BlockNumber)>(params) - .and_then(|(address, _block_number)| to_value(&take_weak!(self.client).nonce(&address))) + from_params_discard_second(params).and_then(|(address, )| + to_value(&take_weak!(self.client).nonce(&address))) } fn block_transaction_count_by_hash(&self, params: Params) -> Result { @@ -329,9 +332,8 @@ impl Eth for EthClient // TODO: do not ignore block number param fn code_at(&self, params: Params) -> Result { - from_params::<(Address, BlockNumber)>(params) - .and_then(|(address, _block_number)| - to_value(&take_weak!(self.client).code(&address).map_or_else(Bytes::default, Bytes::new))) + from_params_discard_second(params).and_then(|(address, )| + to_value(&take_weak!(self.client).code(&address).map_or_else(Bytes::default, Bytes::new))) } fn block_by_hash(&self, params: Params) -> Result { @@ -506,31 +508,21 @@ impl Eth for EthClient } fn call(&self, params: Params) -> Result { - from_params::<(CallRequest, BlockNumber)>(params) - .and_then(|(request, _block_number)| { - let client = take_weak!(self.client); - let accounts = take_weak!(self.accounts); - let signed = Self::sign_call(&client, &accounts, request); - let output = signed.map(|tx| client.call(&tx) - .map(|e| Bytes::new(e.output)) - .unwrap_or(Bytes::default())); - - to_value(&output) - }) + from_params_discard_second(params).and_then(|(request, )| { + let client = take_weak!(self.client); + let signed = Self::sign_call(&client, request); + let output = client.call(&signed).map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![])); + to_value(&output) + }) } fn estimate_gas(&self, params: Params) -> Result { - from_params::<(CallRequest, BlockNumber)>(params) - .and_then(|(request, _block_number)| { - let client = take_weak!(self.client); - let accounts = take_weak!(self.accounts); - let signed = Self::sign_call(&client, &accounts, request); - let output = signed.map(|tx| client.call(&tx) - .map(|e| e.gas_used + e.refunded) - .unwrap_or(U256::zero())); - - to_value(&output) - }) + from_params_discard_second(params).and_then(|(request, )| { + let client = take_weak!(self.client); + let signed = Self::sign_call(&client, request); + let used = client.call(&signed).map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0)); + to_value(&used) + }) } } diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 786b87a26..a4b0e4448 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -334,6 +334,38 @@ fn rpc_eth_call() { assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); } +#[test] +fn rpc_eth_call_default_block() { + let tester = EthTester::default(); + tester.client.set_execution_result(Executed { + gas: U256::zero(), + gas_used: U256::from(0xff30), + refunded: U256::from(0x5), + cumulative_gas_used: U256::zero(), + logs: vec![], + contracts_created: vec![], + output: vec![0x12, 0x34, 0xff], + trace: None, + }); + + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_call", + "params": [{ + "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }], + "id": 1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#; + + assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); +} + #[test] fn rpc_eth_estimate_gas() { let tester = EthTester::default(); @@ -367,6 +399,38 @@ fn rpc_eth_estimate_gas() { assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); } +#[test] +fn rpc_eth_estimate_gas_default_block() { + let tester = EthTester::default(); + tester.client.set_execution_result(Executed { + gas: U256::zero(), + gas_used: U256::from(0xff30), + refunded: U256::from(0x5), + cumulative_gas_used: U256::zero(), + logs: vec![], + contracts_created: vec![], + output: vec![0x12, 0x34, 0xff], + trace: None, + }); + + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_estimateGas", + "params": [{ + "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }], + "id": 1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#; + + assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); +} + #[test] #[ignore] fn rpc_eth_send_transaction() { @@ -476,7 +540,7 @@ fn rpc_eth_compile_serpent() { #[test] fn returns_no_work_if_cant_mine() { - let mut eth_tester = EthTester::default(); + let eth_tester = EthTester::default(); eth_tester.client.set_queue_size(10); let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; diff --git a/rpc/src/v1/tests/web3.rs b/rpc/src/v1/tests/web3.rs index 178dddfd7..bb77b24a2 100644 --- a/rpc/src/v1/tests/web3.rs +++ b/rpc/src/v1/tests/web3.rs @@ -38,8 +38,6 @@ fn rpc_web3_sha3() { let io = IoHandler::new(); io.add_delegate(web3); - let v = version().to_owned().replace("Parity/", "Parity//"); - let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x00"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a","id":1}"#; @@ -52,8 +50,6 @@ fn rpc_web3_sha3_wiki() { let io = IoHandler::new(); io.add_delegate(web3); - let v = version().to_owned().replace("Parity/", "Parity//"); - let request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x68656c6c6f20776f726c64"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad","id":1}"#; diff --git a/rpc/src/v1/types/call_request.rs b/rpc/src/v1/types/call_request.rs index a47d40eb3..045b1cd9b 100644 --- a/rpc/src/v1/types/call_request.rs +++ b/rpc/src/v1/types/call_request.rs @@ -35,9 +35,8 @@ mod tests { use std::str::FromStr; use rustc_serialize::hex::FromHex; use serde_json; - use util::numbers::{Uint, U256}; + use util::numbers::{U256}; use util::hash::Address; - use ethcore::transaction::{Transaction, Action}; use v1::types::Bytes; use super::*; diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index a9ed8a3f4..2623fd0ea 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -35,9 +35,8 @@ mod tests { use std::str::FromStr; use rustc_serialize::hex::FromHex; use serde_json; - use util::numbers::{Uint, U256}; + use util::numbers::{U256}; use util::hash::Address; - use ethcore::transaction::{Transaction, Action}; use v1::types::Bytes; use super::*; diff --git a/util/src/network/connection.rs b/util/src/network/connection.rs index a560c1a91..02c0e2cde 100644 --- a/util/src/network/connection.rs +++ b/util/src/network/connection.rs @@ -501,77 +501,10 @@ mod tests { use std::sync::*; use super::super::stats::*; use std::io::{Read, Write, Error, Cursor, ErrorKind}; - use std::cmp; use mio::{EventSet}; use std::collections::VecDeque; use bytes::*; - - struct TestSocket { - read_buffer: Vec, - write_buffer: Vec, - cursor: usize, - buf_size: usize, - } - - impl Default for TestSocket { - fn default() -> Self { - TestSocket::new() - } - } - - impl TestSocket { - fn new() -> Self { - TestSocket { - read_buffer: vec![], - write_buffer: vec![], - cursor: 0, - buf_size: 0, - } - } - - fn new_buf(buf_size: usize) -> TestSocket { - TestSocket { - read_buffer: vec![], - write_buffer: vec![], - cursor: 0, - buf_size: buf_size, - } - } - } - - impl Read for TestSocket { - fn read(&mut self, buf: &mut [u8]) -> Result { - let end_position = cmp::min(self.read_buffer.len(), self.cursor+buf.len()); - let len = cmp::max(end_position - self.cursor, 0); - match len { - 0 => Ok(0), - _ => { - for i in self.cursor..end_position { - buf[i-self.cursor] = self.read_buffer[i]; - } - self.cursor = self.cursor + buf.len(); - Ok(len) - } - } - } - } - - impl Write for TestSocket { - fn write(&mut self, buf: &[u8]) -> Result { - if self.buf_size == 0 || buf.len() < self.buf_size { - self.write_buffer.extend(buf.iter().cloned()); - Ok(buf.len()) - } - else { - self.write_buffer.extend(buf.iter().take(self.buf_size).cloned()); - Ok(self.buf_size) - } - } - - fn flush(&mut self) -> Result<(), Error> { - unimplemented!(); - } - } + use devtools::*; impl GenericSocket for TestSocket {}