Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
22d845b
replace floating point arithm from token module with rust_decimal
brentstone Aug 30, 2022
97523f4
[ci] wasm checksums update
github-actions[bot] Oct 26, 2022
d08da6e
changelog: #436
tzemanovic Oct 26, 2022
29eb68f
remove staking reward address from all code
brentstone Oct 25, 2022
020f6bf
remove staking reward address from genesis toml files
brentstone Oct 26, 2022
3eb21f7
client: remove staking rewards address from init-validator result
tzemanovic Oct 26, 2022
b54b5c0
wallet: remove validator rewards key
tzemanovic Oct 26, 2022
9852d28
remove staking rewards address from cli strings and docs strings
tzemanovic Oct 26, 2022
70fa58b
changelog: #687
tzemanovic Oct 26, 2022
da7bffc
introduce validator commission rate and changes
brentstone Sep 21, 2022
3fbc30e
require commission rate input data for new validators
brentstone Sep 23, 2022
4b88573
epoched commission rate and tx for validator to change their rate
brentstone Sep 27, 2022
4ff76d8
commission rate: query + refactor validator change tx
brentstone Sep 28, 2022
77dfff4
add missing commission rate-related instances
brentstone Oct 26, 2022
5b6565e
include and update `rust_decimal`
brentstone Oct 26, 2022
288bf33
bug fix from splitting this PR off of #388
brentstone Oct 26, 2022
3704ef6
cleaning: incl fmt + clippy
brentstone Oct 26, 2022
0e097d8
init validator: add commission rate required args for tests
brentstone Oct 26, 2022
80283b2
fix commission rate validation on validator initialization
brentstone Oct 28, 2022
9d8a0d0
improve docs
brentstone Oct 28, 2022
629e1c5
[ci] wasm checksums update
github-actions[bot] Oct 31, 2022
258b910
wasm tx test for changing validator commission rate
brentstone Nov 4, 2022
6610a65
fix error convention
brentstone Nov 4, 2022
563d218
commission change wasm tx test: fix and update validation
brentstone Nov 4, 2022
7d652e3
bug fix: consensus key validation error
brentstone Nov 4, 2022
9b4f2be
fix get of epoched commission rate before pipeline
brentstone Nov 4, 2022
6778fd0
add max change info to query of validator commission rate
brentstone Nov 4, 2022
b900354
fix pos state machine test
brentstone Nov 7, 2022
7b6de40
[ci] wasm checksums update
github-actions[bot] Nov 7, 2022
302a08c
changes in response to review comments
brentstone Nov 8, 2022
dcfd6af
validator VP that checks source and signature for a commission rate c…
brentstone Nov 9, 2022
9068938
add max commission rate info to validation and pos state machine test
brentstone Nov 9, 2022
9b175c4
fix: critical flaw in pos VP that was prematurely returning true
brentstone Nov 9, 2022
fea59bd
add vp validator to wasms
brentstone Nov 9, 2022
757ba1d
async tx to change validator commission rate
brentstone Nov 9, 2022
42b0bfa
addressing 2nd round of review comments
brentstone Nov 10, 2022
476877e
[ci] wasm checksums update
github-actions[bot] Nov 10, 2022
6b92f2c
changelog: add #695
tzemanovic Nov 10, 2022
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
42 changes: 39 additions & 3 deletions apps/src/lib/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2095,21 +2095,57 @@ pub mod args {
}
}

#[derive(Clone, Debug)]
/// Commission rate change args
pub struct TxCommissionRateChange {
/// Common tx arguments
pub tx: Tx,
/// Validator address (should be self)
pub validator: WalletAddress,
/// Value to which the tx changes the commission rate
pub rate: Decimal,
}

impl Args for TxCommissionRateChange {
fn parse(matches: &ArgMatches) -> Self {
let tx = Tx::parse(matches);
let validator = VALIDATOR.parse(matches);
let rate = COMMISSION_RATE.parse(matches);
Self {
tx,
validator,
rate,
}
}

fn def(app: App) -> App {
app.add_args::<Query>()
.arg(VALIDATOR.def().about(
"The validator's address whose commission rate to change.",
))
.arg(
COMMISSION_RATE
.def()
.about("The desired new commission rate."),
)
}
}

/// Query PoS commission rate
#[derive(Clone, Debug)]
pub struct QueryCommissionRate {
/// Common query args
pub query: Query,
/// Address of a validator
pub validator: Option<WalletAddress>,
pub validator: WalletAddress,
/// Epoch in which to find commission rate
pub epoch: Option<Epoch>,
}

