From 845fa97da1bcc9d55e33e0614eb0fe4fcc15c0c9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 26 Mar 2016 13:30:02 +0100 Subject: [PATCH] Fix eth_call so it doesn't need the secret of the sender. --- ethcore/src/executive.rs | 2 +- ethcore/src/transaction.rs | 30 +++++++++++++++++++- rpc/src/v1/impls/eth.rs | 58 +++++++++++--------------------------- rpc/src/v1/tests/eth.rs | 2 ++ 4 files changed, 49 insertions(+), 43 deletions(-) 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/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 13cc08996..e7710b6df 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::*; @@ -168,33 +167,16 @@ 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) } } @@ -533,12 +515,10 @@ impl Eth for EthClient fn call(&self, params: Params) -> Result { from_params_discard_second(params).and_then(|(request, )| { 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())); - + let signed = Self::sign_call(&client, request); + info!("call: signed={:?}", signed); + let output = client.call(&signed).map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![])); + info!("call: output={:?}", output); to_value(&output) }) } @@ -546,13 +526,9 @@ impl Eth for EthClient fn estimate_gas(&self, params: Params) -> Result { from_params_discard_second(params).and_then(|(request, )| { 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) + 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 5c94320e3..8b40ba65c 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -345,6 +345,7 @@ fn rpc_eth_call_default_block() { logs: vec![], contracts_created: vec![], output: vec![0x12, 0x34, 0xff], + trace: None, }); let request = r#"{ @@ -409,6 +410,7 @@ fn rpc_eth_estimate_gas_default_block() { logs: vec![], contracts_created: vec![], output: vec![0x12, 0x34, 0xff], + trace: None, }); let request = r#"{