hold password in engine, add rpc
This commit is contained in:
parent
4ef5badcea
commit
34d5017950
@ -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<AccountProvider>) {}
|
||||
|
||||
/// 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)
|
||||
|
@ -66,6 +66,8 @@ pub struct Tendermint {
|
||||
step_service: IoService<Step>,
|
||||
/// Address to be used as authority.
|
||||
authority: RwLock<Address>,
|
||||
/// Password used for signing messages.
|
||||
password: RwLock<Option<String>>,
|
||||
/// Blockchain height.
|
||||
height: AtomicUsize,
|
||||
/// Consensus round.
|
||||
@ -98,6 +100,7 @@ impl Tendermint {
|
||||
builtins: builtins,
|
||||
step_service: try!(IoService::<Step>::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<BlockHash>) -> Option<Bytes> {
|
||||
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::<ClientIoMessage>::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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -116,6 +116,12 @@ impl<C, M, F> ParitySet for ParitySetClient<C, M, F> where
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_sealer(&self, address: H160, password: String) -> Result<bool, Error> {
|
||||
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<bool, Error> {
|
||||
try!(self.active());
|
||||
|
||||
|
@ -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<U256>,
|
||||
gas_range_target: RwLock<(U256, U256)>,
|
||||
password: RwLock<String>,
|
||||
author: RwLock<Address>,
|
||||
extra_data: RwLock<Bytes>,
|
||||
limit: RwLock<usize>,
|
||||
@ -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;
|
||||
}
|
||||
|
@ -44,6 +44,10 @@ build_rpc_trait! {
|
||||
#[rpc(name = "parity_setAuthor")]
|
||||
fn set_author(&self, H160) -> Result<bool, Error>;
|
||||
|
||||
/// Sets account for signing consensus messages.
|
||||
#[rpc(name = "parity_setSealer")]
|
||||
fn set_sealer(&self, H160, String) -> Result<bool, Error>;
|
||||
|
||||
/// Sets the limits for transaction queue.
|
||||
#[rpc(name = "parity_setTransactionsLimit")]
|
||||
fn set_transactions_limit(&self, usize) -> Result<bool, Error>;
|
||||
|
Loading…
Reference in New Issue
Block a user