Added xDai chain env-vars and CLI/config options.

This commit is contained in:
DrPeterVanNostrand 2018-12-18 02:14:14 +00:00
parent 4f6288d0eb
commit 8b61d5c02e
5 changed files with 177 additions and 147 deletions

178
README.md
View File

@ -2,24 +2,23 @@
# `poa-governance-notifications`
A tool to monitor a POA Network blockchain for
[governance events](https://github.com/poanetwork/wiki/wiki/Governance-Overview).
A CLI tool for monitoring a blockchain for POA Network governance ballots. This tool can be used to
monitor _any_ chain that uses POA Network's governance contracts.
More info regarding governance can be found in
[POA Network's Wiki](https://github.com/poanetwork/wiki/wiki/Governance-Overview).
POA Network's governance contracts can be found in the
[`poa-network-consensus-contracts` repo](https://github.com/poanetwork/poa-network-consensus-contracts/tree/master/contracts),
all Solidity files prefixed with "Voting" are classified as a "governance contract".
The `poagov` command line tool is distributed as a binary for Linux and
OSX; it can also be built from source for both platforms.
OSX. The `poagov` binary can be built from source for both OSX and Linux using the code in this repo.
You can find the source code for the currently deployed governance contracts
[here](https://github.com/poanetwork/poa-network-consensus-contracts/tree/master/contracts).
### Downloading the `poagov` Binary
You can find the addresses for governance contracts currently deployed to Core
[here](https://github.com/poanetwork/poa-chain-spec/blob/core/contracts.json)
and Sokol
[here](https://github.com/poanetwork/poa-chain-spec/blob/sokol/contracts.json).
# Installing the `poagov` Binary
*Note:* the `poagov` binary requires libssl to be installed prior to
usage, if you do not have libssl installed, go to the "Requires libssl"
*Note:* the `poagov` binary requires `libssl` to be installed prior to
usage, if you do not have `libssl` installed, go to the "Requires libssl"
section in this README to find out how to download it.
On Debian/Ubuntu:
@ -41,34 +40,26 @@ On OSX:
$ ./poagov --help
# Building `poagov` from Source
### Building `poagov` from Source
To build the `poagov` CLI tool, run the following:
To build the `poagov` CLI tool from source, clone this repo and run:
$ git clone https://github.com/poanetwork/poa-governance-notifications.git
$ cd poa-governance-notifications
$ cargo build --release
`poagov` can be built with Rust 1.31.0-stable or later and requires `libssl`;
see the following "Requires libssl" section for more information.
see the "Requires `libssl`" section in this README for more information.
### Testing
##### Testing `poagov`
You can run `poagov`'s tests to ensure that everything is working properly:
$ cargo test --release
The test suite will verify: that the required env-vars are found in the `.env`
file, that each network's JSON-RPC server can be reached, and that each
contract ABI can be loaded.
# Requires `libssl`
### Running `poagov` Requires `libssl`
SMTP over TLS requires that you have a native TLS library installed on your
machine, the preferred library for Linux and OSX is OpenSSL >= 1.0.1,
otherwise known as `libssl` (you will need more than just the OpenSSL
binary that you may or may not already have installed at
`/usr/bin/openssl`).
otherwise known as `libssl`.
If running `cargo build --release` panics with an error like:
@ -84,7 +75,7 @@ To install `libssl` on Debian/Ubuntu run the following:
$ sudo apt update
$ sudo apt-get install -y pkg-config libssl-dev
To install libssl on MacOS run the following:
To install `libssl` on MacOS run the following:
$ brew update
$ brew install openssl
@ -111,7 +102,7 @@ The above solution comes from the linked Stack Overflow thread.
More information on common issues encountered while installing the
`openssl` Rust crate can be found [here](https://crates.io/crates/openssl).
# Usage
### Usage
Once you have built or downloaded `poagov`, you can print out the CLI usage by
running:
@ -128,68 +119,88 @@ running:
poagov [FLAGS] [OPTIONS]
FLAGS:
--core monitor voting contracts deployed to the Core network
--sokol monitor voting contracts deployed to the Sokol network
--v1 monitors the v1 voting contracts
--v2 monitors the v2 voting contracts
-k, --keys monitors the blockchain for ballots to change keys
-p, --proxy monitors the blockchain for ballots to change the proxy address
-t, --threshold monitors the blockchain for ballots to change the minimum threshold
-e, --emission monitors the blockchain for ballots to manage emission funds
--earliest begin monitoring for governance events starting at the first block in the blockchain
--latest begin monitoring for governance events starting at the last block mined
--email enables email notifications (SMTP configurations must be set in your `.env` file)
--log-emails logs each notification's email body; does not require the --email flag to be set
--log-file logs are written to files in the ./logs directory, log files are rotated when they reach a size of 4MB
-h, --help prints help information
-V, --version prints version information
--core Monitors POA Network's Core Network for governance ballots
--sokol Monitors POA Network's Sokol network for governance ballots
--xdai Monitors the xDai Network for governance ballots
--v1 Monitors the v1 governance contracts
--v2 [default] Monitors the v2 governance contracts, if no contract version CLI argument is given by
-k, --keys Monitors the blockchain for ballots to change keys
-t, --threshold Monitors the blockchain for ballots to change the minimum threshold
the user, we set this CLI flag
-p, --proxy Monitors the blockchain for ballots to change the proxy address
-e, --emission Monitors the blockchain for ballots to manage emission funds
--earliest Monitor for governance events starting at the blockchain's first block
--latest Monitor for governance events starting at the blockchain's most recently mined block
--email Enables email notifications (SMTP configuration options must be set in your `.env` file)
--log-emails Logs the full email body for each notification generated, this option does not require the
`--email` flag to be set
--log-file Logs are written to files in the ./logs directory, logs are rotated chronologically across 3
files, each file has a max size of 4MB
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
--block-time <value> the average number of seconds it takes to mine a new block
-n, --limit <value> shutdown `poagov` after this many notifications have been generated, useful when testing
--start <value> start monitoring for governance events at this block (inclusive)
--tail <value> start monitoring for governance events for the `n` blocks prior to the last block mined
--block-time <value> The average number of seconds it takes to mine a new block
-n, --limit <value> Stops `poagov` after this many notifications have been generated (this option can be
useful when testing `poagov`)
--start <value> Start monitoring for governance events at this block (inclusive)
--tail <value> Start monitoring for governance events for the `n` blocks prior to the last mined block
Hitting `[ctrl-c]` while `poagov` is running will cause the process to gracefully shutdown.
### Required Arguments
##### Required CLI Arguments
Each time you run `poagov`, four CLI arguments are required:
Each time you run `poagov`, three CLI arguments are required:
1. The chain (specify only one): `--core`, `--sokol`.
2. The contracts to monitor (specify at least one): `--keys`, `--threshold`, `--proxy`, `--emission`.
2. The hardfork version (specify only one): `--v1`, `--v2`.
4. The block in the chain from where to start monitoring (specify only one): `--earliest`, `--latest`, `--start=<block_number>`, `--tail=<value>`.
1. The chain (specify only one): `--core`, `--sokol`, `--xdai`.
2. The governance ballots to monitor (specify at least one): `--keys`, `--threshold`, `--proxy`, `--emission`.
3. The block in the chain from where to start monitoring (specify only one): `--earliest`, `--latest`, `--start=<block_number>`, `--tail=<value>`.
### Notes on the hardfork version options `--v1` and `--v2`
##### Notes on the Hardfork Version CLI Options: `--v1` and `--v2`
`--v1` indicates that you want to monitor for governance events prior to the
Sokol and Core hardforks that will occur in September-2018 and November-2018
respectively.
`--v2` indicates that you want to monitor for governance events that occured
`--v2` indicates that you want to monitor for governance events that occurred
after the above hardfork dates.
- More information regarding the planned hardforks for the Sokol and Core
We default to `--v2` being set as it will monitor the currently deployed contract.
- More information regarding the planned hardforks for the POA Sokol and Core
chains in September and November 2018 can be found
[here](https://medium.com/poa-network/poa-network-news-and-updates-36-2e6e00550c15).
### Optional Arguments
Providing the `--email` flag will enable governance notification emails. To use
this option, you must first configure SMTP in your `.env`.
Providing the `--v1` flag will tell `poagov` to look for ballots corresponding
to the hardfork #1 governance contracts. The hardfork #1 contracts are not
currently being by POA Network and not new governance notifications will be
generated, however you can use `poagov` to view all past `--v1` ballots that
have occurred using:
$ poagov <--core, --sokol> --v1 --earliest -ktp
Providing the `--email` flag will enable governance notification via email. To
use this option, you must first configure SMTP in your `.env` file.
Providing the `--block-time=<value>` will set how often `poagov` will query the
blockchain for new governance events. Defaults to 30 seconds.
Providing the `--log-emails` flag will print the full text for a notification
email to stderr when governance events are found. When this option is set,
email to `stderr` when governance events are found. When this option is set,
email text will be logged regardless of whether or not the `--email` flag is
set.
Setting the `--log-file` flag will write logs to a file in the `./logs/`
Setting the `--log-file` flag will write logs to a file in the `logs/`
directory. Logs are rotated chronologically across three files. Once the
`logs` directory has reached its max number of files, the oldest log file will
`logs/` directory has reached its max number of files, the oldest log file will
be deleted to make room for the next log file. Log files have a max size of
4MB; the log files will rotated once the current log file has reached the max
file size.
@ -197,7 +208,7 @@ file size.
Setting the `--limit=<value>` option will cause `poagov` to stop once `value`
number of notifications have been generated. This option is useful when testing.
# Setting up the `.env` File
### Setting up the `.env` File
When the `poagov` CLI tool is run, the process' environment variables are
loaded via an `.env` file. The `.env` file contains configuration variables
@ -217,40 +228,40 @@ to run `poagov`. If you wish to enable email notifications, you must add the
required SMTP config values to your `.env` file. See the "Setting up Email
Notifications" section for details.
### Setting up Email Notifications
##### Setting up Email Notifications
In order to enable email notifications, you must change the name of the
`sample.env` file to `.env`. Then, you must add values for the following
SMTP config options in your `.env` file:
EMAIL_RECIPIENTS=
SMTP_HOST_DOMAIN=
SMTP_PORT=
SMTP_USERNAME=
SMTP_PASSWORD=
OUTGOING_EMAIL_ADDRESS=
EMAIL_RECIPIENTS=
Add a comma-separated list of email address to the "VALIDATORS" config
option in your .env file. These addresses will be sent emails when `poagov`
encounters governance events on the POA blockchain.
Add a comma-separated list of email address to the `EMAIL_RECIPIENTS` config
option in your `.env` file. These addresses will be sent emails when `poagov`
encounters new ballots.
*Note* `poagov` forces SMTP email notifcations to be sent over an encrypted
channel, if your SMTP Host does not support TLS or STARTTLS, `poagov` will
panic. You may notice that we default `SMTP_PORT` to port 587 for STARTTLS,
but you may use port 465 for TLS, or any other port that your outgoing
email server is lisening for secure connections. If you require unencrypted
SMTP, submit an issue and I can add it.
*Note* `poagov` forces SMTP email notifcations to be sent over TLS/STARTTLS, if
your SMTP Host does not support TLS or STARTTLS, `poagov` will `panic!`.
You may notice that we default `SMTP_PORT` to port 587 for STARTTLS, but you
may use any port for which your outgoing email server is listening; port 465 is
commonly used for TLS.
Your SMTP configuration should look something like the following:
EMAIL_RECIPIENTS=alice@poa.network,bob@poa.network
SMTP_HOST_DOMAIN=mail.riseup.net
SMTP_PORT=587
SMTP_USERNAME=evariste_galois
SMTP_PASSWORD='finteFIELDS#$!'
OUTGOING_EMAIL_ADDRESS=evariste_galois@riseup.net
EMAIL_RECIPIENTS=alice@poa.network,bob@poa.network
# An Explained Example
### An Explained Example
$ poagov --sokol --v1 -kt --earliest --email --log-emails --limit=1
@ -263,14 +274,13 @@ Your SMTP configuration should look something like the following:
- `--log-emails` for each governance notification generated, log the corresponding email body.
- `--limit=1` stop running `poagov` after one ballot notification has been generated.
# Logs
### Logs
Logs are output to `stderr` unless the `--log-file` CLI flag is set. Events
that are logged include: the generation of governance notifications, sending an
email successesfully or failing to send an email, aned what range of blocks
from the chain have been successfully monitored for governance events.
Optionally, you can log the email body for each governance notification
generated by setting the `--log-emails` CLI flag.
Logs are written to `stderr` by default; if the `--log-file` CLI flag is set,
then logs will be written to a file in the `logs.` directory. Logged
information includes: the generation of governance notifications, sending an
email successfully, failing to send an email, blocks that we have finished
monitoring, email bodies generated (using the `--log-emails` CLI option).
The following is an example command with its corresponding logs:

View File

@ -27,17 +27,6 @@ THRESHOLD_CONTRACT_ADDRESS_SOKOL_V1=0x700db8ba3128087f3b23f60de4bc3179bafa467d
PROXY_CONTRACT_ADDRESS_CORE_V1=0x9c8a06f0197ee718cd820adeb48a88ea2a9b5c48
PROXY_CONTRACT_ADDRESS_SOKOL_V1=0x0aa4a75549757a90f62f88b3b96b69bead2db0ff
# TODO: rename env-vars to <contract name>_CONTRACT_ADDRESS_<version>_<network>:
#
# KEYS_CONTRACT_ADDRESS_V1_CORE=
# KEYS_CONTRACT_ADDRESS_V1_SOKOL=
#
# THRESHOLD_CONTRACT_ADDRESS_V1_CORE=
# THRESHOLD_CONTRACT_ADDRESS_V1_SOKOL=
#
# PROXY_CONTRACT_ADDRESS_V1_CORE=
# PROXY_CONTRACT_ADDRESS_V1_SOKOL=
# ------------------------------------------------------------------------
# V2 Governance Contract Addresses Deployed on the Core, Sokol, and xDai Networks
# ------------------------------------------------------------------------
@ -61,7 +50,6 @@ PROXY_CONTRACT_ADDRESS_CORE_V2=0x468758926c796722d85bded792d1831f0839caa6
PROXY_CONTRACT_ADDRESS_SOKOL_V2=0x604cdc518f3eb0446e15fc05a22923c82d8a8e21
PROXY_CONTRACT_ADDRESS_XDAI_V2=0x96bcea97bd6cbf1cc6d637796c5c3a7a642bc8fc
# TODO: change this env-var name to "EMISSION_":
EMISSION_FUNDS_CONTRACT_ADDRESS_CORE_V2=0x7e9b90b22cdd1f6aa206f0d852ac96212217d60e
EMISSION_FUNDS_CONTRACT_ADDRESS_SOKOL_V2=0x7cfa6f2c0d032f9dde652996e989a4d385b8b9d7
EMISSION_FUNDS_CONTRACT_ADDRESS_XDAI_V2=0x918092ab6f2b6f24b82aeaf797566a222dea4d28

View File

@ -8,23 +8,24 @@ pub fn parse_cli() -> Cli {
.version("1.0.0")
.about("Monitors a POA Network blockchain for governance events.")
.args_from_usage(
"[core] --core 'monitor voting contracts deployed to the Core network'
[sokol] --sokol 'monitor voting contracts deployed to the Sokol network'
[keys] -k --keys 'monitors the blockchain for ballots to change keys'
[threshold] -t --threshold 'monitors the blockchain for ballots to change the minimum threshold'
[proxy] -p --proxy 'monitors the blockchain for ballots to change the proxy address'
[emission] -e --emission 'monitors the blockchain for ballots to manage emission funds'
[v1] --v1 'monitors the v1 voting contracts'
[v2] --v2 'monitors the v2 voting contracts'
[earliest] --earliest 'begin monitoring for governance events starting at the first block in the blockchain'
[latest] --latest 'begin monitoring for governance events starting at the last block mined'
[start_block] --start [value] 'start monitoring for governance events at this block (inclusive)'
[tail] --tail [value] 'start monitoring for governance events for the `n` blocks prior to the last block mined'
[email] --email 'enables email notifications (SMTP configurations must be set in your `.env` file)'
[block_time] --block-time [value] 'the average number of seconds it takes to mine a new block'
[notification_limit] -n --limit [value] 'shutdown `poagov` after this many notifications have been generated'
[log_emails] --log-emails 'logs each notification's email body; does not require the --email flag to be set'
[log_to_file] --log-file 'logs are written to files in the ./logs directory, logs are rotated chronologically across 3 files, each file has a max size of 8MB'"
"[core] --core 'Monitors POA Network's Core Network for governance ballots'
[sokol] --sokol 'Monitors POA Network's Sokol network for governance ballots'
[xdai] --xdai 'Monitors the xDai Network for governance ballots'
[keys] -k --keys 'Monitors the blockchain for ballots to change keys'
[threshold] -t --threshold 'Monitors the blockchain for ballots to change the minimum threshold'
[proxy] -p --proxy 'Monitors the blockchain for ballots to change the proxy address'
[emission] -e --emission 'Monitors the blockchain for ballots to manage emission funds'
[v1] --v1 'Monitors the v1 governance contracts'
[v2] --v2 '[default] Monitors the v2 governance contracts, if no contract version CLI argument is given by the user, we set this CLI flag'
[earliest] --earliest 'Monitor for governance events starting at the blockchain's first block'
[latest] --latest 'Monitor for governance events starting at the blockchain's most recently mined block'
[start_block] --start [value] 'Start monitoring for governance events at this block (inclusive)'
[tail] --tail [value] 'Start monitoring for governance events for the `n` blocks prior to the last mined block'
[email] --email 'Enables email notifications (SMTP configuration options must be set in your `.env` file)'
[block_time] --block-time [value] 'The average number of seconds it takes to mine a new block'
[notification_limit] -n --limit [value] 'Stops `poagov` after this many notifications have been generated (this option can be useful when testing `poagov`)'
[log_emails] --log-emails 'Logs the full email body for each notification generated, this option does not require the `--email` flag to be set'
[log_to_file] --log-file 'Logs are written to files in the ./logs directory, logs are rotated chronologically across 3 files, each file has a max size of 8MB'"
).get_matches();
Cli(cli_args)
@ -42,6 +43,19 @@ impl Cli {
self.0.is_present("sokol")
}
pub fn xdai(&self) -> bool {
self.0.is_present("xdai")
}
pub fn one_network_specified(&self) -> bool {
match (self.core(), self.sokol(), self.xdai()) {
(true, false, false) => true,
(false, true, false) => true,
(false, false, true) => true,
_ => false,
}
}
pub fn keys(&self) -> bool {
self.0.is_present("keys")
}
@ -70,6 +84,10 @@ impl Cli {
self.0.is_present("v2")
}
pub fn multiple_versions_specified(&self) -> bool {
self.v1() && self.v2()
}
pub fn earliest(&self) -> bool {
self.0.is_present("earliest")
}
@ -86,21 +104,14 @@ impl Cli {
self.0.value_of("tail")
}
pub fn multiple_start_blocks_specified(&self) -> bool {
let mut count = 0;
if self.earliest() {
count += 1;
pub fn one_start_block_was_specified(&self) -> bool {
match (self.earliest(), self.latest(), self.start_block().is_some(), self.tail().is_some()) {
(true, false, false, false) => true,
(false, true, false, false) => true,
(false, false, true, false) => true,
(false, false, false, true) => true,
_ => false,
}
if self.latest() {
count += 1;
}
if self.start_block().is_some() {
count += 1;
}
if self.tail().is_some() {
count += 1;
}
count != 1
}
pub fn email(&self) -> bool {

View File

@ -15,6 +15,7 @@ const DEFAULT_BLOCK_TIME_SECS: u64 = 30;
pub enum Network {
Core,
Sokol,
XDai,
}
impl Network {
@ -22,6 +23,7 @@ impl Network {
match self {
Network::Core => "CORE",
Network::Sokol => "SOKOL",
Network::XDai=> "XDAI",
}
}
}
@ -190,18 +192,26 @@ pub struct Config {
impl Config {
pub fn new(cli: &Cli) -> Result<Self> {
if cli.core() == cli.sokol() {
if !cli.one_network_specified() {
return Err(Error::MustSpecifyOneCliArgument("--core, --sokol".to_string()));
}
if cli.v1() == cli.v2() {
return Err(Error::MustSpecifyOneCliArgument("--v1, --v2".to_string()));
if cli.multiple_versions_specified() {
return Err(Error::MustSpecifyZeroOrOneCliArguments("--v1, --v2".to_string()));
}
if cli.no_contracts_specified() {
return Err(Error::MustSpecifyAtLeastOneCliArgument(
"--keys, --threshold, --proxy, --emission".to_string().to_string(),
));
}
if cli.multiple_start_blocks_specified() {
if cli.v1() {
if cli.xdai() {
return Err(Error::V1ContractsWereNotDeployedToXDaiChain);
}
if cli.emission() {
return Err(Error::EmissionFundsV1ContractDoesNotExist);
}
}
if !cli.one_start_block_was_specified() {
return Err(Error::MustSpecifyOneCliArgument(
"--earliest, --latest, --start-block, --tail".to_string()
));
@ -209,10 +219,13 @@ impl Config {
let network = if cli.core() {
Network::Core
} else {
} else if cli.sokol() {
Network::Sokol
} else {
Network::XDai
};
// We default to `V2` if no contract version CLI argument was supplied.
let version = if cli.v1() {
ContractVersion::V1
} else {
@ -268,23 +281,26 @@ impl Config {
let email_notifications = cli.email();
// TODO: should the recipient email addresses be validated here? For now, we just allow
// email sending to fail, which will then get logged to the user.
let email_recipients: Vec<String> = env::var("EMAIL_RECIPIENTS")
.map_err(|_| Error::MissingEnvVar("EMAIL_RECIPIENTS".into()))?
.map_err(|_| Error::MissingEnvVar("EMAIL_RECIPIENTS".to_string()))?
.split(',')
.filter_map(|s| if s.is_empty() { None } else { Some(s.into()) })
.map(|recipient_email_address| recipient_email_address.to_string())
.collect();
let smtp_host_domain = if email_notifications {
let host = env::var("SMTP_HOST_DOMAIN")
.map_err(|_| Error::MissingEnvVar("SMTP_HOST_DOMAIN".into()))?;
Some(host)
match env::var("SMTP_HOST_DOMAIN") {
Ok(host) => Some(host),
_ => return Err(Error::MissingEnvVar("SMTP_HOST_DOMAIN".to_string())),
}
} else {
None
};
let smtp_port = if email_notifications {
if let Ok(s) = env::var("SMTP_PORT") {
let port = s.parse().map_err(|_| Error::InvalidSmtpPort(s.into()))?;
let port = s.parse().map_err(|_| Error::InvalidSmtpPort(s.to_string()))?;
Some(port)
} else {
return Err(Error::MissingEnvVar("SMTP_PORT".into()));
@ -294,25 +310,28 @@ impl Config {
};
let smtp_username = if email_notifications {
let username = env::var("SMTP_USERNAME")
.map_err(|_| Error::MissingEnvVar("SMTP_USERNAME".into()))?;
Some(username)
match env::var("SMTP_USERNAME") {
Ok(username) => Some(username),
_ => return Err(Error::MissingEnvVar("SMTP_USERNAME".into())),
}
} else {
None
};
let smtp_password = if email_notifications {
let password = env::var("SMTP_PASSWORD")
.map_err(|_| Error::MissingEnvVar("SMTP_PASSWORD".into()))?;
Some(password)
match env::var("SMTP_PASSWORD") {
Ok(password) => Some(password),
_ => return Err(Error::MissingEnvVar("SMTP_PASSWORD".to_string())),
}
} else {
None
};
let outgoing_email_addr = if email_notifications {
let email_addr = env::var("OUTGOING_EMAIL_ADDRESS")
.map_err(|_| Error::MissingEnvVar("OUTGOING_EMAIL_ADDRESS".into()))?;
Some(email_addr)
match env::var("OUTGOING_EMAIL_ADDRESS") {
Ok(outgoing_email_addr) => Some(outgoing_email_addr),
_ => return Err(Error::MissingEnvVar("OUTGOING_EMAIL_ADDRESS".to_string())),
}
} else {
None
};

View File

@ -23,9 +23,11 @@ pub enum Error {
MissingEnvVar(String),
MustSpecifyAtLeastOneCliArgument(String),
MustSpecifyOneCliArgument(String),
MustSpecifyZeroOrOneCliArguments(String),
RequestFailed(reqwest::Error),
StartBlockExceedsLastBlockMined {
start_block: u64,
last_mined_block: u64,
},
V1ContractsWereNotDeployedToXDaiChain,
}