Skip to content
This repository has been archived by the owner on Jul 29, 2022. It is now read-only.

Minor tweaks to the README #44

Merged
merged 8 commits into from
Sep 28, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "GPLv3+"
default-run = "ledgeracio"

[dependencies]
substrate-subxt = { git = "https://github.com/paritytech/substrate-subxt.git", branch = "no-sync-required" }
Expand Down
26 changes: 11 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Ledgeracio CLI

Ledgeracio is a command-line tool and Ledger app designed for staking operations
Ledgeracio is a command-line tool and a Ledger app designed for staking operations
on Substrate-based networks.

Running `ledgeracio --help` will provide top-level usage instructions.
Expand All @@ -24,19 +24,16 @@ necessary support for userspace USB drivers.

## What is Ledgeracio?

Ledgeracio is a CLI app to perform various tasks common to staking on Kusama and
Ledgeracio is a CLI app to perform various tasks common to staking on Kusama and
Polkadot, aka staking-ops. Ledgeracio is designed to reduce the risk of user
error by way of an allowlist of validators that is set up and signed once and
stored on the Ledger device. Furthermore, Ledgeracio can speed up the workflow
considerably when compared to alternatives using Parity Signer + Polkadot{.js}.

This repository only contains the CLI. To submit transactions with Ledgeracio,
you will also need the companion Ledger app. Experimental versions are
available at [Zondax/ledger-polkadot](https://github.com/Zondax/ledger-polkadot)
you will also need the companion Ledger app that you can install from the Ledger app store for [Polkadot](https://support.ledger.com/hc/en-us/articles/360016289919) and [Kusama](https://support.ledger.com/hc/en-us/articles/360016289979-Kusama-KSM-). Development versions of the apps are available at [Zondax/ledger-polkadot](https://github.com/Zondax/ledger-polkadot)
and [Zondax/ledger-kusama](https://github.com/Zondax/ledger-kusama). Please do
not use these unaudited versions in production. In the near future, Ledger will
approve and sign production versions of these apps, which will be available in
the Ledger Store.
not use the unaudited versions in production. For instruction on how to setup and use your Ledger device with Polkadot/Kusama, see the [Polkadot wiki](https://wiki.polkadot.network/docs/en/learn-ledger).

The Ledgeracio CLI contains two binaries. The first, simply called
`ledgeracio`, is used to submit transactions. The second, called
Expand All @@ -48,11 +45,10 @@ can safely be used on virtually any machine on which it will run.
Some subcommands of `ledgeracio-allowlist`, however, generate and use secret
keys, which are stored unencrypted on disk. Therefore, they MUST NOT be used
except on trusted and secured machines. Ideally, these subcommands should be
run on a machine that is reserved for provisioning of Ledgeracio apps, and
which has no network connectivity.
run on a machine that is reserved for provisioning of Ledger devices with the Ledgeracio app, and which has no network connectivity.

The allowlist serves to prevent one from accidentally nominating the wrong
validator, which could result in a slash. It does not protect against malicious
validator, which could result in a slash. It does NOT protect against malicious
use of the device. Anyone with both the device and its PIN can uninstall the
Ledgeracio app and install the standard Polkadot or Kusama app, which uses the
same derivation path and thus can perform the same transactions.
Expand Down Expand Up @@ -117,7 +113,7 @@ binary format.
### Device provisioning

`ledgeracio-allowlist` is also used for device provisioning. To set the
allowlist, one uses `ledgeracio-allowlist set-key`. This command will only
allowlist, use `ledgeracio-allowlist set-key`. This command will only
succeed once. If an allowlist has already been uploaded, it will fail. The
only way to change the allowlist signing key is to reinstall the Ledgeracio app,
which does not result in any funds being lost.
Expand Down Expand Up @@ -151,7 +147,7 @@ status. The first takes an index, while the second takes an address.
### Allowlist handling: `ledgeracio-allowlist`

The Ledgeracio app enforces a list of allowed stash accounts. This is
managed using the `ledgeracio allowlist` command.
managed using the `ledgeracio-allowlist` command.

Some subcommands involve the generation or use of secret keys, which are stored
on disk without encryption. These subcommands MUST NOT be used on untrusted
Expand All @@ -169,7 +165,7 @@ This is to prevent accidental overwrites.

The public key is not sensitive, and is required by anyone who wishes to verify
signed allowlists and operate on the allowed accounts. It will be uploaded
to the Ledger device by `ledgeracio allowlist set-key`. The secret key allows
to the Ledger device by `ledgeracio-allowlist set-key`. The secret key allows
generating signatures, and therefore must be kept secret. It should never leave
the (preferably air gapped) machine it is generated on.

Expand Down Expand Up @@ -299,8 +295,8 @@ given index.
#### Announcing an intention to validate: `ledgeracio validator announce <index> [commission]`

This command announces that the controller account at `<index>` intends to
validate. An optional commission may also be provided. If none is supplied, it
defaults to 100%.
validate. An optional commission (as a decimal between 0 and 1 inclusive) may also be provided. If none is supplied, it
DemiMarie marked this conversation as resolved.
Show resolved Hide resolved
defaults to 1, or 100%.

#### Cease validation: `ledgeracio validator chill`

Expand Down
39 changes: 39 additions & 0 deletions src/bin/ledgeracio/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,36 @@ pub fn pad(mut zeros: u8, value: u128) -> String {
value
}

pub fn parse_ppb(data: &str) -> Result<u32, Error> {
if data == "1" {
Ok(1_000_000_000)
} else if data == "0" {
Ok(0)
} else if !data.starts_with("0.") {
Err(
"Commission must start with 0. or be equal to 1 (the default) or 0"
.to_owned()
.into(),
)
} else if data.len() > 11 {
Err("Commission too long. Check for excess trailing zeroes."
.to_owned()
.into())
} else {
let mut len = data.len() - 2;
let mut res: u32 = str::parse(&data[2..])?;
while len < 9 {
res *= 10;
len += 1;
}
Ok(res)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn padding_works() {
assert_eq!(pad(0, 100), "100".to_owned());
Expand All @@ -154,4 +181,16 @@ mod tests {
assert_eq!(pad(3, 10001), "10.001".to_owned());
assert_eq!(pad(3, 10010), "10.01".to_owned());
}

#[test]
fn parse_ppb_works() {
assert_eq!(parse_ppb("1").unwrap(), 1_000_000_000);
assert_eq!(parse_ppb("0").unwrap(), 0);
assert!(parse_ppb("0.").is_err());
assert_eq!(parse_ppb("0.01").unwrap(), 10_000_000);
assert!(parse_ppb("0.0100000000").is_err());
assert_eq!(parse_ppb("0.010000000").unwrap(), 10_000_000);
assert_eq!(parse_ppb("0.000000000").unwrap(), 0);
assert_eq!(parse_ppb("0.999999999").unwrap(), 999_999_999);
}
}
15 changes: 12 additions & 3 deletions src/bin/ledgeracio/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
//! e.g. rotating session keys, set payment target, announcing
//! intention to validate etc. Requires a network connection.

use super::{parse_reward_destination, AccountType, AddressSource, Error, LedgeracioPath, StructOpt};
use super::{common::parse_ppb, parse_reward_destination, AccountType, AddressSource, Error,
LedgeracioPath, StructOpt};
use codec::Decode;
use core::{future::Future, pin::Pin};
use ledgeracio::parse_address;
Expand All @@ -42,7 +43,11 @@ pub(crate) enum Validator {
/// specified.
Show { index: Option<u32> },
/// Announce intention to validate
Announce { index: u32, commission: Option<u32> },
Announce {
index: u32,
#[structopt(parse(try_from_str = parse_ppb))]
commission: Option<u32>,
},
/// Chill (announce intention to cease validation)
Chill { index: u32 },
/// Replace a session key
Expand Down Expand Up @@ -92,8 +97,12 @@ pub(crate) async fn main<T: FnOnce() -> Result<super::HardStore, Error>>(
}
Validator::Announce { index, commission } => {
let path = LedgeracioPath::new(network, AccountType::Validator, index)?;
let commission = commission.unwrap_or(1_000_000_000);
if commission > 1_000_000_000 {
return Err(format!("Commission {} too large (limit is 10⁹)", commission).into())
}
let prefs = ValidatorPrefs {
commission: Perbill::from_parts(commission.unwrap_or(u32::max_value())),
commission: Perbill::from_parts(commission),
};
let signer = keystore()?.signer(path).await?;
Ok(Some(client.await?.validate(&signer, prefs).await?))
Expand Down