Also show validators with no votes, add check.

We now compare the collected keys to the full current validator list before
printing the results.
This commit is contained in:
Andreas Fackler 2018-12-13 16:15:41 +01:00 committed by Andreas Fackler
parent 744c5bda28
commit fdb0741ff6
5 changed files with 500 additions and 16 deletions

View File

@ -1,6 +1,13 @@
# Changelog
All notable changes to the project will be documented in this file.
## Unreleased
- Migrate to Rust 2018. At least version 1.31.0 required.
- Show new validators in the list, even if there was no ballot since they were added.
## [0.4.0] - 2018-10-15
- Support new contracts (hard fork 2).

View File

@ -0,0 +1,462 @@
[
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "pendingList",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x03aca792"
},
{
"constant": true,
"inputs": [],
"name": "getCurrentValidatorsLength",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x0eaba26a"
},
{
"constant": false,
"inputs": [
{
"name": "_newAddress",
"type": "address"
}
],
"name": "setProxyStorage",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function",
"signature": "0x10855269"
},
{
"constant": false,
"inputs": [
{
"name": "_validator",
"type": "address"
},
{
"name": "_shouldFireEvent",
"type": "bool"
}
],
"name": "addValidator",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function",
"signature": "0x21a3fb85"
},
{
"constant": true,
"inputs": [],
"name": "isMasterOfCeremonyRemovedPending",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x273cb593"
},
{
"constant": true,
"inputs": [],
"name": "isMasterOfCeremonyRemoved",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x379fed9a"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "validatorsState",
"outputs": [
{
"name": "isValidator",
"type": "bool"
},
{
"name": "isValidatorFinalized",
"type": "bool"
},
{
"name": "index",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x4110a489"
},
{
"constant": true,
"inputs": [],
"name": "getPendingList",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x45199e0a"
},
{
"constant": false,
"inputs": [],
"name": "finalizeChange",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function",
"signature": "0x75286211"
},
{
"constant": false,
"inputs": [
{
"name": "_newKey",
"type": "address"
},
{
"name": "_oldKey",
"type": "address"
}
],
"name": "swapValidatorKey",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function",
"signature": "0x879736b2"
},
{
"constant": true,
"inputs": [
{
"name": "_someone",
"type": "address"
}
],
"name": "isValidatorFinalized",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x8f2eabe1"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "currentValidators",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x900eb5a8"
},
{
"constant": true,
"inputs": [],
"name": "getKeysManager",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x9a573786"
},
{
"constant": true,
"inputs": [],
"name": "wasProxyStorageSet",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xa5f8b874"
},
{
"constant": true,
"inputs": [],
"name": "getCurrentValidatorsLengthWithoutMoC",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xa8756337"
},
{
"constant": true,
"inputs": [],
"name": "proxyStorage",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xae4b1b5b"
},
{
"constant": true,
"inputs": [],
"name": "finalized",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xb3f05b97"
},
{
"constant": true,
"inputs": [],
"name": "getValidators",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xb7ab4db5"
},
{
"constant": true,
"inputs": [],
"name": "systemAddress",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xd3e848f1"
},
{
"constant": true,
"inputs": [],
"name": "masterOfCeremonyPending",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xec7de1e9"
},
{
"constant": false,
"inputs": [
{
"name": "_validator",
"type": "address"
},
{
"name": "_shouldFireEvent",
"type": "bool"
}
],
"name": "removeValidator",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function",
"signature": "0xf89a77b1"
},
{
"constant": true,
"inputs": [],
"name": "masterOfCeremony",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xfa81b200"
},
{
"constant": true,
"inputs": [
{
"name": "_someone",
"type": "address"
}
],
"name": "isValidator",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0xfacd743b"
},
{
"inputs": [
{
"name": "_masterOfCeremony",
"type": "address"
},
{
"name": "validators",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor",
"signature": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "parentHash",
"type": "bytes32"
},
{
"indexed": false,
"name": "newSet",
"type": "address[]"
}
],
"name": "InitiateChange",
"type": "event",
"signature": "0x55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "newSet",
"type": "address[]"
}
],
"name": "ChangeFinalized",
"type": "event",
"signature": "0x8564cd629b15f47dc310d45bcbfc9bcf5420b0d51bf0659a16c67f91d2763253"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "proxyStorage",
"type": "address"
}
],
"name": "MoCInitializedProxyStorage",
"type": "event",
"signature": "0x600bcf04a13e752d1e3670a5a9f1c21177ca2a93c6f5391d4f1298d098097c22"
}
]

