--author and --extra-data options. Fixed null parent-hash.

This commit is contained in:
Gav Wood 2016-03-01 16:58:14 +01:00
parent 1eca9acffb
commit 48df869202
6 changed files with 95 additions and 18 deletions

View File

@ -182,6 +182,7 @@ impl<'x> OpenBlock<'x> {
r.block.base.header.set_author(author); r.block.base.header.set_author(author);
r.block.base.header.set_extra_data(extra_data); r.block.base.header.set_extra_data(extra_data);
r.block.base.header.set_timestamp_now(parent.timestamp()); r.block.base.header.set_timestamp_now(parent.timestamp());
r.block.base.header.set_parent_hash(parent.hash());
engine.populate_from_parent(&mut r.block.base.header, parent); engine.populate_from_parent(&mut r.block.base.header, parent);
engine.on_new_block(&mut r.block); engine.on_new_block(&mut r.block);
@ -308,10 +309,15 @@ impl ClosedBlock {
pub fn try_seal(self, engine: &Engine, seal: Vec<Bytes>) -> Result<SealedBlock, ClosedBlock> { pub fn try_seal(self, engine: &Engine, seal: Vec<Bytes>) -> Result<SealedBlock, ClosedBlock> {
let mut s = self; let mut s = self;
s.block.base.header.set_seal(seal); s.block.base.header.set_seal(seal);
match engine.verify_block_basic(&s.block.base.header, None).is_err() || engine.verify_block_unordered(&s.block.base.header, None).is_err() { if let Err(e) = engine.verify_block_basic(&s.block.base.header, None) {
false => Err(s), debug!("Failed to try_seal: {:?}", e);
true => Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes }), return Err(s);
} }
if let Err(e) = engine.verify_block_unordered(&s.block.base.header, None) {
debug!("Failed to try_seal: {:?}", e);
return Err(s);
}
Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes })
} }
/// Drop this object and return the underlieing database. /// Drop this object and return the underlieing database.

View File

