Deprecate account management (#10213)
* Extract accounts from ethcore. * Fix ethcore. * Get rid of AccountProvider in test_helpers * Fix rest of the code. * Re-use EngineSigner, fix tests. * Simplify EngineSigner to always have an Address. * Fix RPC tests. * Add deprecation notice to RPCs. * Feature to disable accounts. * extract accounts in RPC * Run with accounts in tests. * Fix RPC compilation and tests. * Fix compilation of the binary. * Fix compilation of the binary. * Fix compilation with accounts enabled. * Fix tests. * Update submodule. * Remove android. * Use derive for Default * Don't build secretstore by default. * Add link to issue. * Refresh Cargo.lock. * Fix miner tests. * Update rpc/Cargo.toml Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com> * Fix private tests.
This commit is contained in:
committed by
Afri Schoedon
parent
8fa56add47
commit
d5c19f8719
@@ -24,7 +24,6 @@ use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
|
||||
use std::sync::{Weak, Arc};
|
||||
use std::time::{UNIX_EPOCH, SystemTime, Duration};
|
||||
|
||||
use account_provider::AccountProvider;
|
||||
use block::*;
|
||||
use client::EngineClient;
|
||||
use engines::{Engine, Seal, EngineError, ConstructedVerifier};
|
||||
@@ -37,7 +36,7 @@ use hash::keccak;
|
||||
use super::signer::EngineSigner;
|
||||
use super::validator_set::{ValidatorSet, SimpleList, new_validator_set};
|
||||
use self::finality::RollingFinality;
|
||||
use ethkey::{self, Password, Signature};
|
||||
use ethkey::{self, Signature};
|
||||
use io::{IoContext, IoHandler, TimerToken, IoService};
|
||||
use itertools::{self, Itertools};
|
||||
use rlp::{encode, Decodable, DecoderError, Encodable, RlpStream, Rlp};
|
||||
@@ -412,7 +411,7 @@ pub struct AuthorityRound {
|
||||
transition_service: IoService<()>,
|
||||
step: Arc<PermissionedStep>,
|
||||
client: Arc<RwLock<Option<Weak<EngineClient>>>>,
|
||||
signer: RwLock<EngineSigner>,
|
||||
signer: RwLock<Option<Box<EngineSigner>>>,
|
||||
validators: Box<ValidatorSet>,
|
||||
validate_score_transition: u64,
|
||||
validate_step_transition: u64,
|
||||
@@ -665,7 +664,7 @@ impl AuthorityRound {
|
||||
can_propose: AtomicBool::new(true),
|
||||
}),
|
||||
client: Arc::new(RwLock::new(None)),
|
||||
signer: Default::default(),
|
||||
signer: RwLock::new(None),
|
||||
validators: our_params.validators,
|
||||
validate_score_transition: our_params.validate_score_transition,
|
||||
validate_step_transition: our_params.validate_step_transition,
|
||||
@@ -788,7 +787,7 @@ impl AuthorityRound {
|
||||
return;
|
||||
}
|
||||
|
||||
if let (true, Some(me)) = (current_step > parent_step + 1, self.signer.read().address()) {
|
||||
if let (true, Some(me)) = (current_step > parent_step + 1, self.signer.read().as_ref().map(|s| s.address())) {
|
||||
debug!(target: "engine", "Author {} built block with step gap. current step: {}, parent step: {}",
|
||||
header.author(), current_step, parent_step);
|
||||
let mut reported = HashSet::new();
|
||||
@@ -1492,12 +1491,16 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
self.validators.register_client(client);
|
||||
}
|
||||
|
||||
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: Password) {
|
||||
self.signer.write().set(ap, address, password);
|
||||
fn set_signer(&self, signer: Box<EngineSigner>) {
|
||||
*self.signer.write() = Some(signer);
|
||||
}
|
||||
|
||||
fn sign(&self, hash: H256) -> Result<Signature, Error> {
|
||||
Ok(self.signer.read().sign(hash)?)
|
||||
Ok(self.signer.read()
|
||||
.as_ref()
|
||||
.ok_or(ethkey::Error::InvalidAddress)?
|
||||
.sign(hash)?
|
||||
)
|
||||
}
|
||||
|
||||
fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> {
|
||||
@@ -1532,16 +1535,16 @@ mod tests {
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
||||
use hash::keccak;
|
||||
use accounts::AccountProvider;
|
||||
use ethereum_types::{Address, H520, H256, U256};
|
||||
use ethkey::Signature;
|
||||
use types::header::Header;
|
||||
use rlp::encode;
|
||||
use block::*;
|
||||
use test_helpers::{
|
||||
generate_dummy_client_with_spec_and_accounts, get_temp_state_db,
|
||||
generate_dummy_client_with_spec, get_temp_state_db,
|
||||
TestNotify
|
||||
};
|
||||
use account_provider::AccountProvider;
|
||||
use spec::Spec;
|
||||
use types::transaction::{Action, Transaction};
|
||||
use engines::{Seal, Engine, EngineError, EthEngine};
|
||||
@@ -1620,14 +1623,14 @@ mod tests {
|
||||
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||
let b2 = b2.close_and_lock().unwrap();
|
||||
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b1.block(), &genesis_header) {
|
||||
assert!(b1.clone().try_seal(engine, seal).is_ok());
|
||||
// Second proposal is forbidden.
|
||||
assert!(engine.generate_seal(b1.block(), &genesis_header) == Seal::None);
|
||||
}
|
||||
|
||||
engine.set_signer(tap, addr2, "2".into());
|
||||
engine.set_signer(Box::new((tap, addr2, "2".into())));
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
|
||||
assert!(b2.clone().try_seal(engine, seal).is_ok());
|
||||
// Second proposal is forbidden.
|
||||
@@ -1654,13 +1657,13 @@ mod tests {
|
||||
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||
let b2 = b2.close_and_lock().unwrap();
|
||||
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
match engine.generate_seal(b1.block(), &genesis_header) {
|
||||
Seal::None | Seal::Proposal(_) => panic!("wrong seal"),
|
||||
Seal::Regular(_) => {
|
||||
engine.step();
|
||||
|
||||
engine.set_signer(tap.clone(), addr2, "0".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||
match engine.generate_seal(b2.block(), &genesis_header) {
|
||||
Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"),
|
||||
Seal::None => {}
|
||||
@@ -1768,7 +1771,7 @@ mod tests {
|
||||
assert!(aura.verify_block_family(&header, &parent_header).is_ok());
|
||||
assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 0);
|
||||
|
||||
aura.set_signer(Arc::new(AccountProvider::transient_provider()), Default::default(), "".into());
|
||||
aura.set_signer(Box::new((Arc::new(AccountProvider::transient_provider()), Default::default(), "".into())));
|
||||
|
||||
// Do not report on steps skipped between genesis and first block.
|
||||
header.set_number(1);
|
||||
@@ -1878,12 +1881,12 @@ mod tests {
|
||||
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps);
|
||||
let notify = Arc::new(TestNotify::default());
|
||||
client.add_notify(notify.clone());
|
||||
engine.register_client(Arc::downgrade(&client) as _);
|
||||
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
|
||||
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||
let b1 = b1.close_and_lock().unwrap();
|
||||
@@ -1917,7 +1920,7 @@ mod tests {
|
||||
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps);
|
||||
let notify = Arc::new(TestNotify::default());
|
||||
client.add_notify(notify.clone());
|
||||
engine.register_client(Arc::downgrade(&client) as _);
|
||||
@@ -1927,7 +1930,7 @@ mod tests {
|
||||
let b1 = b1.close_and_lock().unwrap();
|
||||
|
||||
// since the block is empty it isn't sealed and we generate empty steps
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
||||
engine.step();
|
||||
|
||||
@@ -1944,9 +1947,9 @@ mod tests {
|
||||
let b2 = b2.close_and_lock().unwrap();
|
||||
|
||||
// we will now seal a block with 1tx and include the accumulated empty step message
|
||||
engine.set_signer(tap.clone(), addr2, "0".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
|
||||
let empty_steps = ::rlp::encode_list(&vec![empty_step2]);
|
||||
|
||||
@@ -1970,7 +1973,7 @@ mod tests {
|
||||
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps);
|
||||
let notify = Arc::new(TestNotify::default());
|
||||
client.add_notify(notify.clone());
|
||||
engine.register_client(Arc::downgrade(&client) as _);
|
||||
@@ -1980,14 +1983,14 @@ mod tests {
|
||||
let b1 = b1.close_and_lock().unwrap();
|
||||
|
||||
// since the block is empty it isn't sealed and we generate empty steps
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
||||
engine.step();
|
||||
|
||||
// step 3
|
||||
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||
let b2 = b2.close_and_lock().unwrap();
|
||||
engine.set_signer(tap.clone(), addr2, "0".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||
assert_eq!(engine.generate_seal(b2.block(), &genesis_header), Seal::None);
|
||||
engine.step();
|
||||
|
||||
@@ -1996,10 +1999,10 @@ mod tests {
|
||||
let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||
let b3 = b3.close_and_lock().unwrap();
|
||||
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b3.block(), &genesis_header) {
|
||||
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
|
||||
engine.set_signer(tap.clone(), addr2, "0".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||
let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash());
|
||||
|
||||
let empty_steps = ::rlp::encode_list(&vec![empty_step2, empty_step3]);
|
||||
@@ -2022,7 +2025,7 @@ mod tests {
|
||||
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_test_round_empty_steps);
|
||||
engine.register_client(Arc::downgrade(&client) as _);
|
||||
|
||||
// step 2
|
||||
@@ -2030,7 +2033,7 @@ mod tests {
|
||||
let b1 = b1.close_and_lock().unwrap();
|
||||
|
||||
// since the block is empty it isn't sealed and we generate empty steps
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
||||
engine.step();
|
||||
|
||||
@@ -2084,7 +2087,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// empty step with valid signature from incorrect proposer for step
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
let empty_steps = vec![sealed_empty_step(engine, 1, &parent_header.hash())];
|
||||
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
|
||||
|
||||
@@ -2094,9 +2097,9 @@ mod tests {
|
||||
);
|
||||
|
||||
// valid empty steps
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
let empty_step2 = sealed_empty_step(engine, 2, &parent_header.hash());
|
||||
engine.set_signer(tap.clone(), addr2, "0".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||
let empty_step3 = sealed_empty_step(engine, 3, &parent_header.hash());
|
||||
|
||||
let empty_steps = vec![empty_step2, empty_step3];
|
||||
@@ -2121,10 +2124,7 @@ mod tests {
|
||||
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
|
||||
let client = generate_dummy_client_with_spec_and_accounts(
|
||||
Spec::new_test_round_block_reward_contract,
|
||||
None,
|
||||
);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_test_round_block_reward_contract);
|
||||
engine.register_client(Arc::downgrade(&client) as _);
|
||||
|
||||
// step 2
|
||||
@@ -2144,7 +2144,7 @@ mod tests {
|
||||
let b1 = b1.close_and_lock().unwrap();
|
||||
|
||||
// since the block is empty it isn't sealed and we generate empty steps
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
||||
engine.step();
|
||||
|
||||
@@ -2182,7 +2182,7 @@ mod tests {
|
||||
let engine = &*spec.engine;
|
||||
|
||||
let addr1 = accounts[0];
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||
|
||||
let mut header: Header = Header::default();
|
||||
let empty_step = empty_step(engine, 1, &header.parent_hash());
|
||||
@@ -2263,7 +2263,7 @@ mod tests {
|
||||
header.set_author(accounts[0]);
|
||||
|
||||
// when
|
||||
engine.set_signer(tap.clone(), accounts[1], "0".into());
|
||||
engine.set_signer(Box::new((tap.clone(), accounts[1], "0".into())));
|
||||
let empty_steps = vec![
|
||||
sealed_empty_step(&*engine, 1, &parent.hash()),
|
||||
sealed_empty_step(&*engine, 1, &parent.hash()),
|
||||
@@ -2300,9 +2300,9 @@ mod tests {
|
||||
header.set_author(accounts[0]);
|
||||
|
||||
// when
|
||||
engine.set_signer(tap.clone(), accounts[1], "0".into());
|
||||
engine.set_signer(Box::new((tap.clone(), accounts[1], "0".into())));
|
||||
let es1 = sealed_empty_step(&*engine, 1, &parent.hash());
|
||||
engine.set_signer(tap.clone(), accounts[0], "1".into());
|
||||
engine.set_signer(Box::new((tap.clone(), accounts[0], "1".into())));
|
||||
let es2 = sealed_empty_step(&*engine, 2, &parent.hash());
|
||||
|
||||
let mut empty_steps = vec![es2, es1];
|
||||
|
||||
@@ -16,19 +16,18 @@
|
||||
|
||||
//! A blockchain engine that supports a basic, non-BFT proof-of-authority.
|
||||
|
||||
use std::sync::{Weak, Arc};
|
||||
use ethereum_types::{H256, H520, Address};
|
||||
use std::sync::Weak;
|
||||
use ethereum_types::{H256, H520};
|
||||
use parking_lot::RwLock;
|
||||
use ethkey::{self, Password, Signature};
|
||||
use account_provider::AccountProvider;
|
||||
use ethkey::{self, Signature};
|
||||
use block::*;
|
||||
use engines::{Engine, Seal, ConstructedVerifier, EngineError};
|
||||
use engines::signer::EngineSigner;
|
||||
use error::{BlockError, Error};
|
||||
use ethjson;
|
||||
use client::EngineClient;
|
||||
use machine::{AuxiliaryData, Call, EthereumMachine};
|
||||
use types::header::{Header, ExtendedHeader};
|
||||
use super::signer::EngineSigner;
|
||||
use super::validator_set::{ValidatorSet, SimpleList, new_validator_set};
|
||||
|
||||
/// `BasicAuthority` params.
|
||||
@@ -76,7 +75,7 @@ fn verify_external(header: &Header, validators: &ValidatorSet) -> Result<(), Err
|
||||
/// Engine using `BasicAuthority`, trivial proof-of-authority consensus.
|
||||
pub struct BasicAuthority {
|
||||
machine: EthereumMachine,
|
||||
signer: RwLock<EngineSigner>,
|
||||
signer: RwLock<Option<Box<EngineSigner>>>,
|
||||
validators: Box<ValidatorSet>,
|
||||
}
|
||||
|
||||
@@ -85,7 +84,7 @@ impl BasicAuthority {
|
||||
pub fn new(our_params: BasicAuthorityParams, machine: EthereumMachine) -> Self {
|
||||
BasicAuthority {
|
||||
machine: machine,
|
||||
signer: Default::default(),
|
||||
signer: RwLock::new(None),
|
||||
validators: new_validator_set(our_params.validators),
|
||||
}
|
||||
}
|
||||
@@ -190,12 +189,16 @@ impl Engine<EthereumMachine> for BasicAuthority {
|
||||
self.validators.register_client(client);
|
||||
}
|
||||
|
||||
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: Password) {
|
||||
self.signer.write().set(ap, address, password);
|
||||
fn set_signer(&self, signer: Box<EngineSigner>) {
|
||||
*self.signer.write() = Some(signer);
|
||||
}
|
||||
|
||||
fn sign(&self, hash: H256) -> Result<Signature, Error> {
|
||||
Ok(self.signer.read().sign(hash)?)
|
||||
Ok(self.signer.read()
|
||||
.as_ref()
|
||||
.ok_or_else(|| ethkey::Error::InvalidAddress)?
|
||||
.sign(hash)?
|
||||
)
|
||||
}
|
||||
|
||||
fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> {
|
||||
@@ -214,7 +217,7 @@ mod tests {
|
||||
use ethereum_types::H520;
|
||||
use block::*;
|
||||
use test_helpers::get_temp_state_db;
|
||||
use account_provider::AccountProvider;
|
||||
use accounts::AccountProvider;
|
||||
use types::header::Header;
|
||||
use spec::Spec;
|
||||
use engines::Seal;
|
||||
@@ -257,7 +260,7 @@ mod tests {
|
||||
|
||||
let spec = new_test_authority();
|
||||
let engine = &*spec.engine;
|
||||
engine.set_signer(Arc::new(tap), addr, "".into());
|
||||
engine.set_signer(Box::new((Arc::new(tap), addr, "".into())));
|
||||
let genesis_header = spec.genesis_header();
|
||||
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
@@ -275,7 +278,7 @@ mod tests {
|
||||
|
||||
let engine = new_test_authority().engine;
|
||||
assert!(!engine.seals_internally().unwrap());
|
||||
engine.set_signer(Arc::new(tap), authority, "".into());
|
||||
engine.set_signer(Box::new((Arc::new(tap), authority, "".into())));
|
||||
assert!(engine.seals_internally().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,17 +170,14 @@ mod test {
|
||||
use client::PrepareOpenBlock;
|
||||
use ethereum_types::U256;
|
||||
use spec::Spec;
|
||||
use test_helpers::generate_dummy_client_with_spec_and_accounts;
|
||||
use test_helpers::generate_dummy_client_with_spec;
|
||||
|
||||
use engines::SystemOrCodeCallKind;
|
||||
use super::{BlockRewardContract, RewardKind};
|
||||
|
||||
#[test]
|
||||
fn block_reward_contract() {
|
||||
let client = generate_dummy_client_with_spec_and_accounts(
|
||||
Spec::new_test_round_block_reward_contract,
|
||||
None,
|
||||
);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_test_round_block_reward_contract);
|
||||
|
||||
let machine = Spec::new_test_machine();
|
||||
|
||||
|
||||
@@ -20,16 +20,17 @@ mod authority_round;
|
||||
mod basic_authority;
|
||||
mod instant_seal;
|
||||
mod null_engine;
|
||||
mod signer;
|
||||
mod validator_set;
|
||||
|
||||
pub mod block_reward;
|
||||
pub mod signer;
|
||||
|
||||
pub use self::authority_round::AuthorityRound;
|
||||
pub use self::basic_authority::BasicAuthority;
|
||||
pub use self::epoch::{EpochVerifier, Transition as EpochTransition};
|
||||
pub use self::instant_seal::{InstantSeal, InstantSealParams};
|
||||
pub use self::null_engine::NullEngine;
|
||||
pub use self::signer::EngineSigner;
|
||||
|
||||
// TODO [ToDr] Remove re-export (#10130)
|
||||
pub use types::engines::ForkChoice;
|
||||
@@ -39,7 +40,6 @@ use std::sync::{Weak, Arc};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::{fmt, error};
|
||||
|
||||
use account_provider::AccountProvider;
|
||||
use builtin::Builtin;
|
||||
use vm::{EnvInfo, Schedule, CreateContractAddress, CallType, ActionValue};
|
||||
use error::Error;
|
||||
@@ -49,7 +49,7 @@ use snapshot::SnapshotComponents;
|
||||
use spec::CommonParams;
|
||||
use types::transaction::{self, UnverifiedTransaction, SignedTransaction};
|
||||
|
||||
use ethkey::{Password, Signature};
|
||||
use ethkey::{Signature};
|
||||
use parity_machine::{Machine, LocalizedMachine as Localized, TotalScoredHeader};
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use unexpected::{Mismatch, OutOfBounds};
|
||||
@@ -380,8 +380,8 @@ pub trait Engine<M: Machine>: Sync + Send {
|
||||
/// Takes a header of a fully verified block.
|
||||
fn is_proposal(&self, _verified_header: &M::Header) -> bool { false }
|
||||
|
||||
/// Register an account which signs consensus messages.
|
||||
fn set_signer(&self, _account_provider: Arc<AccountProvider>, _address: Address, _password: Password) {}
|
||||
/// Register a component which signs consensus messages.
|
||||
fn set_signer(&self, _signer: Box<EngineSigner>) {}
|
||||
|
||||
/// Sign using the EngineSigner, to be used for consensus tx signing.
|
||||
fn sign(&self, _hash: H256) -> Result<Signature, M::Error> { unimplemented!() }
|
||||
|
||||
@@ -16,49 +16,68 @@
|
||||
|
||||
//! A signer used by Engines which need to sign messages.
|
||||
|
||||
use std::sync::Arc;
|
||||
use ethereum_types::{H256, Address};
|
||||
use ethkey::{Password, Signature};
|
||||
use account_provider::{self, AccountProvider};
|
||||
use ethkey::{self, Signature};
|
||||
|
||||
/// Everything that an Engine needs to sign messages.
|
||||
pub struct EngineSigner {
|
||||
account_provider: Arc<AccountProvider>,
|
||||
address: Option<Address>,
|
||||
password: Option<Password>,
|
||||
pub trait EngineSigner: Send + Sync {
|
||||
/// Sign a consensus message hash.
|
||||
fn sign(&self, hash: H256) -> Result<Signature, ethkey::Error>;
|
||||
|
||||
/// Signing address
|
||||
fn address(&self) -> Address;
|
||||
}
|
||||
|
||||
impl Default for EngineSigner {
|
||||
fn default() -> Self {
|
||||
EngineSigner {
|
||||
account_provider: Arc::new(AccountProvider::transient_provider()),
|
||||
address: Default::default(),
|
||||
password: Default::default(),
|
||||
/// Creates a new `EngineSigner` from given key pair.
|
||||
pub fn from_keypair(keypair: ethkey::KeyPair) -> Box<EngineSigner> {
|
||||
Box::new(Signer(keypair))
|
||||
}
|
||||
|
||||
struct Signer(ethkey::KeyPair);
|
||||
|
||||
impl EngineSigner for Signer {
|
||||
fn sign(&self, hash: H256) -> Result<Signature, ethkey::Error> {
|
||||
ethkey::sign(self.0.secret(), &hash)
|
||||
}
|
||||
|
||||
fn address(&self) -> Address {
|
||||
self.0.address()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_signer {
|
||||
use std::sync::Arc;
|
||||
|
||||
use ethkey::Password;
|
||||
use accounts::{self, AccountProvider, SignError};
|
||||
|
||||
use super::*;
|
||||
|
||||
impl EngineSigner for (Arc<AccountProvider>, Address, Password) {
|
||||
fn sign(&self, hash: H256) -> Result<Signature, ethkey::Error> {
|
||||
match self.0.sign(self.1, Some(self.2.clone()), hash) {
|
||||
Err(SignError::NotUnlocked) => unreachable!(),
|
||||
Err(SignError::NotFound) => Err(ethkey::Error::InvalidAddress),
|
||||
Err(SignError::Hardware(err)) => {
|
||||
warn!("Error using hardware wallet for engine: {:?}", err);
|
||||
Err(ethkey::Error::InvalidSecret)
|
||||
},
|
||||
Err(SignError::SStore(accounts::Error::EthKey(err))) => Err(err),
|
||||
Err(SignError::SStore(accounts::Error::EthKeyCrypto(err))) => {
|
||||
warn!("Low level crypto error: {:?}", err);
|
||||
Err(ethkey::Error::InvalidSecret)
|
||||
},
|
||||
Err(SignError::SStore(err)) => {
|
||||
warn!("Error signing for engine: {:?}", err);
|
||||
Err(ethkey::Error::InvalidSignature)
|
||||
},
|
||||
Ok(ok) => Ok(ok),
|
||||
}
|
||||
}
|
||||
|
||||
fn address(&self) -> Address {
|
||||
self.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EngineSigner {
|
||||
/// Set up the signer to sign with given address and password.
|
||||
pub fn set(&mut self, ap: Arc<AccountProvider>, address: Address, password: Password) {
|
||||
self.account_provider = ap;
|
||||
self.address = Some(address);
|
||||
self.password = Some(password);
|
||||
debug!(target: "poa", "Setting Engine signer to {}", address);
|
||||
}
|
||||
|
||||
/// Sign a consensus message hash.
|
||||
pub fn sign(&self, hash: H256) -> Result<Signature, account_provider::SignError> {
|
||||
self.account_provider.sign(self.address.unwrap_or_else(Default::default), self.password.clone(), hash)
|
||||
}
|
||||
|
||||
/// Signing address.
|
||||
pub fn address(&self) -> Option<Address> {
|
||||
self.address.clone()
|
||||
}
|
||||
|
||||
/// Check if the signing address was set.
|
||||
pub fn is_some(&self) -> bool {
|
||||
self.address.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,10 +141,10 @@ mod tests {
|
||||
use rlp::encode;
|
||||
use spec::Spec;
|
||||
use types::header::Header;
|
||||
use account_provider::AccountProvider;
|
||||
use miner::MinerService;
|
||||
use accounts::AccountProvider;
|
||||
use miner::{self, MinerService};
|
||||
use types::ids::BlockId;
|
||||
use test_helpers::generate_dummy_client_with_spec_and_accounts;
|
||||
use test_helpers::generate_dummy_client_with_spec;
|
||||
use call_contract::CallContract;
|
||||
use client::{BlockChainClient, ChainInfo, BlockInfo};
|
||||
use super::super::ValidatorSet;
|
||||
@@ -152,7 +152,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn fetches_validators() {
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, None);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_validator_contract);
|
||||
let vc = Arc::new(ValidatorContract::new("0000000000000000000000000000000000000005".parse::<Address>().unwrap()));
|
||||
vc.register_client(Arc::downgrade(&client) as _);
|
||||
let last_hash = client.best_block_header().hash();
|
||||
@@ -164,13 +164,14 @@ mod tests {
|
||||
fn reports_validators() {
|
||||
let tap = Arc::new(AccountProvider::transient_provider());
|
||||
let v1 = tap.insert_account(keccak("1").into(), &"".into()).unwrap();
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, Some(tap.clone()));
|
||||
let client = generate_dummy_client_with_spec(Spec::new_validator_contract);
|
||||
client.engine().register_client(Arc::downgrade(&client) as _);
|
||||
let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
|
||||
|
||||
// Make sure reporting can be done.
|
||||
client.miner().set_gas_range_target((1_000_000.into(), 1_000_000.into()));
|
||||
client.miner().set_author(v1, Some("".into())).unwrap();
|
||||
let signer = Box::new((tap.clone(), v1, "".into()));
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
|
||||
// Check a block that is a bit in future, reject it but don't report the validator.
|
||||
let mut header = Header::default();
|
||||
|
||||
@@ -150,15 +150,15 @@ mod tests {
|
||||
use std::sync::Arc;
|
||||
use std::collections::BTreeMap;
|
||||
use hash::keccak;
|
||||
use account_provider::AccountProvider;
|
||||
use accounts::AccountProvider;
|
||||
use client::{BlockChainClient, ChainInfo, BlockInfo, ImportBlock};
|
||||
use engines::EpochChange;
|
||||
use engines::validator_set::ValidatorSet;
|
||||
use ethkey::Secret;
|
||||
use types::header::Header;
|
||||
use miner::MinerService;
|
||||
use miner::{self, MinerService};
|
||||
use spec::Spec;
|
||||
use test_helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data};
|
||||
use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data};
|
||||
use types::ids::BlockId;
|
||||
use ethereum_types::Address;
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
@@ -171,26 +171,29 @@ mod tests {
|
||||
let s0: Secret = keccak("0").into();
|
||||
let v0 = tap.insert_account(s0.clone(), &"".into()).unwrap();
|
||||
let v1 = tap.insert_account(keccak("1").into(), &"".into()).unwrap();
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_multi, Some(tap));
|
||||
let client = generate_dummy_client_with_spec(Spec::new_validator_multi);
|
||||
client.engine().register_client(Arc::downgrade(&client) as _);
|
||||
|
||||
// Make sure txs go through.
|
||||
client.miner().set_gas_range_target((1_000_000.into(), 1_000_000.into()));
|
||||
|
||||
// Wrong signer for the first block.
|
||||
client.miner().set_author(v1, Some("".into())).unwrap();
|
||||
let signer = Box::new((tap.clone(), v1, "".into()));
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
client.transact_contract(Default::default(), Default::default()).unwrap();
|
||||
::client::EngineClient::update_sealing(&*client);
|
||||
assert_eq!(client.chain_info().best_block_number, 0);
|
||||
// Right signer for the first block.
|
||||
client.miner().set_author(v0, Some("".into())).unwrap();
|
||||
let signer = Box::new((tap.clone(), v0, "".into()));
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
::client::EngineClient::update_sealing(&*client);
|
||||
assert_eq!(client.chain_info().best_block_number, 1);
|
||||
// This time v0 is wrong.
|
||||
client.transact_contract(Default::default(), Default::default()).unwrap();
|
||||
::client::EngineClient::update_sealing(&*client);
|
||||
assert_eq!(client.chain_info().best_block_number, 1);
|
||||
client.miner().set_author(v1, Some("".into())).unwrap();
|
||||
let signer = Box::new((tap.clone(), v1, "".into()));
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
::client::EngineClient::update_sealing(&*client);
|
||||
assert_eq!(client.chain_info().best_block_number, 2);
|
||||
// v1 is still good.
|
||||
|
||||
@@ -445,19 +445,19 @@ mod tests {
|
||||
use ethereum_types::Address;
|
||||
use types::ids::BlockId;
|
||||
use spec::Spec;
|
||||
use account_provider::AccountProvider;
|
||||
use accounts::AccountProvider;
|
||||
use types::transaction::{Transaction, Action};
|
||||
use client::{ChainInfo, BlockInfo, ImportBlock};
|
||||
use ethkey::Secret;
|
||||
use miner::MinerService;
|
||||
use test_helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data};
|
||||
use miner::{self, MinerService};
|
||||
use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data};
|
||||
use super::super::ValidatorSet;
|
||||
use super::{ValidatorSafeContract, EVENT_NAME_HASH};
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
|
||||
#[test]
|
||||
fn fetches_validators() {
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract);
|
||||
let vc = Arc::new(ValidatorSafeContract::new("0000000000000000000000000000000000000005".parse::<Address>().unwrap()));
|
||||
vc.register_client(Arc::downgrade(&client) as _);
|
||||
let last_hash = client.best_block_header().hash();
|
||||
@@ -472,11 +472,12 @@ mod tests {
|
||||
let v0 = tap.insert_account(s0.clone(), &"".into()).unwrap();
|
||||
let v1 = tap.insert_account(keccak("0").into(), &"".into()).unwrap();
|
||||
let chain_id = Spec::new_validator_safe_contract().chain_id();
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap));
|
||||
let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract);
|
||||
client.engine().register_client(Arc::downgrade(&client) as _);
|
||||
let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
|
||||
let signer = Box::new((tap.clone(), v1, "".into()));
|
||||
|
||||
client.miner().set_author(v1, Some("".into())).unwrap();
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
// Remove "1" validator.
|
||||
let tx = Transaction {
|
||||
nonce: 0.into(),
|
||||
@@ -504,11 +505,13 @@ mod tests {
|
||||
assert_eq!(client.chain_info().best_block_number, 1);
|
||||
|
||||
// Switch to the validator that is still there.
|
||||
client.miner().set_author(v0, Some("".into())).unwrap();
|
||||
let signer = Box::new((tap.clone(), v0, "".into()));
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
::client::EngineClient::update_sealing(&*client);
|
||||
assert_eq!(client.chain_info().best_block_number, 2);
|
||||
// Switch back to the added validator, since the state is updated.
|
||||
client.miner().set_author(v1, Some("".into())).unwrap();
|
||||
let signer = Box::new((tap.clone(), v1, "".into()));
|
||||
client.miner().set_author(miner::Author::Sealer(signer));
|
||||
let tx = Transaction {
|
||||
nonce: 2.into(),
|
||||
gas_price: 0.into(),
|
||||
@@ -539,7 +542,7 @@ mod tests {
|
||||
use types::header::Header;
|
||||
use types::log_entry::LogEntry;
|
||||
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract);
|
||||
let engine = client.engine().clone();
|
||||
let validator_contract = "0000000000000000000000000000000000000005".parse::<Address>().unwrap();
|
||||
|
||||
@@ -576,7 +579,7 @@ mod tests {
|
||||
use types::header::Header;
|
||||
use engines::{EpochChange, Proof};
|
||||
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
|
||||
let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract);
|
||||
let engine = client.engine().clone();
|
||||
|
||||
let mut new_header = Header::default();
|
||||
|
||||
Reference in New Issue
Block a user