From 34d5017950b2a9f0609146a516303974b036d9ce Mon Sep 17 00:00:00 2001 From: keorn Date: Wed, 30 Nov 2016 12:59:33 +0000 Subject: [PATCH] hold password in engine, add rpc --- ethcore/src/engines/mod.rs | 3 +++ ethcore/src/engines/tendermint/mod.rs | 21 ++++++++++++++++----- ethcore/src/miner/miner.rs | 15 ++++++++++++++- ethcore/src/miner/mod.rs | 3 +++ rpc/src/v1/impls/parity_set.rs | 6 ++++++ rpc/src/v1/tests/helpers/miner_service.rs | 9 +++++++++ rpc/src/v1/traits/parity_set.rs | 4 ++++ 7 files changed, 55 insertions(+), 6 deletions(-) diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 91557f8c3..67e89b834 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -187,6 +187,9 @@ pub trait Engine : Sync + Send { /// Add an account provider useful for Engines that sign stuff. fn register_account_provider(&self, _account_provider: Arc) {} + /// Register an account which signs consensus messages. + fn set_signer(&self, _address: Address, _password: String) {} + /// Check if new block should be chosen as the one in chain. fn is_new_best_block(&self, best_total_difficulty: U256, _best_header: HeaderView, parent_details: &BlockDetails, new_header: &HeaderView) -> bool { ethash::is_new_best_block(best_total_difficulty, parent_details, new_header) diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 28aae2b10..452aed8aa 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -66,6 +66,8 @@ pub struct Tendermint { step_service: IoService, /// Address to be used as authority. authority: RwLock
, + /// Password used for signing messages. + password: RwLock>, /// Blockchain height. height: AtomicUsize, /// Consensus round. @@ -98,6 +100,7 @@ impl Tendermint { builtins: builtins, step_service: try!(IoService::::start()), authority: RwLock::new(Address::default()), + password: RwLock::new(None), height: AtomicUsize::new(1), round: AtomicUsize::new(0), step: RwLock::new(Step::Propose), @@ -144,7 +147,7 @@ impl Tendermint { fn generate_message(&self, block_hash: Option) -> Option { if let Some(ref ap) = *self.account_provider.lock() { message_full_rlp( - |mh| ap.sign(*self.authority.read(), None, mh).ok().map(H520::from), + |mh| ap.sign(*self.authority.read(), self.password.read().clone(), mh).ok().map(H520::from), self.height.load(AtomicOrdering::SeqCst), self.round.load(AtomicOrdering::SeqCst), *self.step.read(), @@ -333,7 +336,7 @@ impl Engine for Tendermint { let round = self.round.load(AtomicOrdering::SeqCst); let bh = Some(header.bare_hash()); let vote_info = message_info_rlp(height, round, Step::Propose, bh); - if let Ok(signature) = ap.sign(*author, None, vote_info.sha3()).map(H520::from) { + if let Ok(signature) = ap.sign(*author, self.password.read().clone(), vote_info.sha3()).map(H520::from) { self.votes.vote(ConsensusMessage { signature: signature, height: height, round: round, step: Step::Propose, block_hash: bh }, *author); *self.proposal.write() = Some(header.bare_hash()); Some(vec![ @@ -472,6 +475,11 @@ impl Engine for Tendermint { t.sender().map(|_|()) // Perform EC recovery and cache sender } + fn set_signer(&self, address: Address, password: String) { + *self.authority.write() = address; + *self.password.write() = Some(password); + } + fn is_new_best_block(&self, _best_total_difficulty: U256, best_header: HeaderView, _parent_details: &BlockDetails, new_header: &HeaderView) -> bool { let new_signatures = new_header.seal().get(2).expect("Tendermint seal should have three elements.").len(); let best_signatures = best_header.seal().get(2).expect("Tendermint seal should have three elements.").len(); @@ -695,7 +703,6 @@ mod tests { let proposal = Some(b.header().bare_hash()); // Register IoHandler remembers messages. - seal[2] = precommit_signatures(&tap, h, r, Some(b.header().bare_hash()), v0, v1); let io_service = IoService::::start().unwrap(); let test_io = TestIo::new(); io_service.register_handler(test_io.clone()).unwrap(); @@ -708,8 +715,12 @@ mod tests { vote(&engine, |mh| tap.sign(v1, None, mh).ok().map(H520::from), h, r, Step::Precommit, proposal); vote(&engine, |mh| tap.sign(v0, None, mh).ok().map(H520::from), h, r, Step::Precommit, proposal); + // Wait a bit for async stuff. ::std::thread::sleep(::std::time::Duration::from_millis(500)); - assert_eq!(test_io.received.read()[5], ClientIoMessage::SubmitSeal(proposal.unwrap(), seal)); - println!("{:?}", *test_io.received.read()); + seal[2] = precommit_signatures(&tap, h, r, Some(b.header().bare_hash()), v0, v1); + let first = test_io.received.read()[5] == ClientIoMessage::SubmitSeal(proposal.unwrap(), seal.clone()); + seal[2] = precommit_signatures(&tap, h, r, Some(b.header().bare_hash()), v1, v0); + let second = test_io.received.read()[5] == ClientIoMessage::SubmitSeal(proposal.unwrap(), seal); + assert!(first ^ second); } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 5aaa5b479..b1984dd43 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -19,7 +19,7 @@ use std::time::{Instant, Duration}; use util::*; use util::using_queue::{UsingQueue, GetAction}; -use account_provider::AccountProvider; +use account_provider::{AccountProvider, Error as AccountError}; use views::{BlockView, HeaderView}; use header::Header; use state::{State, CleanupMode}; @@ -735,6 +735,19 @@ impl MinerService for Miner { *self.author.write() = author; } + fn set_signer(&self, address: Address, password: String) -> Result<(), AccountError> { + if self.seals_internally { + if let Some(ref ap) = self.accounts { + try!(ap.sign(address.clone(), Some(password.clone()), Default::default())); + } + let mut sealing_work = self.sealing_work.lock(); + sealing_work.enabled = self.engine.is_sealer(&address).unwrap_or(false); + *self.author.write() = address; + self.engine.set_signer(address, password); + } + Ok(()) + } + fn set_extra_data(&self, extra_data: Bytes) { *self.extra_data.write() = extra_data; } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 1fb2244fd..89937e115 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -76,6 +76,9 @@ pub trait MinerService : Send + Sync { /// Set the author that we will seal blocks as. fn set_author(&self, author: Address); + /// Set info necessary to sign consensus messages. + fn set_signer(&self, address: Address, password: String) -> Result<(), ::account_provider::Error>; + /// Get the extra_data that we will seal blocks with. fn extra_data(&self) -> Bytes; diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index 47634d518..11bc48268 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -116,6 +116,12 @@ impl ParitySet for ParitySetClient where Ok(true) } + fn set_sealer(&self, address: H160, password: String) -> Result { + try!(self.active()); + try!(take_weak!(self.miner).set_signer(address.into(), password).map_err(Into::into).map_err(errors::from_password_error)); + Ok(true) + } + fn set_transactions_limit(&self, limit: usize) -> Result { try!(self.active()); diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index ad55faa7b..87efd2425 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -25,6 +25,7 @@ use ethcore::header::BlockNumber; use ethcore::transaction::SignedTransaction; use ethcore::receipt::{Receipt, RichReceipt}; use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus}; +use ethcore::account_provider::Error as AccountError; /// Test miner service. pub struct TestMinerService { @@ -43,6 +44,7 @@ pub struct TestMinerService { min_gas_price: RwLock, gas_range_target: RwLock<(U256, U256)>, + password: RwLock, author: RwLock
, extra_data: RwLock, limit: RwLock, @@ -61,6 +63,7 @@ impl Default for TestMinerService { min_gas_price: RwLock::new(U256::from(20_000_000)), gas_range_target: RwLock::new((U256::from(12345), U256::from(54321))), author: RwLock::new(Address::zero()), + password: RwLock::new(String::new()), extra_data: RwLock::new(vec![1, 2, 3, 4]), limit: RwLock::new(1024), tx_gas_limit: RwLock::new(!U256::zero()), @@ -83,6 +86,12 @@ impl MinerService for TestMinerService { *self.author.write() = author; } + fn set_signer(&self, address: Address, password: String) -> Result<(), AccountError> { + *self.author.write() = address; + *self.password.write() = password; + Ok(()) + } + fn set_extra_data(&self, extra_data: Bytes) { *self.extra_data.write() = extra_data; } diff --git a/rpc/src/v1/traits/parity_set.rs b/rpc/src/v1/traits/parity_set.rs index c83eff022..89d92e043 100644 --- a/rpc/src/v1/traits/parity_set.rs +++ b/rpc/src/v1/traits/parity_set.rs @@ -44,6 +44,10 @@ build_rpc_trait! { #[rpc(name = "parity_setAuthor")] fn set_author(&self, H160) -> Result; + /// Sets account for signing consensus messages. + #[rpc(name = "parity_setSealer")] + fn set_sealer(&self, H160, String) -> Result; + /// Sets the limits for transaction queue. #[rpc(name = "parity_setTransactionsLimit")] fn set_transactions_limit(&self, usize) -> Result;