diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 764c61c52..e7526e8cd 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -35,6 +35,7 @@ mod codes { pub const NO_AUTHOR: i64 = -32002; pub const NO_NEW_WORK: i64 = -32003; pub const NO_WORK_REQUIRED: i64 = -32004; + pub const CANNOT_SUBMIT_WORK: i64 = -32005; pub const UNKNOWN_ERROR: i64 = -32009; pub const TRANSACTION_ERROR: i64 = -32010; pub const EXECUTION_ERROR: i64 = -32015; @@ -197,6 +198,14 @@ pub fn no_work_required() -> Error { } } +pub fn cannot_submit_work(err: EthcoreError) -> Error { + Error { + code: ErrorCode::ServerError(codes::CANNOT_SUBMIT_WORK), + message: "Cannot submit work.".into(), + data: Some(Value::String(err.to_string())), + } +} + pub fn not_enough_data() -> Error { Error { code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index ba8356334..be845821d 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -34,6 +34,7 @@ mod signer; mod signing_queue; mod subscribers; mod subscription_manager; +mod work; pub use self::dispatch::{Dispatcher, FullDispatcher}; pub use self::network_settings::NetworkSettings; @@ -50,6 +51,7 @@ pub use self::signing_queue::{ pub use self::signer::SignerService; pub use self::subscribers::Subscribers; pub use self::subscription_manager::GenericPollManager; +pub use self::work::submit_work_detail; pub fn to_url(address: &Option<::Host>) -> Option { address.as_ref().map(|host| (**host).to_owned()) diff --git a/rpc/src/v1/helpers/work.rs b/rpc/src/v1/helpers/work.rs new file mode 100644 index 000000000..c2b7db765 --- /dev/null +++ b/rpc/src/v1/helpers/work.rs @@ -0,0 +1,47 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Helpers for submit a POW work. + +use std::sync::Arc; + +use rlp; +use ethcore::miner::{BlockChainClient, MinerService}; +use ethereum_types::{H64 as EthcoreH64, H256 as EthcoreH256}; +use jsonrpc_core::Error; +use v1::types::{H64, H256}; +use v1::helpers::errors; + +// Submit a POW work and return the block's hash +pub fn submit_work_detail(client: &Arc, miner: &Arc, nonce: H64, pow_hash: H256, mix_hash: H256) -> Result { + // TODO [ToDr] Should disallow submissions in case of PoA? + let nonce: EthcoreH64 = nonce.into(); + let pow_hash: EthcoreH256 = pow_hash.into(); + let mix_hash: EthcoreH256 = mix_hash.into(); + trace!(target: "miner", "submit_work_detail: Decoded: nonce={}, pow_hash={}, mix_hash={}", nonce, pow_hash, mix_hash); + let seal = vec![rlp::encode(&mix_hash).into_vec(), rlp::encode(&nonce).into_vec()]; + let import = miner.submit_seal(pow_hash, seal) + .and_then(|block| client.import_sealed_block(block)); + match import { + Ok(hash) => { + Ok(hash.into()) + }, + Err(err) => { + warn!(target: "miner", "Cannot submit work - {:?}.", err); + Err(errors::cannot_submit_work(err)) + }, + } +} diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 64191a06c..d912c13dd 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -20,8 +20,8 @@ use std::thread; use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH}; use std::sync::Arc; -use rlp::{self, Rlp}; -use ethereum_types::{U256, H64, H256, Address}; +use rlp::Rlp; +use ethereum_types::{U256, H256, Address}; use parking_lot::Mutex; use ethash::{self, SeedHashCompute}; @@ -40,7 +40,7 @@ use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::future; use jsonrpc_macros::Trailing; -use v1::helpers::{errors, limit_logs, fake_sign}; +use v1::helpers::{self, errors, limit_logs, fake_sign}; use v1::helpers::dispatch::{FullDispatcher, default_gas_price}; use v1::helpers::block_import::is_major_importing; use v1::traits::Eth; @@ -789,22 +789,9 @@ impl Eth for EthClient< } fn submit_work(&self, nonce: RpcH64, pow_hash: RpcH256, mix_hash: RpcH256) -> Result { - // TODO [ToDr] Should disallow submissions in case of PoA? - let nonce: H64 = nonce.into(); - let pow_hash: H256 = pow_hash.into(); - let mix_hash: H256 = mix_hash.into(); - trace!(target: "miner", "submit_work: Decoded: nonce={}, pow_hash={}, mix_hash={}", nonce, pow_hash, mix_hash); - - let seal = vec![rlp::encode(&mix_hash).into_vec(), rlp::encode(&nonce).into_vec()]; - let import = self.miner.submit_seal(pow_hash, seal) - .and_then(|block| self.client.import_sealed_block(block)); - - match import { - Ok(_) => Ok(true), - Err(err) => { - warn!(target: "miner", "Cannot submit work - {:?}.", err); - Ok(false) - }, + match helpers::submit_work_detail(&self.client, &self.miner, nonce, pow_hash, mix_hash) { + Ok(_) => Ok(true), + Err(_) => Ok(false), } } diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 4ab456e68..3f51826fc 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -38,7 +38,7 @@ use v1::helpers::light_fetch::LightFetch; use v1::metadata::Metadata; use v1::traits::Parity; use v1::types::{ - Bytes, U256, U64, H160, H256, H512, CallRequest, + Bytes, U256, U64, H64, H160, H256, H512, CallRequest, Peers, Transaction, RpcSettings, Histogram, TransactionStats, LocalTransactionStatus, BlockNumber, LightBlockNumber, ConsensusCapability, VersionInfo, @@ -418,4 +418,8 @@ impl Parity for ParityClient { fn call(&self, _requests: Vec, _block: Trailing) -> Result> { Err(errors::light_unimplemented(None)) } + + fn submit_work_detail(&self, _nonce: H64, _pow_hash: H256, _mix_hash: H256) -> Result { + Err(errors::light_unimplemented(None)) + } } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index bbf75411e..3dce93ecd 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -40,7 +40,7 @@ use v1::helpers::{self, errors, fake_sign, ipfs, SigningQueue, SignerService, Ne use v1::metadata::Metadata; use v1::traits::Parity; use v1::types::{ - Bytes, U256, U64, H160, H256, H512, CallRequest, + Bytes, U256, U64, H64, H160, H256, H512, CallRequest, Peers, Transaction, RpcSettings, Histogram, TransactionStats, LocalTransactionStatus, BlockNumber, ConsensusCapability, VersionInfo, @@ -471,4 +471,8 @@ impl Parity for ParityClient where .map(|res| res.into_iter().map(|res| res.output.into()).collect()) .map_err(errors::call) } + + fn submit_work_detail(&self, nonce: H64, pow_hash: H256, mix_hash: H256) -> Result { + helpers::submit_work_detail(&self.client, &self.miner, nonce, pow_hash, mix_hash) + } } diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index c71e6d8dc..0dc0f15dc 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -22,7 +22,7 @@ use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_macros::Trailing; use v1::types::{ - H160, H256, H512, U256, U64, Bytes, CallRequest, + H64, H160, H256, H512, U256, U64, Bytes, CallRequest, Peers, Transaction, RpcSettings, Histogram, TransactionStats, LocalTransactionStatus, BlockNumber, ConsensusCapability, VersionInfo, @@ -224,5 +224,10 @@ build_rpc_trait! { /// Call contract, returning the output data. #[rpc(name = "parity_call")] fn call(&self, Vec, Trailing) -> Result>; + + /// Used for submitting a proof-of-work solution (similar to `eth_submitWork`, + /// but returns block hash on success, and returns an explicit error message on failure). + #[rpc(name = "parity_submitWorkDetail")] + fn submit_work_detail(&self, H64, H256, H256) -> Result; } }