View File

@ -11,6 +11,7 @@ pub mod v2 {
use_contract!(key_mgr, "abi/v2/KeysManager.abi.json");
use_contract!(val_meta, "abi/v2/ValidatorMetadata.abi.json");
use_contract!(voting, "abi/v2/VotingToChangeKeys.abi.json");
use_contract!(consensus, "abi/v2/PoaNetworkConsensus.abi.json");
}
// The `use_contract!` macro triggers several Clippy warnings.
@ -25,6 +26,7 @@ pub struct ContractV1V2Addresses {
pub metadata_address: Address,
pub keys_manager_address: Address,
pub voting_to_change_keys_address: Address,
pub poa_address: Address,
}
#[derive(Deserialize)]

View File

@ -1,6 +1,10 @@
use crate::contracts::v1::voting::events::{ballot_created as ballot_created_v1, vote as vote_v1};
use crate::contracts::v2::consensus::functions::get_validators as get_validators_fn;
use crate::contracts::v2::key_mgr::events::voting_key_changed;
use crate::contracts::v2::key_mgr::functions::get_mining_key_by_voting;
use crate::contracts::v2::key_mgr::functions::{
get_mining_key_by_voting as get_mining_key_by_voting_fn,
get_voting_by_mining as get_voting_by_mining_fn,
};
use crate::contracts::v2::val_meta::functions::validators as validators_fn;
use crate::contracts::v2::voting::events::{ballot_created, vote};
use crate::contracts::ContractAddresses;
@ -132,11 +136,22 @@ impl Counter {
return Err(ErrorKind::NoEventsFound.into());
}
// Add all voters we haven't encountered so far.
let mining_keys: Vec<Address> = self.call_poa(get_validators_fn::call())?;
for mining_key in mining_keys {
let voter = self.call_key_mgr(get_voting_by_mining_fn::call(mining_key))?;
if voter.is_zero() {
vprintln!("Voting key for {} is zero. Skipping.", mining_key);
} else if voters.insert(voter) {
eprintln!("Unexpected voter {} (mining key {})", voter, mining_key);
}
}
vprintln!(""); // Add a new line between event log and table.
// Finally, gather the metadata for all voters.
for voter in voters {
let mining_key = match self.call_key_mgr(get_mining_key_by_voting::call(voter)) {
let mining_key = match self.call_key_mgr(get_mining_key_by_voting_fn::call(voter)) {
Err(err) => {
eprintln!("Failed to find mining key for voter {}: {:?}", voter, err);
continue;
@ -196,6 +211,14 @@ impl Counter {
)
}
/// Calls a function of the `PoaNetworkConsensus` contract and returns the decoded result.
fn call_poa<D>(&self, fn_call: (Bytes, D)) -> Result<D::Output, web3::contract::Error>
where
D: FunctionOutputDecoder,
{
util::raw_call(self.addrs.v2.poa_address, &self.web3.eth(), fn_call)
}
fn voters_for_ballot(&self, id: Uint) -> Result<Vec<Address>, Error> {
let vote_filter = vote::filter(id, None).or(vote_v1::filter(id, None));
let is_voting = |log: &web3::types::Log| self.addrs.is_voting(&log.address);

View File

@ -43,20 +43,10 @@ impl Stats {
}
/// Inserts metadata about a voter: the mining key and the `Validator` information.
pub fn set_metadata(
&mut self,
voter: &Address,
mining_key: Address,
validator: Validator,
) -> bool {
match self.voter_stats.get_mut(voter) {
None => false,
Some(vs) => {
vs.validator = Some(validator);
vs.mining_key = Some(mining_key);
true
}
}
pub fn set_metadata(&mut self, voter: &Address, mining_key: Address, validator: Validator) {
let vs = self.voter_stats.entry(*voter).or_default();
vs.validator = Some(validator);
vs.mining_key = Some(mining_key);
}
}