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:
parent
744c5bda28
commit
fdb0741ff6
|
@ -1,6 +1,13 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
All notable changes to the project will be documented in this file.
|
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
|
## [0.4.0] - 2018-10-15
|
||||||
|
|
||||||
- Support new contracts (hard fork 2).
|
- Support new contracts (hard fork 2).
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
|
@ -11,6 +11,7 @@ pub mod v2 {
|
||||||
use_contract!(key_mgr, "abi/v2/KeysManager.abi.json");
|
use_contract!(key_mgr, "abi/v2/KeysManager.abi.json");
|
||||||
use_contract!(val_meta, "abi/v2/ValidatorMetadata.abi.json");
|
use_contract!(val_meta, "abi/v2/ValidatorMetadata.abi.json");
|
||||||
use_contract!(voting, "abi/v2/VotingToChangeKeys.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.
|
// The `use_contract!` macro triggers several Clippy warnings.
|
||||||
|
@ -25,6 +26,7 @@ pub struct ContractV1V2Addresses {
|
||||||
pub metadata_address: Address,
|
pub metadata_address: Address,
|
||||||
pub keys_manager_address: Address,
|
pub keys_manager_address: Address,
|
||||||
pub voting_to_change_keys_address: Address,
|
pub voting_to_change_keys_address: Address,
|
||||||
|
pub poa_address: Address,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use crate::contracts::v1::voting::events::{ballot_created as ballot_created_v1, vote as vote_v1};
|
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::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::val_meta::functions::validators as validators_fn;
|
||||||
use crate::contracts::v2::voting::events::{ballot_created, vote};
|
use crate::contracts::v2::voting::events::{ballot_created, vote};
|
||||||
use crate::contracts::ContractAddresses;
|
use crate::contracts::ContractAddresses;
|
||||||
|
@ -132,11 +136,22 @@ impl Counter {
|
||||||
return Err(ErrorKind::NoEventsFound.into());
|
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.
|
vprintln!(""); // Add a new line between event log and table.
|
||||||
|
|
||||||
// Finally, gather the metadata for all voters.
|
// Finally, gather the metadata for all voters.
|
||||||
for voter in 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) => {
|
Err(err) => {
|
||||||
eprintln!("Failed to find mining key for voter {}: {:?}", voter, err);
|
eprintln!("Failed to find mining key for voter {}: {:?}", voter, err);
|
||||||
continue;
|
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> {
|
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 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);
|
let is_voting = |log: &web3::types::Log| self.addrs.is_voting(&log.address);
|
||||||
|
|
18
src/stats.rs
18
src/stats.rs
|
@ -43,20 +43,10 @@ impl Stats {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts metadata about a voter: the mining key and the `Validator` information.
|
/// Inserts metadata about a voter: the mining key and the `Validator` information.
|
||||||
pub fn set_metadata(
|
pub fn set_metadata(&mut self, voter: &Address, mining_key: Address, validator: Validator) {
|
||||||
&mut self,
|
let vs = self.voter_stats.entry(*voter).or_default();
|
||||||
voter: &Address,
|
vs.validator = Some(validator);
|
||||||
mining_key: Address,
|
vs.mining_key = Some(mining_key);
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue