Fix eth_call so it doesn't need the secret of the sender.

This commit is contained in:
Gav Wood 2016-03-26 13:30:02 +01:00
parent aaf04e793d
commit 845fa97da1
4 changed files with 49 additions and 43 deletions

View File

@ -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();

View File

@ -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());
}

View File

@ -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<C, S, A, M, EM> EthClient<C, S, A, M, EM>
}
}
fn sign_call(client: &Arc<C>, accounts: &Arc<A>, request: CallRequest) -> Option<SignedTransaction> {
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<C>, 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<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
fn call(&self, params: Params) -> Result<Value, Error> {
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<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
fn estimate_gas(&self, params: Params) -> Result<Value, Error> {
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)
})
}
}

View File

@ -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#"{