update Signature and ipc usage
This commit is contained in:
parent
e7a9bf4df8
commit
a4ba7262ad
@ -42,7 +42,7 @@ pub trait ChainNotify : Send + Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// fires when chain broadcasts a message
|
/// fires when chain broadcasts a message
|
||||||
fn broadcast(&self, _data: &[u8]) {
|
fn broadcast(&self, _data: Vec<u8>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,12 +25,12 @@ use time::precise_time_ns;
|
|||||||
use util::{journaldb, rlp, Bytes, View, PerfTimer, Itertools, Mutex, RwLock};
|
use util::{journaldb, rlp, Bytes, View, PerfTimer, Itertools, Mutex, RwLock};
|
||||||
use util::journaldb::JournalDB;
|
use util::journaldb::JournalDB;
|
||||||
use util::rlp::{UntrustedRlp};
|
use util::rlp::{UntrustedRlp};
|
||||||
use util::ec::recover;
|
use util::{U256, H256, H520, Address, H2048, Uint};
|
||||||
use util::{U256, H256, Address, H2048, Uint};
|
|
||||||
use util::sha3::*;
|
use util::sha3::*;
|
||||||
use util::kvdb::*;
|
use util::kvdb::*;
|
||||||
|
|
||||||
// other
|
// other
|
||||||
|
use ethkey::recover;
|
||||||
use io::*;
|
use io::*;
|
||||||
use views::{BlockView, HeaderView, BodyView};
|
use views::{BlockView, HeaderView, BodyView};
|
||||||
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult};
|
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult};
|
||||||
@ -1031,12 +1031,11 @@ impl BlockChainClient for Client {
|
|||||||
// TODO: Make it an actual queue, return errors.
|
// TODO: Make it an actual queue, return errors.
|
||||||
fn queue_infinity_message(&self, message: Bytes) {
|
fn queue_infinity_message(&self, message: Bytes) {
|
||||||
let full_rlp = UntrustedRlp::new(&message);
|
let full_rlp = UntrustedRlp::new(&message);
|
||||||
if let Ok(signature) = full_rlp.val_at(0) {
|
if let Ok(signature) = full_rlp.val_at::<H520>(0) {
|
||||||
if let Ok(message) = full_rlp.val_at::<Vec<_>>(1) {
|
if let Ok(message) = full_rlp.at(1) {
|
||||||
let message_rlp = UntrustedRlp::new(&message);
|
if let Ok(pub_key) = recover(&signature.into(), &message.as_raw().sha3()) {
|
||||||
if let Ok(pub_key) = recover(&signature, &message.sha3()) {
|
if let Ok(new_message) = self.engine.handle_message(pub_key.sha3().into(), message) {
|
||||||
if let Ok(new_message) = self.engine.handle_message(pub_key.sha3().into(), message_rlp) {
|
self.notify(|notify| notify.broadcast(new_message.clone()));
|
||||||
self.notify(|notify| notify.broadcast(&new_message));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,9 @@
|
|||||||
//! Voting on a hash, where each vote has to come from a set of addresses.
|
//! Voting on a hash, where each vote has to come from a set of addresses.
|
||||||
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use common::{HashSet, RwLock, H256, Signature, Address, Error, ec, Hashable};
|
use common::{HashSet, RwLock, H256, Address, Error, Hashable};
|
||||||
use super::EngineError;
|
use super::EngineError;
|
||||||
|
use ethkey::{recover, Signature};
|
||||||
|
|
||||||
/// Collect votes on a hash.
|
/// Collect votes on a hash.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -57,7 +58,7 @@ impl ProposeCollect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn can_vote(&self, signature: &Signature) -> Result<(), Error> {
|
fn can_vote(&self, signature: &Signature) -> Result<(), Error> {
|
||||||
let signer = Address::from(try!(ec::recover(&signature, &self.hash)).sha3());
|
let signer = Address::from(try!(recover(&signature, &self.hash)).sha3());
|
||||||
match self.voters.contains(&signer) {
|
match self.voters.contains(&signer) {
|
||||||
false => try!(Err(EngineError::UnauthorisedVoter)),
|
false => try!(Err(EngineError::UnauthorisedVoter)),
|
||||||
true => Ok(()),
|
true => Ok(()),
|
||||||
@ -108,18 +109,18 @@ mod tests {
|
|||||||
|
|
||||||
// Unapproved voter.
|
// Unapproved voter.
|
||||||
let signature = tap.sign(addr3, bare_hash).unwrap();
|
let signature = tap.sign(addr3, bare_hash).unwrap();
|
||||||
assert!(!vote.vote(&signature.into()));
|
assert!(!vote.vote(&signature));
|
||||||
assert!(vote.winner().is_none());
|
assert!(vote.winner().is_none());
|
||||||
// First good vote.
|
// First good vote.
|
||||||
let signature = tap.sign(addr1, bare_hash).unwrap();
|
let signature = tap.sign(addr1, bare_hash).unwrap();
|
||||||
assert!(vote.vote(&signature.into()));
|
assert!(vote.vote(&signature));
|
||||||
assert_eq!(vote.winner().unwrap(), bare_hash);
|
assert_eq!(vote.winner().unwrap(), bare_hash);
|
||||||
// Voting again is ineffective.
|
// Voting again is ineffective.
|
||||||
let signature = tap.sign(addr1, bare_hash).unwrap();
|
let signature = tap.sign(addr1, bare_hash).unwrap();
|
||||||
assert!(!vote.vote(&signature.into()));
|
assert!(!vote.vote(&signature));
|
||||||
// Second valid vote.
|
// Second valid vote.
|
||||||
let signature = tap.sign(addr2, bare_hash).unwrap();
|
let signature = tap.sign(addr2, bare_hash).unwrap();
|
||||||
assert!(vote.vote(&signature.into()));
|
assert!(vote.vote(&signature));
|
||||||
assert_eq!(vote.winner().unwrap(), bare_hash);
|
assert_eq!(vote.winner().unwrap(), bare_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
//! Voting on hashes, where each vote has to come from a set of public keys.
|
//! Voting on hashes, where each vote has to come from a set of public keys.
|
||||||
|
|
||||||
use super::EngineError;
|
use super::EngineError;
|
||||||
use common::{HashSet, HashMap, RwLock, H256, Signature, Address, Error, ec, Hashable};
|
use common::{HashSet, HashMap, RwLock, H256, Address, Error, Hashable};
|
||||||
|
use ethkey::{Signature, recover};
|
||||||
|
|
||||||
/// Signed voting on hashes.
|
/// Signed voting on hashes.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -49,11 +50,11 @@ impl SignedVote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Vote on hash using the signed hash, true if vote counted.
|
/// Vote on hash using the signed hash, true if vote counted.
|
||||||
pub fn vote(&self, bare_hash: H256, signature: &Signature) -> bool {
|
pub fn vote(&self, bare_hash: H256, signature: Signature) -> bool {
|
||||||
if !self.can_vote(&bare_hash, signature).is_ok() { return false; }
|
if !self.can_vote(&bare_hash, &signature).is_ok() { return false; }
|
||||||
let mut guard = self.votes.try_write().unwrap();
|
let mut guard = self.votes.try_write().unwrap();
|
||||||
let set = guard.entry(bare_hash.clone()).or_insert_with(|| HashSet::new());
|
let set = guard.entry(bare_hash.clone()).or_insert_with(|| HashSet::new());
|
||||||
if !set.insert(signature.clone()) { return false; }
|
if !set.insert(signature) { return false; }
|
||||||
// Set the winner if threshold is reached.
|
// Set the winner if threshold is reached.
|
||||||
if set.len() >= self.threshold {
|
if set.len() >= self.threshold {
|
||||||
let mut guard = self.winner.try_write().unwrap();
|
let mut guard = self.winner.try_write().unwrap();
|
||||||
@ -63,7 +64,7 @@ impl SignedVote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn can_vote(&self, bare_hash: &H256, signature: &Signature) -> Result<(), Error> {
|
fn can_vote(&self, bare_hash: &H256, signature: &Signature) -> Result<(), Error> {
|
||||||
let signer = Address::from(try!(ec::recover(&signature, bare_hash)).sha3());
|
let signer = Address::from(try!(recover(&signature, bare_hash)).sha3());
|
||||||
match self.voters.contains(&signer) {
|
match self.voters.contains(&signer) {
|
||||||
false => try!(Err(EngineError::UnauthorisedVoter)),
|
false => try!(Err(EngineError::UnauthorisedVoter)),
|
||||||
true => Ok(()),
|
true => Ok(()),
|
||||||
|
@ -106,7 +106,10 @@ impl Tendermint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prevote_message(&self, sender: Address, message: UntrustedRlp) -> Result<Bytes, Error> {
|
fn prevote_message(&self, sender: Address, message: UntrustedRlp) -> Result<Bytes, Error> {
|
||||||
try!(Err(EngineError::WrongStep))
|
match *self.our_params.s.try_write().unwrap() {
|
||||||
|
Step::Prevote(ref mut vote) => try!(Err(EngineError::WrongStep)),
|
||||||
|
_ => try!(Err(EngineError::WrongStep)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn threshold(&self) -> usize {
|
fn threshold(&self) -> usize {
|
||||||
@ -167,7 +170,7 @@ impl Engine for Tendermint {
|
|||||||
fn handle_message(&self, sender: Address, message: UntrustedRlp) -> Result<Bytes, Error> {
|
fn handle_message(&self, sender: Address, message: UntrustedRlp) -> Result<Bytes, Error> {
|
||||||
match try!(message.val_at(0)) {
|
match try!(message.val_at(0)) {
|
||||||
0u8 if sender == self.proposer() => self.propose_message(try!(message.at(1))),
|
0u8 if sender == self.proposer() => self.propose_message(try!(message.at(1))),
|
||||||
1 => self.prevote_message(sender, try!(message.at(1))),
|
1 if self.our_params.validators.contains(&sender) => self.prevote_message(sender, try!(message.at(1))),
|
||||||
_ => try!(Err(EngineError::UnknownStep)),
|
_ => try!(Err(EngineError::UnknownStep)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,6 +228,7 @@ mod tests {
|
|||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use super::Step;
|
use super::Step;
|
||||||
|
use ethkey::Signature;
|
||||||
|
|
||||||
/// Create a new test chain spec with `Tendermint` consensus engine.
|
/// Create a new test chain spec with `Tendermint` consensus engine.
|
||||||
/// Account "0".sha3() and "1".sha3() are a validators.
|
/// Account "0".sha3() and "1".sha3() are a validators.
|
||||||
@ -267,21 +271,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_do_signature_verification_fail() {
|
|
||||||
let engine = new_test_tendermint().engine;
|
|
||||||
let mut header: Header = Header::default();
|
|
||||||
header.set_seal(vec![rlp::encode(&Signature::zero()).to_vec()]);
|
|
||||||
|
|
||||||
let verify_result = engine.verify_block_unordered(&header, None);
|
|
||||||
|
|
||||||
match verify_result {
|
|
||||||
Err(Error::Util(UtilError::Crypto(CryptoError::InvalidSignature))) => {},
|
|
||||||
Err(_) => { panic!("should be block difficulty error (got {:?})", verify_result); },
|
|
||||||
_ => { panic!("Should be error, got Ok"); },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_generate_seal() {
|
fn can_generate_seal() {
|
||||||
let tap = AccountProvider::transient_provider();
|
let tap = AccountProvider::transient_provider();
|
||||||
|
@ -366,9 +366,10 @@ impl From<SnapshotError> for Error {
|
|||||||
|
|
||||||
impl From<EngineError> for Error {
|
impl From<EngineError> for Error {
|
||||||
fn from(err: EngineError) -> Error {
|
fn from(err: EngineError) -> Error {
|
||||||
match err {
|
Error::Engine(err)
|
||||||
other => Error::Engine(other),
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<EthkeyError> for Error {
|
impl From<EthkeyError> for Error {
|
||||||
fn from(err: EthkeyError) -> Error {
|
fn from(err: EthkeyError) -> Error {
|
||||||
Error::Ethkey(err)
|
Error::Ethkey(err)
|
||||||
|
@ -189,7 +189,7 @@ impl ChainNotify for EthSync {
|
|||||||
self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
|
self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn broadcast(&self, message: &[u8]) {
|
fn broadcast(&self, message: Vec<u8>) {
|
||||||
self.network.with_context(ETH_PROTOCOL, |context| {
|
self.network.with_context(ETH_PROTOCOL, |context| {
|
||||||
let mut sync_io = NetSyncIo::new(context, &*self.eth_handler.chain);
|
let mut sync_io = NetSyncIo::new(context, &*self.eth_handler.chain);
|
||||||
self.inf_handler.sync.write().propagate_packet(&mut sync_io, message.clone());
|
self.inf_handler.sync.write().propagate_packet(&mut sync_io, message.clone());
|
||||||
|
Loading…
Reference in New Issue
Block a user