Merge branch 'miner-no-ap' into auth-bft

This commit is contained in:
keorn
2016-11-17 22:04:07 +00:00
51 changed files with 1548 additions and 126 deletions

View File

@@ -68,6 +68,7 @@ pub struct AuthorityRound {
builtins: BTreeMap<Address, Builtin>,
transition_service: IoService<BlockArrived>,
message_channel: Mutex<Option<IoChannel<ClientIoMessage>>>,
account_provider: Mutex<Option<Arc<AccountProvider>>>,
step: AtomicUsize,
proposed: AtomicBool,
}
@@ -101,6 +102,7 @@ impl AuthorityRound {
builtins: builtins,
transition_service: try!(IoService::<BlockArrived>::start()),
message_channel: Mutex::new(None),
account_provider: Mutex::new(None),
step: AtomicUsize::new(initial_step),
proposed: AtomicBool::new(false)
});
@@ -219,12 +221,12 @@ impl Engine for AuthorityRound {
///
/// This operation is synchronous and may (quite reasonably) not be available, in which `false` will
/// be returned.
fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option<Vec<Bytes>> {
fn generate_seal(&self, block: &ExecutedBlock) -> Option<Vec<Bytes>> {
if self.proposed.load(AtomicOrdering::SeqCst) { return None; }
let header = block.header();
let step = self.step();
if self.is_step_proposer(step, header.author()) {
if let Some(ap) = accounts {
if let Some(ref ap) = *self.account_provider.lock() {
// Account should be permanently unlocked, otherwise sealing will fail.
if let Ok(signature) = ap.sign(*header.author(), None, header.bare_hash()) {
trace!(target: "poa", "generate_seal: Issuing a block for step {}.", step);
@@ -307,8 +309,11 @@ impl Engine for AuthorityRound {
}
fn register_message_channel(&self, message_channel: IoChannel<ClientIoMessage>) {
let mut guard = self.message_channel.lock();
*guard = Some(message_channel);
*self.message_channel.lock() = Some(message_channel);
}
fn register_account_provider(&self, account_provider: Arc<AccountProvider>) {
*self.account_provider.lock() = Some(account_provider);
}
}
@@ -382,6 +387,7 @@ mod tests {
let spec = Spec::new_test_round();
let engine = &*spec.engine;
engine.register_account_provider(Arc::new(tap));
let genesis_header = spec.genesis_header();
let mut db1 = get_temp_state_db().take();
spec.ensure_db_good(&mut db1).unwrap();
@@ -393,16 +399,16 @@ mod tests {
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b2 = b2.close_and_lock();
if let Some(seal) = engine.generate_seal(b1.block(), Some(&tap)) {
if let Some(seal) = engine.generate_seal(b1.block()) {
assert!(b1.clone().try_seal(engine, seal).is_ok());
// Second proposal is forbidden.
assert!(engine.generate_seal(b1.block(), Some(&tap)).is_none());
assert!(engine.generate_seal(b1.block()).is_none());
}
if let Some(seal) = engine.generate_seal(b2.block(), Some(&tap)) {
if let Some(seal) = engine.generate_seal(b2.block()) {
assert!(b2.clone().try_seal(engine, seal).is_ok());
// Second proposal is forbidden.
assert!(engine.generate_seal(b2.block(), Some(&tap)).is_none());
assert!(engine.generate_seal(b2.block()).is_none());
}
}

View File

@@ -58,6 +58,7 @@ pub struct BasicAuthority {
params: CommonParams,
our_params: BasicAuthorityParams,
builtins: BTreeMap<Address, Builtin>,
account_provider: Mutex<Option<Arc<AccountProvider>>>
}
impl BasicAuthority {
@@ -67,6 +68,7 @@ impl BasicAuthority {
params: params,
our_params: our_params,
builtins: builtins,
account_provider: Mutex::new(None)
}
}
}
@@ -113,8 +115,8 @@ impl Engine for BasicAuthority {
///
/// This operation is synchronous and may (quite reasonably) not be available, in which `false` will
/// be returned.
fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option<Vec<Bytes>> {
if let Some(ap) = accounts {
fn generate_seal(&self, block: &ExecutedBlock) -> Option<Vec<Bytes>> {
if let Some(ref ap) = *self.account_provider.lock() {
let header = block.header();
let message = header.bare_hash();
// account should be pernamently unlocked, otherwise sealing will fail
@@ -179,6 +181,10 @@ impl Engine for BasicAuthority {
fn verify_transaction(&self, t: &SignedTransaction, _header: &Header) -> Result<(), Error> {
t.sender().map(|_|()) // Perform EC recovery and cache sender
}
fn register_account_provider(&self, ap: Arc<AccountProvider>) {
*self.account_provider.lock() = Some(ap);
}
}
#[cfg(test)]
@@ -253,6 +259,7 @@ mod tests {
let spec = new_test_authority();
let engine = &*spec.engine;
engine.register_account_provider(Arc::new(tap));
let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
@@ -260,7 +267,7 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock();
let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap();
let seal = engine.generate_seal(b.block()).unwrap();
assert!(b.try_seal(engine, seal).is_ok());
}

View File

@@ -23,7 +23,6 @@ use spec::CommonParams;
use evm::Schedule;
use block::ExecutedBlock;
use util::Bytes;
use account_provider::AccountProvider;
/// An engine which does not provide any consensus mechanism, just seals blocks internally.
pub struct InstantSeal {
@@ -60,7 +59,7 @@ impl Engine for InstantSeal {
fn is_sealer(&self, _author: &Address) -> Option<bool> { Some(true) }
fn generate_seal(&self, _block: &ExecutedBlock, _accounts: Option<&AccountProvider>) -> Option<Vec<Bytes>> {
fn generate_seal(&self, _block: &ExecutedBlock) -> Option<Vec<Bytes>> {
Some(Vec::new())
}
}
@@ -69,16 +68,12 @@ impl Engine for InstantSeal {
mod tests {
use util::*;
use tests::helpers::*;
use account_provider::AccountProvider;
use spec::Spec;
use header::Header;
use block::*;
#[test]
fn instant_can_seal() {
let tap = AccountProvider::transient_provider();
let addr = tap.insert_account("".sha3(), "").unwrap();
let spec = Spec::new_instant();
let engine = &*spec.engine;
let genesis_header = spec.genesis_header();
@@ -86,10 +81,9 @@ mod tests {
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock();
// Seal with empty AccountProvider.
let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap();
let seal = engine.generate_seal(b.block()).unwrap();
assert!(b.try_seal(engine, seal).is_ok());
}

View File

@@ -114,7 +114,7 @@ pub trait Engine : Sync + Send {
///
/// This operation is synchronous and may (quite reasonably) not be available, in which None will
/// be returned.
fn generate_seal(&self, _block: &ExecutedBlock, _accounts: Option<&AccountProvider>) -> Option<Vec<Bytes>> { None }
fn generate_seal(&self, _block: &ExecutedBlock) -> Option<Vec<Bytes>> { None }
/// Phase 1 quick block verification. Only does checks that are cheap. `block` (the header's full block)
/// may be provided for additional checks. Returns either a null `Ok` or a general error detailing the problem with import.
@@ -179,5 +179,6 @@ pub trait Engine : Sync + Send {
ethash::is_new_best_block(best_total_difficulty, parent_details, new_header)
}
// TODO: sealing stuff - though might want to leave this for later.
/// Add an account provider useful for Engines that sign stuff.
fn register_account_provider(&self, _account_provider: Arc<AccountProvider>) {}
}

View File

@@ -19,7 +19,6 @@ use std::time::{Instant, Duration};
use util::*;
use util::using_queue::{UsingQueue, GetAction};
use account_provider::AccountProvider;
use views::{BlockView, HeaderView};
use state::{State, CleanupMode};
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics};
@@ -220,14 +219,13 @@ pub struct Miner {
extra_data: RwLock<Bytes>,
engine: Arc<Engine>,
accounts: Option<Arc<AccountProvider>>,
work_poster: Option<WorkPoster>,
gas_pricer: Mutex<GasPricer>,
}
impl Miner {
/// Creates new instance of miner.
fn new_raw(options: MinerOptions, gas_pricer: GasPricer, spec: &Spec, accounts: Option<Arc<AccountProvider>>) -> Miner {
fn new_raw(options: MinerOptions, gas_pricer: GasPricer, spec: &Spec) -> Miner {
let work_poster = match options.new_work_notify.is_empty() {
true => None,
false => Some(WorkPoster::new(&options.new_work_notify))
@@ -261,26 +259,20 @@ impl Miner {
author: RwLock::new(Address::default()),
extra_data: RwLock::new(Vec::new()),
options: options,
accounts: accounts,
engine: spec.engine.clone(),
work_poster: work_poster,
gas_pricer: Mutex::new(gas_pricer),
}
}
/// Creates new instance of miner with accounts and with given spec.
pub fn with_spec_and_accounts(spec: &Spec, accounts: Option<Arc<AccountProvider>>) -> Miner {
Miner::new_raw(Default::default(), GasPricer::new_fixed(20_000_000_000u64.into()), spec, accounts)
}
/// Creates new instance of miner without accounts, but with given spec.
/// Creates new instance of miner with given spec.
pub fn with_spec(spec: &Spec) -> Miner {
Miner::new_raw(Default::default(), GasPricer::new_fixed(20_000_000_000u64.into()), spec, None)
Miner::new_raw(Default::default(), GasPricer::new_fixed(20_000_000_000u64.into()), spec)
}
/// Creates new instance of a miner Arc.
pub fn new(options: MinerOptions, gas_pricer: GasPricer, spec: &Spec, accounts: Option<Arc<AccountProvider>>) -> Arc<Miner> {
Arc::new(Miner::new_raw(options, gas_pricer, spec, accounts))
pub fn new(options: MinerOptions, gas_pricer: GasPricer, spec: &Spec) -> Arc<Miner> {
Arc::new(Miner::new_raw(options, gas_pricer, spec))
}
fn forced_sealing(&self) -> bool {
@@ -461,10 +453,7 @@ impl Miner {
/// Err(Some(block)) returns for unsuccesful sealing while Err(None) indicates misspecified engine.
fn seal_block_internally(&self, block: ClosedBlock) -> Result<SealedBlock, Option<ClosedBlock>> {
trace!(target: "miner", "seal_block_internally: block has transaction - attempting internal seal.");
let s = self.engine.generate_seal(block.block(), match self.accounts {
Some(ref x) => Some(&**x),
None => None,
});
let s = self.engine.generate_seal(block.block());
if let Some(seal) = s {
trace!(target: "miner", "seal_block_internally: managed internal seal. importing...");
block.lock().try_seal(&*self.engine, seal).or_else(|_| {
@@ -1170,7 +1159,6 @@ mod tests {
},
GasPricer::new_fixed(0u64.into()),
&Spec::new_test(),
None, // accounts provider
)).ok().expect("Miner was just created.")
}