Use ethabi-contract for VotingToChangeKeys, too.

This commit is contained in:
Andreas Fackler 2018-05-09 17:28:02 +02:00
parent 78f2da0a4a
commit 994d0ae202
3 changed files with 21 additions and 110 deletions

View File

@ -1,84 +0,0 @@
use error::{ErrorKind, Result};
use ethabi::{Address, Log, RawTopicFilter, Token, Topic, Uint};
use std::fmt;
use util::LogExt;
/// An event that is logged when a new ballot is started.
#[derive(Debug)]
pub struct BallotCreated {
/// The ballot ID.
pub id: Uint,
/// The ballot type.
ballot_type: Uint,
/// The creator's voting key.
creator: Address,
}
impl BallotCreated {
/// Parses the log and returns a `BallotCreated`, if the log corresponded to such an event.
pub fn from_log(log: &Log) -> Result<BallotCreated> {
match (
log.uint_param(0, "id"),
log.uint_param(1, "ballotType"),
log.address_param(2, "creator"),
) {
(Some(&id), Some(&ballot_type), Some(&creator)) => Ok(BallotCreated {
id,
ballot_type,
creator,
}),
_ => Err(ErrorKind::UnexpectedLogParams.into()),
}
}
/// Returns a topic filter to find the votes corresponding to this ballot.
pub fn vote_topic_filter(&self) -> RawTopicFilter {
RawTopicFilter {
topic0: Topic::This(Token::Uint(self.id)),
..RawTopicFilter::default()
}
}
}
impl fmt::Display for BallotCreated {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"BallotCreated {{ id: {}, ballot_type: {}, creator: {} }}",
self.id, self.ballot_type, self.creator,
)
}
}
/// An event that is logged whenever someone casts a vote in a ballot.
#[derive(Debug)]
pub struct Vote {
/// The ballot ID.
id: Uint,
/// The decision this vote is for.
decision: Uint,
/// The voter's voting key.
pub voter: Address,
/// The timestamp of this vote.
time: Uint,
}
impl Vote {
/// Parses the log and returns a `Vote`, if the log corresponded to such an event.
pub fn from_log(log: &Log) -> Result<Vote> {
match (
log.uint_param(0, "id"),
log.uint_param(1, "decision"),
log.address_param(2, "voter"),
log.uint_param(3, "time"),
) {
(Some(&id), Some(&decision), Some(&voter), Some(&time)) => Ok(Vote {
id,
decision,
voter,
time,
}),
_ => Err(ErrorKind::UnexpectedLogParams.into()),
}
}
}

View File