@ -196,6 +196,8 @@ pub struct Client {
// for sealing... // for sealing...
sealing_block: Mutex<Option<ClosedBlock>>, sealing_block: Mutex<Option<ClosedBlock>>,
author: RwLock<Address>,
extra_data: RwLock<Bytes>,
} }
const HISTORY: u64 = 1000; const HISTORY: u64 = 1000;
@ -233,6 +235,8 @@ impl Client {
import_lock: Mutex::new(()), import_lock: Mutex::new(()),
panic_handler: panic_handler, panic_handler: panic_handler,
sealing_block: Mutex::new(None), sealing_block: Mutex::new(None),
author: RwLock::new(Address::new()),
extra_data: RwLock::new(Vec::new()),
})) }))
} }
@ -364,7 +368,7 @@ impl Client {
} }
if self.chain_info().best_block_hash != original_best { if self.chain_info().best_block_hash != original_best {
self.new_chain_head(); self.prepare_sealing();
} }
imported imported
@ -414,27 +418,55 @@ impl Client {
} }
} }
/// New chain head event. /// Set the author that we will seal blocks as.
pub fn new_chain_head(&self) { pub fn author(&self) -> Address {
self.author.read().unwrap().clone()
}
/// Set the author that we will seal blocks as.
pub fn set_author(&self, author: Address) {
*self.author.write().unwrap() = author;
}
/// Set the extra_data that we will seal blocks wuth.
pub fn extra_data(&self) -> Bytes {
self.extra_data.read().unwrap().clone()
}
/// Set the extra_data that we will seal blocks with.
pub fn set_extra_data(&self, extra_data: Bytes) {
*self.extra_data.write().unwrap() = extra_data;
}
/// New chain head event. Restart mining operation.
pub fn prepare_sealing(&self) {
let h = self.chain.read().unwrap().best_block_hash(); let h = self.chain.read().unwrap().best_block_hash();
debug!("New best block: #{}: {}", self.chain.read().unwrap().best_block_number(), h);
let b = OpenBlock::new( let b = OpenBlock::new(
self.engine.deref().deref(), self.engine.deref().deref(),
self.state_db.lock().unwrap().clone(), self.state_db.lock().unwrap().clone(),
match self.chain.read().unwrap().block_header(&h) { Some(ref x) => x, None => {return;} }, match self.chain.read().unwrap().block_header(&h) { Some(ref x) => x, None => {return;} },
self.build_last_hashes(h.clone()), self.build_last_hashes(h),
x!("0037a6b811ffeb6e072da21179d11b1406371c63"), self.author(),
b"Parity".to_vec() self.extra_data()
); );
// TODO: push uncles.
// TODO: push transactions.
let b = b.close(); let b = b.close();
debug!("Sealing: hash={}, diff={}, number={}", b.hash(), b.block().header().difficulty(), b.block().header().number()); trace!("Sealing: number={}, hash={}, diff={}", b.hash(), b.block().header().difficulty(), b.block().header().number());
debug!("Header: {:?}", b.block().header());
*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. /// Grab the `ClosedBlock` that we want to be sealed. Comes as a mutex that you have to lock.
pub fn sealing_block(&self) -> &Mutex<Option<ClosedBlock>> { &self.sealing_block } pub fn sealing_block(&self) -> &Mutex<Option<ClosedBlock>> {
if self.sealing_block.lock().unwrap().is_none() {
self.prepare_sealing();
}
&self.sealing_block
}
/// Submit `seal` as a valid solution for the header of `pow_hash`. /// Submit `seal` as a valid solution for the header of `pow_hash`.
/// Will check the seal, but not actually insert the block into the chain.
pub fn submit_seal(&self, pow_hash: H256, seal: Vec<Bytes>) -> Result<(), Error> { pub fn submit_seal(&self, pow_hash: H256, seal: Vec<Bytes>) -> Result<(), Error> {
let mut maybe_b = self.sealing_block.lock().unwrap(); let mut maybe_b = self.sealing_block.lock().unwrap();
match *maybe_b { match *maybe_b {

View File

@ -102,10 +102,12 @@ impl Header {
Self::default() Self::default()
} }
/// Get the number field of the header. /// Get the parent_hash field of the header.
pub fn number(&self) -> BlockNumber { self.number } pub fn parent_hash(&self) -> &H256 { &self.parent_hash }
/// Get the timestamp field of the header. /// Get the timestamp field of the header.
pub fn timestamp(&self) -> u64 { self.timestamp } pub fn timestamp(&self) -> u64 { self.timestamp }
/// Get the number field of the header.
pub fn number(&self) -> BlockNumber { self.number }
/// Get the author field of the header. /// Get the author field of the header.
pub fn author(&self) -> &Address { &self.author } pub fn author(&self) -> &Address { &self.author }
@ -127,11 +129,13 @@ impl Header {
// TODO: seal_at, set_seal_at &c. // TODO: seal_at, set_seal_at &c.
/// Set the number field of the header. /// Set the number field of the header.
pub fn set_number(&mut self, a: BlockNumber) { self.number = a; self.note_dirty(); } pub fn set_parent_hash(&mut self, a: H256) { self.parent_hash = a; self.note_dirty(); }
/// Set the timestamp field of the header. /// Set the timestamp field of the header.
pub fn set_timestamp(&mut self, a: u64) { self.timestamp = a; self.note_dirty(); } pub fn set_timestamp(&mut self, a: u64) { self.timestamp = a; self.note_dirty(); }
/// Set the timestamp field of the header to the current time. /// Set the timestamp field of the header to the current time.
pub fn set_timestamp_now(&mut self, but_later_than: u64) { self.timestamp = max(now_utc().to_timespec().sec as u64, but_later_than + 1); self.note_dirty(); } pub fn set_timestamp_now(&mut self, but_later_than: u64) { self.timestamp = max(now_utc().to_timespec().sec as u64, but_later_than + 1); self.note_dirty(); }
/// Set the number field of the header.
pub fn set_number(&mut self, a: BlockNumber) { self.number = a; self.note_dirty(); }
/// Set the author field of the header. /// Set the author field of the header.
pub fn set_author(&mut self, a: Address) { if a != self.author { self.author = a; self.note_dirty(); } } pub fn set_author(&mut self, a: Address) { if a != self.author { self.author = a; self.note_dirty(); } }

View File

@ -85,6 +85,10 @@ Options:
--jsonrpc-url URL Specify URL for JSON-RPC API server [default: 127.0.0.1:8545]. --jsonrpc-url URL Specify URL for JSON-RPC API server [default: 127.0.0.1:8545].
--jsonrpc-cors URL Specify CORS header for JSON-RPC API responses [default: null]. --jsonrpc-cors URL Specify CORS header for JSON-RPC API responses [default: null].
--author ADDRESS Specify the block author (aka "coinbase") address for sending block rewards
from sealed blocks [default: 0037a6b811ffeb6e072da21179d11b1406371c63].
--extra-data STRING Specify a custom extra-data for authored blocks, no more than 32 characters.
-l --logging LOGGING Specify the logging level. -l --logging LOGGING Specify the logging level.
-v --version Show information about version. -v --version Show information about version.
-h --help Show this screen. -h --help Show this screen.
@ -114,6 +118,8 @@ struct Args {
flag_jsonrpc_cors: String, flag_jsonrpc_cors: String,
flag_logging: Option<String>, flag_logging: Option<String>,
flag_version: bool, flag_version: bool,
flag_author: String,
flag_extra_data: Option<String>,
} }
fn setup_log(init: &Option<String>) { fn setup_log(init: &Option<String>) {
@ -196,6 +202,18 @@ impl Configuration {
self.args.flag_db_path.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) self.args.flag_db_path.replace("$HOME", env::home_dir().unwrap().to_str().unwrap())
} }
fn author(&self) -> Address {
Address::from_str(&self.args.flag_author).unwrap_or_else(|_| die!("{}: Invalid address for --author. Must be 40 hex characters, without the 0x at the beginning.", self.args.flag_author))
}
fn extra_data(&self) -> Bytes {
match self.args.flag_extra_data {
Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(),
None => version_data(),
Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); }
}
}
fn _keys_path(&self) -> String { fn _keys_path(&self) -> String {
self.args.flag_keys_path.replace("$HOME", env::home_dir().unwrap().to_str().unwrap()) self.args.flag_keys_path.replace("$HOME", env::home_dir().unwrap().to_str().unwrap())
} }
@ -296,6 +314,8 @@ impl Configuration {
client_config.queue.max_mem_use = self.args.flag_queue_max_size; client_config.queue.max_mem_use = self.args.flag_queue_max_size;
let mut service = ClientService::start(client_config, spec, net_settings, &Path::new(&self.path())).unwrap(); let mut service = ClientService::start(client_config, spec, net_settings, &Path::new(&self.path())).unwrap();
let client = service.client().clone(); let client = service.client().clone();
client.set_author(self.author());
client.set_extra_data(self.extra_data());
// Sync // Sync
let sync = EthSync::register(service.network(), sync_config, client); let sync = EthSync::register(service.network(), sync_config, client);

View File

@ -236,12 +236,12 @@ impl Eth for EthClient {
} }
fn submit_work(&self, params: Params) -> Result<Value, Error> { fn submit_work(&self, params: Params) -> Result<Value, Error> {
// TODO: println! should be debug!
println!("Work submission: {:?}", params);
from_params::<(H64, H256, H256)>(params).and_then(|(nonce, pow_hash, mix_hash)| { from_params::<(H64, H256, H256)>(params).and_then(|(nonce, pow_hash, mix_hash)| {
// trace!("Decoded: nonce={}, pow_hash={}, mix_hash={}", nonce, pow_hash, mix_hash);
let c = take_weak!(self.client); let c = take_weak!(self.client);
let seal = vec![encode(&mix_hash).to_vec(), encode(&nonce).to_vec()]; let seal = vec![encode(&mix_hash).to_vec(), encode(&nonce).to_vec()];
to_value(&c.submit_seal(pow_hash, seal).is_ok()) let r = c.submit_seal(pow_hash, seal);
to_value(&r.is_ok())
}) })
} }

View File

@ -18,6 +18,7 @@
use std::fs::File; use std::fs::File;
use common::*; use common::*;
use rlp::{Stream, RlpStream};
use target_info::Target; use target_info::Target;
use rustc_version; use rustc_version;
@ -71,3 +72,17 @@ pub fn contents(name: &str) -> Result<Bytes, UtilError> {
pub fn version() -> String { pub fn version() -> String {
format!("Parity//v{}-{}-{}/{}-{}-{}/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())
} }
/// Get the standard version data for this software.
pub fn version_data() -> Bytes {
let mut s = RlpStream::new_list(4);
let v =
(u32::from_str(env!("CARGO_PKG_VERSION_MAJOR")).unwrap() << 16) +
(u32::from_str(env!("CARGO_PKG_VERSION_MINOR")).unwrap() << 8) +
u32::from_str(env!("CARGO_PKG_VERSION_PATCH")).unwrap();
s.append(&v);
s.append(&"Parity");
s.append(&format!("rustc{}", rustc_version::version()));
s.append(&Target::os());
s.out()
}