Merge pull request #829 from ethcore/optionalblocknumberinrpc-master
Make BlockNumber optional, fix eth_call
This commit is contained in:
commit
ff0e6eb0d5
@ -905,7 +905,7 @@ mod tests {
|
|||||||
gas: U256::from(100_000),
|
gas: U256::from(100_000),
|
||||||
gas_price: U256::zero(),
|
gas_price: U256::zero(),
|
||||||
nonce: U256::zero()
|
nonce: U256::zero()
|
||||||
}.fake_sign();
|
}.invalid_sign();
|
||||||
let mut state_result = get_temp_state();
|
let mut state_result = get_temp_state();
|
||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
let mut info = EnvInfo::default();
|
let mut info = EnvInfo::default();
|
||||||
|
@ -134,7 +134,7 @@ impl Transaction {
|
|||||||
|
|
||||||
/// Useful for test incorrectly signed transactions.
|
/// Useful for test incorrectly signed transactions.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn fake_sign(self) -> SignedTransaction {
|
pub fn invalid_sign(self) -> SignedTransaction {
|
||||||
SignedTransaction {
|
SignedTransaction {
|
||||||
unsigned: self,
|
unsigned: self,
|
||||||
r: U256::zero(),
|
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.
|
/// Get the transaction cost in gas for the given params.
|
||||||
pub fn gas_required_for(is_create: bool, data: &[u8], schedule: &Schedule) -> u64 {
|
pub fn gas_required_for(is_create: bool, data: &[u8], schedule: &Schedule) -> u64 {
|
||||||
data.iter().fold(
|
data.iter().fold(
|
||||||
@ -342,3 +354,19 @@ fn signing() {
|
|||||||
}.sign(&key.secret());
|
}.sign(&key.secret());
|
||||||
assert_eq!(Address::from(key.public().sha3()), t.sender().unwrap());
|
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());
|
||||||
|
}
|
||||||
|
@ -24,7 +24,6 @@ use jsonrpc_core::*;
|
|||||||
use util::numbers::*;
|
use util::numbers::*;
|
||||||
use util::sha3::*;
|
use util::sha3::*;
|
||||||
use util::rlp::{encode, UntrustedRlp, View};
|
use util::rlp::{encode, UntrustedRlp, View};
|
||||||
use util::crypto::KeyPair;
|
|
||||||
use ethcore::client::*;
|
use ethcore::client::*;
|
||||||
use ethcore::block::IsBlock;
|
use ethcore::block::IsBlock;
|
||||||
use ethcore::views::*;
|
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::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, TransactionRequest, CallRequest, OptionalValue, Index, Filter, Log, Receipt};
|
||||||
use v1::helpers::{PollFilter, PollManager, ExternalMinerService, ExternalMiner};
|
use v1::helpers::{PollFilter, PollManager, ExternalMinerService, ExternalMiner};
|
||||||
use util::keys::store::AccountProvider;
|
use util::keys::store::AccountProvider;
|
||||||
|
use serde;
|
||||||
|
|
||||||
fn default_gas() -> U256 {
|
fn default_gas() -> U256 {
|
||||||
U256::from(21_000)
|
U256::from(21_000)
|
||||||
@ -167,38 +167,42 @@ 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> {
|
fn sign_call(client: &Arc<C>, request: CallRequest) -> SignedTransaction {
|
||||||
match request.from {
|
let from = request.from.unwrap_or(Address::zero());
|
||||||
Some(ref from) => {
|
EthTransaction {
|
||||||
let transaction = EthTransaction {
|
nonce: request.nonce.unwrap_or_else(|| client.nonce(&from)),
|
||||||
nonce: request.nonce.unwrap_or_else(|| client.nonce(from)),
|
|
||||||
action: request.to.map_or(Action::Create, Action::Call),
|
action: request.to.map_or(Action::Create, Action::Call),
|
||||||
gas: request.gas.unwrap_or_else(default_gas),
|
gas: request.gas.unwrap_or_else(default_gas),
|
||||||
gas_price: request.gas_price.unwrap_or_else(default_gas_price),
|
gas_price: request.gas_price.unwrap_or_else(default_gas_price),
|
||||||
value: request.value.unwrap_or_else(U256::zero),
|
value: request.value.unwrap_or_else(U256::zero),
|
||||||
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
|
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
|
||||||
};
|
}.fake_sign(from)
|
||||||
|
|
||||||
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()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6.
|
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<F>(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<F1, F2>(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<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
||||||
where C: BlockChainClient + 'static,
|
where C: BlockChainClient + 'static,
|
||||||
S: SyncProvider + 'static,
|
S: SyncProvider + 'static,
|
||||||
@ -278,19 +282,18 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn balance(&self, params: Params) -> Result<Value, Error> {
|
fn balance(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(Address, BlockNumber)>(params)
|
from_params_discard_second(params).and_then(|(address, )|
|
||||||
.and_then(|(address, _block_number)| to_value(&take_weak!(self.client).balance(&address)))
|
to_value(&take_weak!(self.client).balance(&address)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn storage_at(&self, params: Params) -> Result<Value, Error> {
|
fn storage_at(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(Address, U256, BlockNumber)>(params)
|
from_params_discard_third::<Address, U256>(params).and_then(|(address, position, )|
|
||||||
.and_then(|(address, position, _block_number)|
|
|
||||||
to_value(&U256::from(take_weak!(self.client).storage_at(&address, &H256::from(position)))))
|
to_value(&U256::from(take_weak!(self.client).storage_at(&address, &H256::from(position)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transaction_count(&self, params: Params) -> Result<Value, Error> {
|
fn transaction_count(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(Address, BlockNumber)>(params)
|
from_params_discard_second(params).and_then(|(address, )|
|
||||||
.and_then(|(address, _block_number)| to_value(&take_weak!(self.client).nonce(&address)))
|
to_value(&take_weak!(self.client).nonce(&address)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_transaction_count_by_hash(&self, params: Params) -> Result<Value, Error> {
|
fn block_transaction_count_by_hash(&self, params: Params) -> Result<Value, Error> {
|
||||||
@ -329,8 +332,7 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
|||||||
|
|
||||||
// TODO: do not ignore block number param
|
// TODO: do not ignore block number param
|
||||||
fn code_at(&self, params: Params) -> Result<Value, Error> {
|
fn code_at(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(Address, BlockNumber)>(params)
|
from_params_discard_second(params).and_then(|(address, )|
|
||||||
.and_then(|(address, _block_number)|
|
|
||||||
to_value(&take_weak!(self.client).code(&address).map_or_else(Bytes::default, Bytes::new)))
|
to_value(&take_weak!(self.client).code(&address).map_or_else(Bytes::default, Bytes::new)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,30 +513,20 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, params: Params) -> Result<Value, Error> {
|
fn call(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(CallRequest, BlockNumber)>(params)
|
from_params_discard_second(params).and_then(|(request, )| {
|
||||||
.and_then(|(request, _block_number)| {
|
|
||||||
let client = take_weak!(self.client);
|
let client = take_weak!(self.client);
|
||||||
let accounts = take_weak!(self.accounts);
|
let signed = Self::sign_call(&client, request);
|
||||||
let signed = Self::sign_call(&client, &accounts, request);
|
let output = client.call(&signed).map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![]));
|
||||||
let output = signed.map(|tx| client.call(&tx)
|
|
||||||
.map(|e| Bytes::new(e.output))
|
|
||||||
.unwrap_or(Bytes::default()));
|
|
||||||
|
|
||||||
to_value(&output)
|
to_value(&output)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_gas(&self, params: Params) -> Result<Value, Error> {
|
fn estimate_gas(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(CallRequest, BlockNumber)>(params)
|
from_params_discard_second(params).and_then(|(request, )| {
|
||||||
.and_then(|(request, _block_number)| {
|
|
||||||
let client = take_weak!(self.client);
|
let client = take_weak!(self.client);
|
||||||
let accounts = take_weak!(self.accounts);
|
let signed = Self::sign_call(&client, request);
|
||||||
let signed = Self::sign_call(&client, &accounts, request);
|
let used = client.call(&signed).map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0));
|
||||||
let output = signed.map(|tx| client.call(&tx)
|
to_value(&used)
|
||||||
.map(|e| e.gas_used + e.refunded)
|
|
||||||
.unwrap_or(U256::zero()));
|
|
||||||
|
|
||||||
to_value(&output)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,6 +334,38 @@ fn rpc_eth_call() {
|
|||||||
assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
|
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]
|
#[test]
|
||||||
fn rpc_eth_estimate_gas() {
|
fn rpc_eth_estimate_gas() {
|
||||||
let tester = EthTester::default();
|
let tester = EthTester::default();
|
||||||
@ -367,6 +399,38 @@ fn rpc_eth_estimate_gas() {
|
|||||||
assert_eq!(tester.io.handle_request(request), Some(response.to_owned()));
|
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]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn rpc_eth_send_transaction() {
|
fn rpc_eth_send_transaction() {
|
||||||
@ -476,7 +540,7 @@ fn rpc_eth_compile_serpent() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn returns_no_work_if_cant_mine() {
|
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);
|
eth_tester.client.set_queue_size(10);
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
|
||||||
|
@ -38,8 +38,6 @@ fn rpc_web3_sha3() {
|
|||||||
let io = IoHandler::new();
|
let io = IoHandler::new();
|
||||||
io.add_delegate(web3);
|
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 request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x00"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a","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();
|
let io = IoHandler::new();
|
||||||
io.add_delegate(web3);
|
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 request = r#"{"jsonrpc": "2.0", "method": "web3_sha3", "params": ["0x68656c6c6f20776f726c64"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad","id":1}"#;
|
||||||
|
|
||||||
|
@ -35,9 +35,8 @@ mod tests {
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use rustc_serialize::hex::FromHex;
|
use rustc_serialize::hex::FromHex;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use util::numbers::{Uint, U256};
|
use util::numbers::{U256};
|
||||||
use util::hash::Address;
|
use util::hash::Address;
|
||||||
use ethcore::transaction::{Transaction, Action};
|
|
||||||
use v1::types::Bytes;
|
use v1::types::Bytes;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -35,9 +35,8 @@ mod tests {
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use rustc_serialize::hex::FromHex;
|
use rustc_serialize::hex::FromHex;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use util::numbers::{Uint, U256};
|
use util::numbers::{U256};
|
||||||
use util::hash::Address;
|
use util::hash::Address;
|
||||||
use ethcore::transaction::{Transaction, Action};
|
|
||||||
use v1::types::Bytes;
|
use v1::types::Bytes;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user