@ -15,13 +15,11 @@ extern crate web3;
mod cli;
mod error;
mod events;
mod stats;
mod util;
mod validator;
use error::{Error, ErrorKind};
use events::{BallotCreated, Vote};
use stats::Stats;
use std::default::Default;
use std::fs::File;
@ -33,11 +31,11 @@ use_contract!(
"NetworkConsensus",
"abi/PoaNetworkConsensus.abi.json"
);
// use_contract!(
// voting,
// "VotingToChangeKeys",
// "abi/VotingToChangeKeys.abi.json"
// );
use_contract!(
voting,
"VotingToChangeKeys",
"abi/VotingToChangeKeys.abi.json"
);
#[derive(Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
@ -55,11 +53,10 @@ fn count_votes(
let (_eloop, transport) = web3::transports::Http::new(url).unwrap();
let web3 = web3::Web3::new(transport);
let voting_abi = File::open("abi/VotingToChangeKeys.abi.json").expect("read voting abi");
let val_meta_abi = File::open("abi/ValidatorMetadata.abi.json").expect("read val meta abi");
let key_mgr_abi = File::open("abi/KeysManager.abi.json").expect("read key mgr abi");
let voting_contract = ethabi::Contract::load(voting_abi)?;
let voting_contract = voting::VotingToChangeKeys::default();
let net_con_contract = net_con::NetworkConsensus::default();
let val_meta_contract = ethabi::Contract::load(val_meta_abi)?;
let key_mgr_contract = ethabi::Contract::load(key_mgr_abi)?;
@ -69,19 +66,18 @@ fn count_votes(
let key_mgr_addr = util::parse_address(&contract_addrs.keys_manager_address).unwrap();
let web3_key_mgr = web3::contract::Contract::new(web3.eth(), key_mgr_addr, key_mgr_contract);
let ballot_event = voting_contract.event("BallotCreated")?;
let vote_event = voting_contract.event("Vote")?;
let ballot_event = voting_contract.events().ballot_created();
let vote_event = voting_contract.events().vote();
let change_event = net_con_contract.events().change_finalized();
let init_change_event = net_con_contract.events().initiate_change();
// Find all ballots and voter changes.
let ballot_or_change_filter = ballot_event
.create_filter(ethabi::RawTopicFilter::default())
.expect("create ballot event filter")
.or(change_event.create_filter())
.or(init_change_event.create_filter(ethabi::Topic::Any))
.to_filter_builder()
.build();
let ballot_or_change_filter =
(ballot_event.create_filter(ethabi::Topic::Any, ethabi::Topic::Any, ethabi::Topic::Any))
.or(change_event.create_filter())
.or(init_change_event.create_filter(ethabi::Topic::Any))
.to_filter_builder()
.build();
let ballot_change_logs_filter = web3.eth_filter()
.create_logs_filter(ballot_or_change_filter)
.wait()?;
@ -127,14 +123,13 @@ fn count_votes(
}
}
prev_init_change = Some(init_change);
} else if let Ok(ballot_log) = ballot_event.parse_log(log.into_raw()) {
} else if let Ok(ballot) = ballot_event.parse_log(log.into_raw()) {
// If it is a `BallotCreated`, find the corresponding votes and update the stats.
let ballot = BallotCreated::from_log(&ballot_log)?;
if verbose {
println!("{}", ballot);
println!("{:?}", ballot);
}
let vote_filter = vote_event
.create_filter(ballot.vote_topic_filter())?
.create_filter(ballot.id, ethabi::Topic::Any)
.to_filter_builder()
.build();
let vote_logs_filter = web3.eth_filter().create_logs_filter(vote_filter).wait()?;
@ -142,7 +137,7 @@ fn count_votes(
let votes = vote_logs
.into_iter()
.map(|vote_log| {
let vote = Vote::from_log(&vote_event.parse_log(vote_log.into_raw())?)?;
let vote = vote_event.parse_log(vote_log.into_raw())?;
if !voters.contains(&vote.voter) {
if verbose {
eprintln!(" Unexpected voter {}", vote.voter);
@ -151,7 +146,7 @@ fn count_votes(
}
Ok(vote)
})
.collect::<Result<Vec<Vote>, Error>>()?;
.collect::<Result<Vec<_>, Error>>()?;
stats.add_ballot(&voters, &votes);
} else {
return Err(ErrorKind::UnexpectedLogParams.into());

View File

@ -1,9 +1,9 @@
use colored::{Color, Colorize};
use ethabi::Address;
use events::Vote;
use std::collections::HashMap;
use std::fmt::{self, Display, Formatter};
use validator::Validator;
use voting;
/// The count of ballots and cast votes, as well as metadata for a particular voter.
#[derive(Clone, Default)]
@ -27,7 +27,7 @@ pub struct Stats {
impl Stats {
/// Adds a ballot: `voters` are the voting keys of everyone who was allowed to cast a vote, and
/// `votes` are the ones that were actually cast.
pub fn add_ballot(&mut self, voters: &[Address], votes: &[Vote]) {
pub fn add_ballot(&mut self, voters: &[Address], votes: &[voting::logs::Vote]) {
for voter in voters {
let mut vs = self.voter_stats
.entry(voter.clone())