Merge remote-tracking branch 'origin/master' into bettermining

This commit is contained in:
Gav Wood 2016-03-26 23:35:51 +01:00
commit fc211f0934
13 changed files with 155 additions and 141 deletions

View File

@ -20,5 +20,7 @@
extern crate rand; extern crate rand;
pub mod random_path; pub mod random_path;
pub mod test_socket;
pub use random_path::*; pub use random_path::*;
pub use test_socket::*;

View File

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

View File

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

View File

@ -11,6 +11,7 @@ path = "run.rs"
"ethcore-ipc" = { path = "../rpc" } "ethcore-ipc" = { path = "../rpc" }
bincode = "*" bincode = "*"
serde = "0.7.0" serde = "0.7.0"
ethcore-devtools = { path = "../../devtools" }
[build-dependencies] [build-dependencies]
syntex = "0.30.0" syntex = "0.30.0"

View File

@ -17,9 +17,9 @@
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::super::socket::*;
use super::super::service::*; use super::super::service::*;
use ipc::*; use ipc::*;
use devtools::*;
#[test] #[test]
fn call_service() { fn call_service() {

View File

@ -17,7 +17,7 @@
extern crate bincode; extern crate bincode;
extern crate ethcore_ipc as ipc; extern crate ethcore_ipc as ipc;
extern crate serde; extern crate serde;
extern crate ethcore_devtools as devtools;
pub mod socket;
pub mod service; pub mod service;
mod examples; mod examples;

View File

@ -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(&params) {
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(&params) {
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)))
} }
@ -506,30 +508,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)
}) })
} }
} }

View File

@ -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}"#;

View File

@ -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}"#;

View File

@ -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::*;

View File

@ -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::*;

View File

@ -501,77 +501,10 @@ mod tests {
use std::sync::*; use std::sync::*;
use super::super::stats::*; use super::super::stats::*;
use std::io::{Read, Write, Error, Cursor, ErrorKind}; use std::io::{Read, Write, Error, Cursor, ErrorKind};
use std::cmp;
use mio::{EventSet}; use mio::{EventSet};
use std::collections::VecDeque; use std::collections::VecDeque;
use bytes::*; use bytes::*;
use devtools::*;
struct TestSocket {
read_buffer: Vec<u8>,
write_buffer: Vec<u8>,
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<usize, Error> {
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<usize, Error> {
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!();
}
}
impl GenericSocket for TestSocket {} impl GenericSocket for TestSocket {}