impl Args for QueryCommissionRate {
fn parse(matches: &ArgMatches) -> Self {
let query = Query::parse(matches);
let validator = VALIDATOR_OPT.parse(matches);
let validator = VALIDATOR.parse(matches);
let epoch = EPOCH.parse(matches);
Self {
query,
Expand All @@ -2120,7 +2156,7 @@ pub mod args {

fn def(app: App) -> App {
app.add_args::<Query>()
.arg(VALIDATOR_OPT.def().about(
.arg(VALIDATOR.def().about(
"The validator's address whose commission rate to query.",
))
.arg(EPOCH.def().about(
Expand Down
87 changes: 43 additions & 44 deletions apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ pub async fn query_voting_power(ctx: Context, args: args::QueryVotingPower) {
println!("Total voting power: {}", total_voting_power);
}

/// Query PoS commssion rate
/// Query PoS validator's commission rate
pub async fn query_commission_rate(
ctx: Context,
args: args::QueryCommissionRate,
Expand All @@ -985,51 +985,50 @@ pub async fn query_commission_rate(
Some(epoch) => epoch,
None => query_epoch(args.query.clone()).await,
};
let client = HttpClient::new(args.query.ledger_address).unwrap();

match args.validator {
Some(validator) => {
let validator = ctx.get(&validator);
let validator_commission_key =
pos::validator_commission_rate_key(&validator);
let validator_max_commission_change_key =
pos::validator_max_commission_rate_change_key(&validator);
let commission_rates = query_storage_value::<pos::CommissionRates>(
&client,
&validator_commission_key,
)
.await;
let max_rate_change = query_storage_value::<Decimal>(
&client,
&validator_max_commission_change_key,
)
.await;
let max_rate_change =
max_rate_change.expect("No max rate change found");
let commission_rates =
commission_rates.expect("No commission rate found ");
match commission_rates.get(epoch) {
Some(rate) => {
println!(
"Validator {} commission rate: {}, max change per \
epoch: {}",
validator.encode(),
*rate,
max_rate_change,
)
}
None => {
println!(
"No commission rate found for {} in epoch {}",
validator.encode(),
epoch
)
}
let client = HttpClient::new(args.query.ledger_address.clone()).unwrap();
let validator = ctx.get(&args.validator);
let is_validator =
is_validator(&validator, args.query.ledger_address).await;

if is_validator {
let validator_commission_key =
pos::validator_commission_rate_key(&validator);
let validator_max_commission_change_key =
pos::validator_max_commission_rate_change_key(&validator);
let commission_rates = query_storage_value::<pos::CommissionRates>(
&client,
&validator_commission_key,
)
.await;
let max_rate_change = query_storage_value::<Decimal>(
&client,
&validator_max_commission_change_key,
)
.await;
let max_rate_change =
max_rate_change.expect("No max rate change found");
let commission_rates =
commission_rates.expect("No commission rate found ");
match commission_rates.get(epoch) {
Some(rate) => {
println!(
"Validator {} commission rate: {}, max change per epoch: \
{}",
validator.encode(),
*rate,
max_rate_change,
)
}
None => {
println!(
"No commission rate found for {} in epoch {}",
validator.encode(),
epoch
)
}
}
None => {
println!("No validator found from the args")
}
} else {
println!("Cannot find validator with address {}", validator);
}
}

Expand Down
87 changes: 86 additions & 1 deletion apps/src/lib/client/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use async_std::io::{self};
use borsh::BorshSerialize;
use itertools::Either::*;
use namada::ledger::governance::storage as gov_storage;
use namada::ledger::pos::{BondId, Bonds, Unbonds};
use namada::ledger::pos::{BondId, Bonds, CommissionRates, Unbonds};
use namada::proto::Tx;
use namada::types::address::{nam, Address};
use namada::types::governance::{
Expand Down Expand Up @@ -52,6 +52,7 @@ const VP_USER_WASM: &str = "vp_user.wasm";
const TX_BOND_WASM: &str = "tx_bond.wasm";
const TX_UNBOND_WASM: &str = "tx_unbond.wasm";
const TX_WITHDRAW_WASM: &str = "tx_withdraw.wasm";
const TX_CHANGE_COMMISSION_WASM: &str = "tx_change_validator_commission.wasm";

const ENV_VAR_ANOMA_TENDERMINT_WEBSOCKET_TIMEOUT: &str =
"ANOMA_TENDERMINT_WEBSOCKET_TIMEOUT";
Expand Down Expand Up @@ -975,6 +976,90 @@ pub async fn submit_withdraw(ctx: Context, args: args::Withdraw) {
process_tx(ctx, &args.tx, tx, Some(default_signer)).await;
}

pub async fn submit_validator_commission_change(
ctx: Context,
args: args::TxCommissionRateChange,
) {
let epoch = rpc::query_epoch(args::Query {
ledger_address: args.tx.ledger_address.clone(),
})
.await;

let tx_code = ctx.read_wasm(TX_CHANGE_COMMISSION_WASM);
let client = HttpClient::new(args.tx.ledger_address.clone()).unwrap();

// Check that the submitter of the tx is a validator
match ctx.wallet.get_validator_data() {
Some(data) => {
if args.rate < Decimal::ZERO || args.rate > Decimal::ONE {
eprintln!(
"Invalid new commission rate, received {}",
args.rate
);
if !args.tx.force {
safe_exit(1)
}
}

let commission_rate_key =
ledger::pos::validator_commission_rate_key(&data.address);
let max_commission_rate_change_key =
ledger::pos::validator_max_commission_rate_change_key(
&data.address,
);
let commission_rates = rpc::query_storage_value::<CommissionRates>(
&client,
&commission_rate_key,
)
.await;
let max_change = rpc::query_storage_value::<Decimal>(
&client,
&max_commission_rate_change_key,
)
.await;

match (commission_rates, max_change) {
(Some(rates), Some(max_change)) => {
// Assuming that pipeline length = 2
let rate_next_epoch = rates.get(epoch + 1).unwrap();
if (args.rate - rate_next_epoch).abs() > max_change {
eprintln!(
"New rate is too large of a change with respect \
to the predecessor epoch in which the rate will \
take effect."
);
if !args.tx.force {
safe_exit(1)
}
}
}
_ => {
eprintln!("Error retrieving from storage");
if !args.tx.force {
safe_exit(1)
}
}
}
}
None => {
eprintln!("Cannot change the commission rate of the validator");
if !args.tx.force {
safe_exit(1)
}
}
}

let data = pos::CommissionChange {
validator: ctx.get(&args.validator),
new_rate: args.rate,
};
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx = Tx::new(tx_code, Some(data));
let default_signer = &args.validator;
process_tx(ctx, &args.tx, tx, Some(default_signer)).await;
}

/// Submit transaction and wait for result. Returns a list of addresses
/// initialized in the transaction if any. In dry run, this is always empty.
async fn process_tx(
Expand Down
7 changes: 6 additions & 1 deletion genesis/dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ tokens = 200000
# Amount of the validator's genesis token balance which is not staked.
non_staked_balance = 100000
# VP for the validator account
validator_vp = "vp_user"
validator_vp = "vp_validator"
# Commission rate for rewards
commission_rate = 0.05
# Maximum change per epoch in the commission rate
Expand Down Expand Up @@ -127,6 +127,11 @@ filename = "vp_user.wasm"
# SHA-256 hash of the wasm file
sha256 = "dc7b97f0448f2369bd2401c3c1d8898f53cac8c464a8c1b1f7f81415a658625d"

# Default validator VP
[wasm.vp_validator]
# filename (relative to wasm path used by the node)
filename = "vp_validator.wasm"

# Token VP
[wasm.vp_token]
filename = "vp_token.wasm"
Expand Down
7 changes: 6 additions & 1 deletion genesis/e2e-tests-single-node.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ tokens = 200000
# Amount of the validator's genesis token balance which is not staked.
non_staked_balance = 1000000000000
# VP for the validator account
validator_vp = "vp_user"
validator_vp = "vp_validator"
# Commission rate for rewards
commission_rate = 0.05
# Maximum change per epoch in the commission rate
Expand Down Expand Up @@ -122,6 +122,11 @@ filename = "vp_user.wasm"
# SHA-256 hash of the wasm file
sha256 = "dc7b97f0448f2369bd2401c3c1d8898f53cac8c464a8c1b1f7f81415a658625d"

# Default validator VP
[wasm.vp_validator]
# filename (relative to wasm path used by the node)
filename = "vp_validator.wasm"

# Token VP
[wasm.vp_token]
filename = "vp_token.wasm"
Expand Down
2 changes: 1 addition & 1 deletion proof_of_stake/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub mod testing {
/// Get an arbitrary rate - a Decimal value between 0 and 1 inclusive, with
/// some fixed precision
pub fn arb_rate() -> impl Strategy<Value = Decimal> {
(0..100_001_u64)
(0..=100_000_u64)
.prop_map(|num| Decimal::from(num) / Decimal::from(100_000_u64))
}
}
Loading