Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

erwan: debug branch #3653

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ee95a49
lint: fix undefined var in smoke test script
conorsch Jan 24, 2024
e7bdfe2
staking: first pass at reworking rate calculations (wip)
erwanor Jan 18, 2024
a2513de
staking: port the rest of staking calculations
erwanor Jan 19, 2024
a5d3cc1
staking: add note on `reward_amount`
erwanor Jan 19, 2024
5161bf4
staking: modify proto messages
erwanor Jan 20, 2024
05b2fd7
staking: restore conversion traits
erwanor Jan 20, 2024
946ae99
staking: convert voting power to `Amount`
erwanor Jan 20, 2024
c0d8454
staking(protos): change `ValidatorStatus` to use `Amount`s
erwanor Jan 20, 2024
2d96095
staking: regenerate protobufs with status changes
erwanor Jan 20, 2024
3e2383d
staking(rate): remove unused `scaling_factor`
erwanor Jan 20, 2024
26f81ba
staking: use `DomainFuture` for `validator_power`
erwanor Jan 22, 2024
8a50bf7
distributions: issuance budget in staking units
erwanor Jan 23, 2024
cd05b14
staking: add `FP_SCALING_FACTOR` constant
erwanor Jan 23, 2024
248091d
staking(rate): rewrite `RateData::next_epoch`
erwanor Jan 23, 2024
f009078
staking(rate): rework `RateData::delegation_amount`
erwanor Jan 23, 2024
b01d468
staking(rate): rework `unbonded_amount`
erwanor Jan 23, 2024
9aa773c
staking(rate): fix voting power calculations
erwanor Jan 23, 2024
2e0700c
staking(rate): base exchange rate calculation rewrite
erwanor Jan 23, 2024
2652a05
staking(rate): use scaling factor constant
erwanor Jan 23, 2024
1ddbe41
staking(genesis): rename initial rate data
erwanor Jan 23, 2024
f6a6d7a
staking(rate): adjust end-epoch processing
erwanor Jan 23, 2024
4172a3a
staking(funding): fix funding stream calculations
erwanor Jan 23, 2024
6b40d55
staking(rate): remove noisy debugging statements
erwanor Jan 23, 2024
86827f6
penumbra: regenerate protos
erwanor Jan 23, 2024
366b76d
staking(funding): adjust reward amount flow
erwanor Jan 23, 2024
16f1390
staking: fix missing `Amount` from rebase
erwanor Jan 23, 2024
16d7d28
staking(rate): move `FP_SCALING_FACTOR` into rate module
erwanor Jan 23, 2024
47fee3c
penumbra: add proto descriptor
erwanor Jan 23, 2024
769d770
pcli: log `delegate_undelegate` execution
erwanor Jan 23, 2024
ff4f6f7
ci: disable pclientd test
erwanor Jan 24, 2024
2ccb8d1
pcli(integration): don't match an exact amount of delegation tokens
erwanor Jan 24, 2024
3d7d166
pcli(integration): tweak regex
erwanor Jan 24, 2024
c7c8499
pcli(integration): match capture group
erwanor Jan 24, 2024
0cb2ae2
ci: now try to log network integration at debug
erwanor Jan 24, 2024
9b96af6
pcli: fix test!
erwanor Jan 24, 2024
4c192b2
fix fmt
erwanor Jan 24, 2024
b10ca25
run now
erwanor Jan 24, 2024
05b3f8e
ok fr
erwanor Jan 24, 2024
2c28e17
remove a test
erwanor Jan 24, 2024
f9ea27c
last run
erwanor Jan 24, 2024
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
17 changes: 9 additions & 8 deletions crates/bin/pcli/src/command/query/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{fs::File, io::Write};
use anyhow::{Context, Result};
use comfy_table::{presets, Table};
use futures::TryStreamExt;
use penumbra_num::Amount;
use penumbra_proto::core::component::stake::v1alpha1::{
query_service_client::QueryServiceClient as StakeQueryServiceClient, ValidatorInfoRequest,
};
Expand Down Expand Up @@ -60,14 +61,14 @@ impl ValidatorCmd {
// Sort by voting power (descending), active first, then inactive
validators.sort_by(|a, b| {
let av = if matches!(a.status.state, validator::State::Active) {
(a.status.voting_power, 0)
(a.status.voting_power, Amount::zero())
} else {
(0, a.status.voting_power)
(Amount::zero(), a.status.voting_power)
};
let bv = if matches!(b.status.state, validator::State::Active) {
(b.status.voting_power, 0)
(b.status.voting_power, Amount::zero())
} else {
(0, b.status.voting_power)
(Amount::zero(), b.status.voting_power)
};

bv.cmp(&av)
Expand All @@ -77,12 +78,12 @@ impl ValidatorCmd {
.iter()
.filter_map(|v| {
if let validator::State::Active = v.status.state {
Some(v.status.voting_power)
Some(v.status.voting_power.value())
} else {
None
}
})
.sum::<u64>() as f64;
.sum::<u128>() as f64;

let mut table = Table::new();
table.load_preset(presets::NOTHING);
Expand All @@ -96,10 +97,10 @@ impl ValidatorCmd {
]);

for v in validators {
let voting_power = (v.status.voting_power as f64) * 1e-6; // apply udelegation factor
let voting_power = (v.status.voting_power.value() as f64) * 1e-6; // apply udelegation factor
let active_voting_power = if matches!(v.status.state, validator::State::Active)
{
v.status.voting_power as f64
v.status.voting_power.value() as f64
} else {
0.0
};
Expand Down
2 changes: 1 addition & 1 deletion crates/bin/pcli/src/command/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ impl TxCmd {
.set_gas_prices(gas_prices)
.set_fee_tier((*fee_tier).into());
let plan = planner
.delegate(unbonded_amount.value(), rate_data)
.delegate(unbonded_amount, rate_data)
.plan(app.view(), AddressIndex::new(*source))
.await
.context("can't plan delegation")?;
Expand Down
7 changes: 5 additions & 2 deletions crates/bin/pcli/src/command/view/staked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,15 @@ impl StakedCmd {
amount: info
.rate_data
// TODO fix with new rate calcs
.unbonded_amount(delegation.amount.value())
.unbonded_amount(delegation.amount)
.into(),
asset_id: *STAKING_TOKEN_ASSET_ID,
};

let rate = info.rate_data.validator_exchange_rate as f64 / 1_0000_0000.0;
let rate = {
let validator_exchange_rate = info.rate_data.validator_exchange_rate.value() as f64;
validator_exchange_rate / 1_0000_0000.0
};

table.add_row(vec![
info.validator.name.clone(),
Expand Down
44 changes: 42 additions & 2 deletions crates/bin/pcli/tests/network_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ fn transaction_sweep() {
#[ignore]
#[test]
fn delegate_and_undelegate() {
tracing_subscriber::fmt::try_init().ok();
tracing::info!("delegate_and_undelegate");
let tmpdir = load_wallet_into_tmpdir();

// Get a validator from the testnet.
Expand All @@ -246,6 +248,7 @@ fn delegate_and_undelegate() {

let mut num_attempts = 0;
loop {
tracing::info!(attempt_number = num_attempts, "attempting delegation");
// Delegate a tiny bit of penumbra to the validator.
let mut delegate_cmd = Command::cargo_bin("pcli").unwrap();
delegate_cmd
Expand All @@ -260,57 +263,92 @@ fn delegate_and_undelegate() {
])
.timeout(std::time::Duration::from_secs(TIMEOUT_COMMAND_SECONDS));
let delegation_result = delegate_cmd.assert().try_success();
tracing::info!(?delegation_result, "delegation result");

// If the undelegation command succeeded, we can exit this loop.
if delegation_result.is_ok() {
tracing::info!("delegation succeeded");
break;
} else {
tracing::info!("delegation failed");
num_attempts += 1;
if num_attempts >= max_attempts {
panic!("Exceeded max attempts for fallible command");
}
}
}

tracing::info!("check that we have some of the delegation token");
// Check we have some of the delegation token for that validator now.
let mut balance_cmd = Command::cargo_bin("pcli").unwrap();
balance_cmd
.args(["--home", tmpdir.path().to_str().unwrap(), "view", "balance"])
.timeout(std::time::Duration::from_secs(TIMEOUT_COMMAND_SECONDS));

balance_cmd
.assert()
.stdout(predicate::str::is_match(validator.as_str()).unwrap());

let balance_output = balance_cmd.output().unwrap().stdout;

let balance_output_string = String::from_utf8_lossy(&balance_output);

tracing::debug!(?balance_output_string, "balance output string");

// We successfully delegated. But since the validator exchange rates are dynamic, we
// need to pull the amount of delegation tokens we obtained so that we can later
// try to execute an undelegation (`tx undelegate <AMOUNT><DELEGATION_TOKEN_DENOM>`).
// To do this, we use a regex to extract the amount of delegation tokens we obtained:
//
//
let delegation_token_pattern = Regex::new(r"(\d+\.?\d+[a-z]?delegation_[a-zA-Z0-9]*)").unwrap();
let (delegation_token_str, [_match]) = delegation_token_pattern
.captures(&balance_output_string)
.expect("can find delegation token in balance output")
.extract();

tracing::info!("check passed, now undelegate");

// Now undelegate. We attempt `max_attempts` times in case an epoch boundary passes
// while we prepare the delegation. See issues #1522, #2047.
let mut num_attempts = 0;
loop {
let amount_to_undelegate = format!("0.99delegation_{}", validator.as_str());
tracing::info!(attempt_number = num_attempts, "attempting undelegation");
let mut undelegate_cmd = Command::cargo_bin("pcli").unwrap();
undelegate_cmd
.args([
"--home",
tmpdir.path().to_str().unwrap(),
"tx",
"undelegate",
amount_to_undelegate.as_str(),
delegation_token_str,
])
.timeout(std::time::Duration::from_secs(TIMEOUT_COMMAND_SECONDS));
let undelegation_result = undelegate_cmd.assert().try_success();

tracing::info!(?undelegation_result, "undelegation result");
// If the undelegation command succeeded, we can exit this loop.
if undelegation_result.is_ok() {
tracing::info!("undelegation succeeded");
break;
} else {
num_attempts += 1;
tracing::info!(
?undelegation_result,
num_attempts,
max_attempts,
"undelegation failed"
);
if num_attempts >= max_attempts {
panic!("Exceeded max attempts for fallible command");
}
}
}

tracing::info!("wait for an epoch");
// Wait for the epoch duration.
thread::sleep(*UNBONDING_DURATION);
tracing::info!("epoch passed, claiming");
let mut undelegate_claim_cmd = Command::cargo_bin("pcli").unwrap();
undelegate_claim_cmd
.args([
Expand All @@ -320,7 +358,9 @@ fn delegate_and_undelegate() {
"undelegate-claim",
])
.timeout(std::time::Duration::from_secs(TIMEOUT_COMMAND_SECONDS));
tracing::info!(?undelegate_claim_cmd, "claiming");
undelegate_claim_cmd.assert().success();
tracing::info!("success!");
sync(&tmpdir);
}

Expand Down
Binary file modified crates/cnidarium/src/gen/proto_descriptor.bin.no_lfs
Binary file not shown.
23 changes: 20 additions & 3 deletions crates/core/component/distributions/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use anyhow::{Context, Result};
use async_trait::async_trait;
use cnidarium::StateWrite;
use cnidarium_component::Component;
use penumbra_asset::STAKING_TOKEN_DENOM;
use penumbra_num::Amount;
use tendermint::v0_37::abci;
use tracing::instrument;
Expand Down Expand Up @@ -59,12 +60,14 @@ trait DistributionManager: StateWriteExt {
let current_epoch = self.get_epoch_for_height(current_block_height).await?;
let num_blocks = current_block_height
.checked_sub(current_epoch.start_height)
.expect("epoch start height is less than or equal to current block height");
.unwrap_or_else(|| panic!("epoch start height is less than or equal to current block height (epoch_start={}, current_height={}", current_epoch.start_height, current_block_height));

// TODO(erwan): Will make the distribution chain param an `Amount`
// in a subsequent PR. Want to avoid conflicts with other in-flight changes.
let staking_issuance_per_block = self
.get_distributions_params()
.await?
.staking_issuance_per_block;
.staking_issuance_per_block as u128;

tracing::debug!(
number_of_blocks_in_epoch = num_blocks,
Expand All @@ -73,9 +76,23 @@ trait DistributionManager: StateWriteExt {
);

let new_issuance_for_epoch = staking_issuance_per_block
.checked_mul(num_blocks)
.checked_mul(num_blocks as u128) /* Safe to cast a `u64` to `u128` */
.expect("infaillible unless issuance is pathological");

tracing::debug!(
?new_issuance_for_epoch,
"computed new issuance for epoch (pre-scaled)"
);

let new_issuance_for_epoch = STAKING_TOKEN_DENOM
.default_unit()
.value(new_issuance_for_epoch.into())
.amount;

tracing::debug!(
?new_issuance_for_epoch,
"computed new issuance for epoch (scaled)"
);
Ok(Amount::from(new_issuance_for_epoch))
}

Expand Down
4 changes: 2 additions & 2 deletions crates/core/component/governance/src/component/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ pub trait StateReadExt: StateRead + penumbra_stake::StateReadExt {
};

// Check that the unbonded amount is correct relative to that exchange rate
if rate_data.unbonded_amount(value.amount.value()) != unbonded_amount.value() {
if rate_data.unbonded_amount(value.amount).value() != unbonded_amount.value() {
anyhow::bail!(
"unbonded amount {}{} does not correspond to {} staked delegation tokens for validator {} using the exchange rate at the start of proposal {}",
unbonded_amount,
Expand Down Expand Up @@ -624,7 +624,7 @@ pub trait StateWriteExt: StateWrite + penumbra_ibc::component::ConnectionStateWr
state_key::rate_data_at_proposal_start(proposal_id, identity_key),
rate_data,
);
self.put_proto(
self.put(
state_key::voting_power_at_proposal_start(proposal_id, identity_key),
power,
)
Expand Down
54 changes: 54 additions & 0 deletions crates/core/component/shielded-pool/src/component/supply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,60 @@ pub trait SupplyWrite: StateWrite {
}
}

async fn increase_token_supply(
&mut self,
asset_id: &asset::Id,
amount_to_add: Amount,
) -> Result<()> {
let key = state_key::token_supply(asset_id);
let current_supply: Amount = self.get(&key).await?.unwrap_or(0u128.into());

tracing::debug!(
?current_supply,
?amount_to_add,
?asset_id,
"increasing token supply"
);
let new_supply = current_supply.checked_add(&amount_to_add).ok_or_else(|| {
anyhow::anyhow!(
"overflow updating token {} supply {} with delta {}",
asset_id,
current_supply,
amount_to_add
)
})?;

self.put(key, new_supply);
Ok(())
}

async fn decrease_token_supply(
&mut self,
asset_id: &asset::Id,
amount_to_sub: Amount,
) -> Result<()> {
let key = state_key::token_supply(asset_id);
let current_supply: Amount = self.get(&key).await?.unwrap_or(0u128.into());

tracing::debug!(
?current_supply,
?amount_to_sub,
?asset_id,
"decreasing token supply"
);
let new_supply = current_supply.checked_sub(&amount_to_sub).ok_or_else(|| {
anyhow::anyhow!(
"overflow updating token {} supply {} with delta {}",
asset_id,
current_supply,
amount_to_sub
)
})?;

self.put(key, new_supply);
Ok(())
}

// TODO: should this really be separate from note management?
// #[instrument(skip(self, change))]
async fn update_token_supply(&mut self, asset_id: &asset::Id, change: i128) -> Result<()> {
Expand Down
5 changes: 2 additions & 3 deletions crates/core/component/stake/src/action_handler/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,9 @@ impl ActionHandler for Delegate {
//
// should give approximately the same results, they may not give
// exactly the same results.
let expected_delegation_amount =
next_rate_data.delegation_amount(d.unbonded_amount.value());
let expected_delegation_amount = next_rate_data.delegation_amount(d.unbonded_amount);

if expected_delegation_amount != d.delegation_amount.value() {
if expected_delegation_amount != d.delegation_amount {
anyhow::bail!(
"given {} unbonded stake, expected {} delegation tokens but description produces {}",
d.unbonded_amount,
Expand Down
4 changes: 2 additions & 2 deletions crates/core/component/stake/src/action_handler/undelegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ impl ActionHandler for Undelegate {
//
// should give approximately the same results, they may not give
// exactly the same results.
let expected_unbonded_amount = rate_data.unbonded_amount(u.delegation_amount.value());
let expected_unbonded_amount = rate_data.unbonded_amount(u.delegation_amount);

ensure!(
u.unbonded_amount.value() == expected_unbonded_amount,
u.unbonded_amount == expected_unbonded_amount,
"undelegation amount {} does not match expected amount {}",
u.unbonded_amount,
expected_unbonded_amount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ impl ActionHandler for UndelegateClaim {
.await?;
ensure!(
current_epoch.index >= end_epoch_index,
"cannot claim unbonding tokens before the end epoch"
"cannot claim unbonding tokens before the end epoch (current epoch: {}, end epoch: {})",
current_epoch.index,
end_epoch_index
);

// 2. That the penalty is correct.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ impl ActionHandler for validator::Definition {
let initial_rate_data = RateData {
identity_key: validator_key,
epoch_index: current_epoch.index,
validator_reward_rate: 0,
validator_exchange_rate: 1_0000_0000, // 1 represented as 1e8
validator_reward_rate: 0u128.into(),
validator_exchange_rate: 1_0000_0000u128.into(), // 1 represented as 1e8
};

state
Expand Down
Loading
Loading