diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index cdffe4302..8b942f777 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -257,7 +257,7 @@ pub fn get_temp_journal_db() -> GuardedTempResult> { } impl MiningBlockChainClient for TestBlockChainClient { - fn prepare_open_block(&self, _author: Address, _gas_range_target: (U256, U256), _extra_data: Bytes) -> OpenBlock { + fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { let engine = &self.spec.engine; let genesis_header = self.spec.genesis_header(); let mut db_result = get_temp_journal_db(); @@ -265,7 +265,7 @@ impl MiningBlockChainClient for TestBlockChainClient { self.spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; - OpenBlock::new( + let mut open_block = OpenBlock::new( engine.deref(), self.vm_factory(), Default::default(), @@ -273,10 +273,13 @@ impl MiningBlockChainClient for TestBlockChainClient { db, &genesis_header, last_hashes, - Address::zero(), - (3141562.into(), 31415620.into()), - vec![] - ).expect("Opening block for tests will not fail.") + author, + gas_range_target, + extra_data + ).expect("Opening block for tests will not fail."); + // TODO [todr] Override timestamp for predictability (set_timestamp_now kind of sucks) + open_block.set_timestamp(10_000_000); + open_block } fn vm_factory(&self) -> &EvmFactory { diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 66a59a86b..275d8a1a4 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -104,8 +104,8 @@ pub struct Dependencies { pub external_miner: Arc, pub logger: Arc, pub settings: Arc, - pub allow_pending_receipt_query: bool, pub net_service: Arc, + pub geth_compatibility: bool, } fn to_modules(apis: &[Api]) -> BTreeMap { @@ -163,7 +163,10 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet &deps.secret_store, &deps.miner, &deps.external_miner, - deps.allow_pending_receipt_query + EthClientOptions { + allow_pending_receipt_query: !deps.geth_compatibility, + send_block_number_in_get_work: !deps.geth_compatibility, + } ); server.add_delegate(client.to_delegate()); diff --git a/parity/run.rs b/parity/run.rs index 5db330708..6412d83ff 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -211,8 +211,8 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> { external_miner: external_miner.clone(), logger: logger.clone(), settings: Arc::new(cmd.net_settings.clone()), - allow_pending_receipt_query: !cmd.geth_compatibility, - net_service: manage_network.clone() + net_service: manage_network.clone(), + geth_compatibility: cmd.geth_compatibility, }); let dependencies = rpc::Dependencies { diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index f773429e8..c704650a3 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -47,6 +47,23 @@ use v1::helpers::CallRequest as CRequest; use v1::impls::{default_gas_price, dispatch_transaction, error_codes}; use serde; +/// Eth RPC options +pub struct EthClientOptions { + /// Returns receipt from pending blocks + pub allow_pending_receipt_query: bool, + /// Send additional block number when asking for work + pub send_block_number_in_get_work: bool, +} + +impl Default for EthClientOptions { + fn default() -> Self { + EthClientOptions { + allow_pending_receipt_query: true, + send_block_number_in_get_work: true, + } + } +} + /// Eth rpc implementation. pub struct EthClient where C: MiningBlockChainClient, @@ -60,7 +77,7 @@ pub struct EthClient where miner: Weak, external_miner: Arc, seed_compute: Mutex, - allow_pending_receipt_query: bool, + options: EthClientOptions, } impl EthClient where @@ -70,7 +87,7 @@ impl EthClient where EM: ExternalMinerService { /// Creates new EthClient. - pub fn new(client: &Arc, sync: &Arc, accounts: &Arc, miner: &Arc, em: &Arc, allow_pending_receipt_query: bool) + pub fn new(client: &Arc, sync: &Arc, accounts: &Arc, miner: &Arc, em: &Arc, options: EthClientOptions) -> EthClient { EthClient { client: Arc::downgrade(client), @@ -79,7 +96,7 @@ impl EthClient where accounts: Arc::downgrade(accounts), external_miner: em.clone(), seed_compute: Mutex::new(SeedHashCompute::new()), - allow_pending_receipt_query: allow_pending_receipt_query, + options: options, } } @@ -496,7 +513,7 @@ impl Eth for EthClient where let miner = take_weak!(self.miner); let hash: H256 = hash.into(); match miner.pending_receipts().get(&hash) { - Some(receipt) if self.allow_pending_receipt_query => to_value(&Receipt::from(receipt.clone())), + Some(receipt) if self.options.allow_pending_receipt_query => to_value(&Receipt::from(receipt.clone())), _ => { let client = take_weak!(self.client); let receipt = client.transaction_receipt(TransactionID::Hash(hash)); @@ -582,8 +599,13 @@ impl Eth for EthClient where let pow_hash = b.hash(); let target = Ethash::difficulty_to_boundary(b.block().header().difficulty()); let seed_hash = self.seed_compute.lock().get_seedhash(b.block().header().number()); - let block_number = RpcU256::from(b.block().header().number()); - to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target), block_number)) + + if self.options.send_block_number_in_get_work { + let block_number = RpcU256::from(b.block().header().number()); + to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target), block_number)) + } else { + to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target))) + } }).unwrap_or(Err(Error::internal_error())) // no work found. }, _ => Err(Error::invalid_params()) diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 8240e8c0c..a9dddf843 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -42,7 +42,7 @@ mod traces; mod rpc; pub use self::web3::Web3Client; -pub use self::eth::EthClient; +pub use self::eth::{EthClient, EthClientOptions}; pub use self::eth_filter::EthFilterClient; pub use self::eth_signing::{EthSigningUnsafeClient, EthSigningQueueClient}; pub use self::net::NetClient; diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 8656a4e49..7e871048e 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -121,7 +121,7 @@ impl EthTester { &account_provider, &miner_service, &external_miner, - true + Default::default(), ); let eth_sign = EthSigningUnsafeClient::new( &client, diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 3d83f934f..5cce14533 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -181,8 +181,9 @@ impl MinerService for TestMinerService { unimplemented!(); } - fn map_sealing_work(&self, _chain: &MiningBlockChainClient, _f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { - None + fn map_sealing_work(&self, chain: &MiningBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { + let open_block = chain.prepare_open_block(self.author(), *self.gas_range_target.write(), self.extra_data()); + Some(f(&open_block.close())) } fn transaction(&self, hash: &H256) -> Option { diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index e0c55f126..9e819c1b0 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -29,7 +29,7 @@ use ethcore::receipt::LocalizedReceipt; use ethcore::transaction::{Transaction, Action}; use ethcore::miner::{ExternalMiner, MinerService}; use ethsync::SyncState; -use v1::{Eth, EthClient, EthSigning, EthSigningUnsafeClient}; +use v1::{Eth, EthClient, EthClientOptions, EthSigning, EthSigningUnsafeClient}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; use rustc_serialize::hex::ToHex; @@ -64,13 +64,19 @@ struct EthTester { impl Default for EthTester { fn default() -> Self { + Self::new_with_options(Default::default()) + } +} + +impl EthTester { + pub fn new_with_options(options: EthClientOptions) -> Self { let client = blockchain_client(); let sync = sync_provider(); let ap = accounts_provider(); let miner = miner_service(); let hashrates = Arc::new(Mutex::new(HashMap::new())); let external_miner = Arc::new(ExternalMiner::new(hashrates.clone())); - let eth = EthClient::new(&client, &sync, &ap, &miner, &external_miner, true).to_delegate(); + let eth = EthClient::new(&client, &sync, &ap, &miner, &external_miner, options).to_delegate(); let sign = EthSigningUnsafeClient::new(&client, &ap, &miner).to_delegate(); let io = IoHandler::new(); io.add_delegate(eth); @@ -790,15 +796,26 @@ fn returns_no_work_if_cant_mine() { } #[test] -fn returns_error_if_can_mine_and_no_closed_block() { - use ethsync::{SyncState}; - +fn returns_correct_work_package() { let eth_tester = EthTester::default(); eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()); - eth_tester.sync.status.write().state = SyncState::Idle; let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":["0x3bbe93f74e7b97ae00784aeff8819c5cb600dd87e8b282a5d3446f3f871f0347","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000","0x01"],"id":1}"#; + + assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); +} + +#[test] +fn should_not_return_block_number() { + let eth_tester = EthTester::new_with_options(EthClientOptions { + allow_pending_receipt_query: true, + send_block_number_in_get_work: false, + }); + eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()); + + let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":["0x3bbe93f74e7b97ae00784aeff8819c5cb600dd87e8b282a5d3446f3f871f0347","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000"],"id":1}"#; assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); }