No block number in get work while in geth-compat mode. (#1821)

This commit is contained in:
Tomasz Drwięga 2016-08-03 15:31:00 +02:00 committed by Gav Wood
parent 6ba1e66d32
commit c5ffb5af79
8 changed files with 73 additions and 27 deletions

View File

@ -257,7 +257,7 @@ pub fn get_temp_journal_db() -> GuardedTempResult<Box<JournalDB>> {
} }
impl MiningBlockChainClient for TestBlockChainClient { 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 engine = &self.spec.engine;
let genesis_header = self.spec.genesis_header(); let genesis_header = self.spec.genesis_header();
let mut db_result = get_temp_journal_db(); 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()); self.spec.ensure_db_good(db.as_hashdb_mut());
let last_hashes = vec![genesis_header.hash()]; let last_hashes = vec![genesis_header.hash()];
OpenBlock::new( let mut open_block = OpenBlock::new(
engine.deref(), engine.deref(),
self.vm_factory(), self.vm_factory(),
Default::default(), Default::default(),
@ -273,10 +273,13 @@ impl MiningBlockChainClient for TestBlockChainClient {
db, db,
&genesis_header, &genesis_header,
last_hashes, last_hashes,
Address::zero(), author,
(3141562.into(), 31415620.into()), gas_range_target,
vec![] extra_data
).expect("Opening block for tests will not fail.") ).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 { fn vm_factory(&self) -> &EvmFactory {

View File

@ -104,8 +104,8 @@ pub struct Dependencies {
pub external_miner: Arc<ExternalMiner>, pub external_miner: Arc<ExternalMiner>,
pub logger: Arc<RotatingLogger>, pub logger: Arc<RotatingLogger>,
pub settings: Arc<NetworkSettings>, pub settings: Arc<NetworkSettings>,
pub allow_pending_receipt_query: bool,
pub net_service: Arc<ManageNetwork>, pub net_service: Arc<ManageNetwork>,
pub geth_compatibility: bool,
} }
fn to_modules(apis: &[Api]) -> BTreeMap<String, String> { fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
@ -163,7 +163,10 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
&deps.secret_store, &deps.secret_store,
&deps.miner, &deps.miner,
&deps.external_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()); server.add_delegate(client.to_delegate());

View File

@ -211,8 +211,8 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
external_miner: external_miner.clone(), external_miner: external_miner.clone(),
logger: logger.clone(), logger: logger.clone(),
settings: Arc::new(cmd.net_settings.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 { let dependencies = rpc::Dependencies {

View File

@ -47,6 +47,23 @@ use v1::helpers::CallRequest as CRequest;
use v1::impls::{default_gas_price, dispatch_transaction, error_codes}; use v1::impls::{default_gas_price, dispatch_transaction, error_codes};
use serde; 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. /// Eth rpc implementation.
pub struct EthClient<C, S: ?Sized, M, EM> where pub struct EthClient<C, S: ?Sized, M, EM> where
C: MiningBlockChainClient, C: MiningBlockChainClient,
@ -60,7 +77,7 @@ pub struct EthClient<C, S: ?Sized, M, EM> where
miner: Weak<M>, miner: Weak<M>,
external_miner: Arc<EM>, external_miner: Arc<EM>,
seed_compute: Mutex<SeedHashCompute>, seed_compute: Mutex<SeedHashCompute>,
allow_pending_receipt_query: bool, options: EthClientOptions,
} }
impl<C, S: ?Sized, M, EM> EthClient<C, S, M, EM> where impl<C, S: ?Sized, M, EM> EthClient<C, S, M, EM> where
@ -70,7 +87,7 @@ impl<C, S: ?Sized, M, EM> EthClient<C, S, M, EM> where
EM: ExternalMinerService { EM: ExternalMinerService {
/// Creates new EthClient. /// Creates new EthClient.
pub fn new(client: &Arc<C>, sync: &Arc<S>, accounts: &Arc<AccountProvider>, miner: &Arc<M>, em: &Arc<EM>, allow_pending_receipt_query: bool) pub fn new(client: &Arc<C>, sync: &Arc<S>, accounts: &Arc<AccountProvider>, miner: &Arc<M>, em: &Arc<EM>, options: EthClientOptions)
-> EthClient<C, S, M, EM> { -> EthClient<C, S, M, EM> {
EthClient { EthClient {
client: Arc::downgrade(client), client: Arc::downgrade(client),
@ -79,7 +96,7 @@ impl<C, S: ?Sized, M, EM> EthClient<C, S, M, EM> where
accounts: Arc::downgrade(accounts), accounts: Arc::downgrade(accounts),
external_miner: em.clone(), external_miner: em.clone(),
seed_compute: Mutex::new(SeedHashCompute::new()), seed_compute: Mutex::new(SeedHashCompute::new()),
allow_pending_receipt_query: allow_pending_receipt_query, options: options,
} }
} }
@ -496,7 +513,7 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
let miner = take_weak!(self.miner); let miner = take_weak!(self.miner);
let hash: H256 = hash.into(); let hash: H256 = hash.into();
match miner.pending_receipts().get(&hash) { 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 client = take_weak!(self.client);
let receipt = client.transaction_receipt(TransactionID::Hash(hash)); let receipt = client.transaction_receipt(TransactionID::Hash(hash));
@ -582,8 +599,13 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
let pow_hash = b.hash(); let pow_hash = b.hash();
let target = Ethash::difficulty_to_boundary(b.block().header().difficulty()); let target = Ethash::difficulty_to_boundary(b.block().header().difficulty());
let seed_hash = self.seed_compute.lock().get_seedhash(b.block().header().number()); let seed_hash = self.seed_compute.lock().get_seedhash(b.block().header().number());
if self.options.send_block_number_in_get_work {
let block_number = RpcU256::from(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)) 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. }).unwrap_or(Err(Error::internal_error())) // no work found.
}, },
_ => Err(Error::invalid_params()) _ => Err(Error::invalid_params())

View File

@ -42,7 +42,7 @@ mod traces;
mod rpc; mod rpc;
pub use self::web3::Web3Client; 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_filter::EthFilterClient;
pub use self::eth_signing::{EthSigningUnsafeClient, EthSigningQueueClient}; pub use self::eth_signing::{EthSigningUnsafeClient, EthSigningQueueClient};
pub use self::net::NetClient; pub use self::net::NetClient;

View File

@ -121,7 +121,7 @@ impl EthTester {
&account_provider, &account_provider,
&miner_service, &miner_service,
&external_miner, &external_miner,
true Default::default(),
); );
let eth_sign = EthSigningUnsafeClient::new( let eth_sign = EthSigningUnsafeClient::new(
&client, &client,

View File

@ -181,8 +181,9 @@ impl MinerService for TestMinerService {
unimplemented!(); unimplemented!();
} }
fn map_sealing_work<F, T>(&self, _chain: &MiningBlockChainClient, _f: F) -> Option<T> where F: FnOnce(&ClosedBlock) -> T { fn map_sealing_work<F, T>(&self, chain: &MiningBlockChainClient, f: F) -> Option<T> where F: FnOnce(&ClosedBlock) -> T {
None 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<SignedTransaction> { fn transaction(&self, hash: &H256) -> Option<SignedTransaction> {

View File

@ -29,7 +29,7 @@ use ethcore::receipt::LocalizedReceipt;
use ethcore::transaction::{Transaction, Action}; use ethcore::transaction::{Transaction, Action};
use ethcore::miner::{ExternalMiner, MinerService}; use ethcore::miner::{ExternalMiner, MinerService};
use ethsync::SyncState; use ethsync::SyncState;
use v1::{Eth, EthClient, EthSigning, EthSigningUnsafeClient}; use v1::{Eth, EthClient, EthClientOptions, EthSigning, EthSigningUnsafeClient};
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService};
use rustc_serialize::hex::ToHex; use rustc_serialize::hex::ToHex;
@ -64,13 +64,19 @@ struct EthTester {
impl Default for EthTester { impl Default for EthTester {
fn default() -> Self { fn default() -> Self {
Self::new_with_options(Default::default())
}
}
impl EthTester {
pub fn new_with_options(options: EthClientOptions) -> Self {
let client = blockchain_client(); let client = blockchain_client();
let sync = sync_provider(); let sync = sync_provider();
let ap = accounts_provider(); let ap = accounts_provider();
let miner = miner_service(); let miner = miner_service();
let hashrates = Arc::new(Mutex::new(HashMap::new())); let hashrates = Arc::new(Mutex::new(HashMap::new()));
let external_miner = Arc::new(ExternalMiner::new(hashrates.clone())); 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 sign = EthSigningUnsafeClient::new(&client, &ap, &miner).to_delegate();
let io = IoHandler::new(); let io = IoHandler::new();
io.add_delegate(eth); io.add_delegate(eth);
@ -790,15 +796,26 @@ fn returns_no_work_if_cant_mine() {
} }
#[test] #[test]
fn returns_error_if_can_mine_and_no_closed_block() { fn returns_correct_work_package() {
use ethsync::{SyncState};
let eth_tester = EthTester::default(); let eth_tester = EthTester::default();
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()); 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 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())); assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned()));
} }