From ffc5c2ea7bf5747acbbc87dca25e37943312d771 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 29 Feb 2016 19:30:13 +0100 Subject: [PATCH] eth_getwork implemented. --- Cargo.lock | 1 + ethash/src/compute.rs | 3 ++- ethash/src/lib.rs | 4 ++-- ethcore/src/client.rs | 13 +++++++------ ethcore/src/ethereum/ethash.rs | 14 ++++++++++---- rpc/Cargo.toml | 1 + rpc/src/v1/impls/eth.rs | 27 +++++++++++++++++++++++++++ util/src/misc.rs | 2 +- util/src/uint.rs | 27 +++++++++++++++++++++++++++ 9 files changed, 78 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bca236813..9c225dbbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -203,6 +203,7 @@ name = "ethcore-rpc" version = "0.9.99" dependencies = [ "clippy 0.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "ethash 0.9.99", "ethcore 0.9.99", "ethcore-util 0.9.99", "ethsync 0.9.99", diff --git a/ethash/src/compute.rs b/ethash/src/compute.rs index 6c311993b..eb64151d0 100644 --- a/ethash/src/compute.rs +++ b/ethash/src/compute.rs @@ -172,7 +172,8 @@ fn get_data_size(block_number: u64) -> usize { } #[inline] -fn get_seedhash(block_number: u64) -> H256 { +/// Given the `block_number`, determine the seed hash for Ethash. +pub fn get_seedhash(block_number: u64) -> H256 { let epochs = block_number / ETHASH_EPOCH_LENGTH; let mut ret: H256 = [0u8; 32]; for _ in 0..epochs { diff --git a/ethash/src/lib.rs b/ethash/src/lib.rs index e96b98b81..982f7129b 100644 --- a/ethash/src/lib.rs +++ b/ethash/src/lib.rs @@ -24,7 +24,7 @@ mod compute; use std::mem; use compute::Light; -pub use compute::{quick_get_difficulty, H256, ProofOfWork, ETHASH_EPOCH_LENGTH}; +pub use compute::{get_seedhash, quick_get_difficulty, H256, ProofOfWork, ETHASH_EPOCH_LENGTH}; use std::sync::{Arc, Mutex}; @@ -35,7 +35,7 @@ struct LightCache { prev: Option>, } -/// Lighy/Full cache manager +/// Light/Full cache manager. pub struct EthashManager { cache: Mutex, } diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index d81507d25..f634579ad 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -195,7 +195,7 @@ pub struct Client { panic_handler: Arc, // for sealing... - _sealing_block: Mutex>, + sealing_block: Mutex>, } const HISTORY: u64 = 1000; @@ -232,7 +232,7 @@ impl Client { report: RwLock::new(Default::default()), import_lock: Mutex::new(()), panic_handler: panic_handler, - _sealing_block: Mutex::new(None), + sealing_block: Mutex::new(None), })) } @@ -417,9 +417,7 @@ impl Client { /// New chain head event. pub fn new_chain_head(&self) { let h = self.chain.read().unwrap().best_block_hash(); - info!("NEW CHAIN HEAD: #{}: {}", self.chain.read().unwrap().best_block_number(), h); - - info!("Preparing to seal."); + info!("New best block: #{}: {}", self.chain.read().unwrap().best_block_number(), h); let b = OpenBlock::new( self.engine.deref().deref(), self.state_db.lock().unwrap().clone(), @@ -430,8 +428,11 @@ impl Client { ); let b = b.close(); info!("Sealed: hash={}, diff={}, number={}", b.hash(), b.block().header().difficulty(), b.block().header().number()); - *self._sealing_block.lock().unwrap() = Some(b); + *self.sealing_block.lock().unwrap() = Some(b); } + + /// Grab the `ClosedBlock` that we want to be sealed. Comes as a mutex that you have to lock. + pub fn sealing_block(&self) -> &Mutex> { &self.sealing_block } } // TODO: need MinerService MinerIoHandler diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 54f02524d..4f1ef1ce3 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -144,9 +144,9 @@ impl Engine for Ethash { } let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(quick_get_difficulty( - &Ethash::to_ethash(header.bare_hash()), - header.nonce().low_u64(), - &Ethash::to_ethash(header.mix_hash())))); + &Ethash::to_ethash(header.bare_hash()), + header.nonce().low_u64(), + &Ethash::to_ethash(header.mix_hash()) ))); if difficulty < header.difficulty { return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: difficulty }))); } @@ -241,10 +241,16 @@ impl Ethash { target } - fn boundary_to_difficulty(boundary: &H256) -> U256 { + /// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`. + pub fn boundary_to_difficulty(boundary: &H256) -> U256 { U256::from((U512::one() << 256) / x!(U256::from(boundary.as_slice()))) } + /// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`. + pub fn difficulty_to_boundary(difficulty: &U256) -> H256 { + x!(U256::from((U512::one() << 256) / x!(difficulty))) + } + fn to_ethash(hash: H256) -> EH256 { unsafe { mem::transmute(hash) } } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index b9ca9deac..c38684643 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -15,6 +15,7 @@ jsonrpc-core = "1.2" jsonrpc-http-server = "2.1" ethcore-util = { path = "../util" } ethcore = { path = "../ethcore" } +ethash = { path = "../ethash" } ethsync = { path = "../sync" } clippy = { version = "0.0.44", optional = true } rustc-serialize = "0.3" diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 00bce5437..5791b7418 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -22,7 +22,11 @@ use util::hash::*; use util::uint::*; use util::sha3::*; use ethcore::client::*; +use ethcore::block::{IsBlock}; use ethcore::views::*; +extern crate ethash; +use self::ethash::get_seedhash; +use ethcore::ethereum::Ethash; use ethcore::ethereum::denominations::shannon; use v1::traits::{Eth, EthFilter}; use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index, Filter, Log}; @@ -209,6 +213,29 @@ impl Eth for EthClient { to_value(&logs) }) } + + fn work(&self, params: Params) -> Result { + match params { + Params::None => { + let c = take_weak!(self.client); + let u = c.sealing_block().lock().unwrap(); + match *u { + Some(ref b) => { + let current_hash = b.hash(); + let target = Ethash::difficulty_to_boundary(b.block().header().difficulty()); + let seed_hash = get_seedhash(b.block().header().number()); + to_value(&(current_hash, seed_hash, target)) + } + _ => Err(Error::invalid_params()) + } + }, + _ => Err(Error::invalid_params()) + } + } + +// fn submit_work(&self, _: Params) -> Result { rpc_unimplemented!() } + +// fn submit_hashrate(&self, _: Params) -> Result { rpc_unimplemented!() } } /// Eth filter rpc implementation. diff --git a/util/src/misc.rs b/util/src/misc.rs index 289f1c50c..35e1f3a75 100644 --- a/util/src/misc.rs +++ b/util/src/misc.rs @@ -69,5 +69,5 @@ pub fn contents(name: &str) -> Result { /// Get the standard version string for this software. pub fn version() -> String { - format!("Parity//{}-{}-{}/{}-{}-{}/rustc{}", env!("CARGO_PKG_VERSION"), short_sha(), commit_date().replace("-", ""), Target::arch(), Target::os(), Target::env(), rustc_version::version()) + format!("Parity//v{}-{}-{}/{}-{}-{}/rustc{}", env!("CARGO_PKG_VERSION"), short_sha(), commit_date().replace("-", ""), Target::arch(), Target::os(), Target::env(), rustc_version::version()) } \ No newline at end of file diff --git a/util/src/uint.rs b/util/src/uint.rs index 517b7a29f..7f2e3d3b1 100644 --- a/util/src/uint.rs +++ b/util/src/uint.rs @@ -1124,6 +1124,33 @@ impl From for U256 { } } +impl<'a> From<&'a U256> for U512 { + fn from(value: &'a U256) -> U512 { + let U256(ref arr) = *value; + let mut ret = [0; 8]; + ret[0] = arr[0]; + ret[1] = arr[1]; + ret[2] = arr[2]; + ret[3] = arr[3]; + U512(ret) + } +} + +impl<'a> From<&'a U512> for U256 { + fn from(value: &'a U512) -> U256 { + let U512(ref arr) = *value; + if arr[4] | arr[5] | arr[6] | arr[7] != 0 { + panic!("Overflow"); + } + let mut ret = [0; 4]; + ret[0] = arr[0]; + ret[1] = arr[1]; + ret[2] = arr[2]; + ret[3] = arr[3]; + U256(ret) + } +} + impl From for U128 { fn from(value: U256) -> U128 { let U256(ref arr) = value;