Skip to content

Commit

Permalink
handle errors for unjail-validator tx in the client
Browse files Browse the repository at this point in the history
  • Loading branch information
brentstone committed Jul 6, 2023
1 parent 9fa2bed commit 856e1a6
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 15 deletions.
2 changes: 2 additions & 0 deletions proof_of_stake/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2688,6 +2688,8 @@ where
}
}

/// Collect the details of all of the enqueued slashes to be processed in future
/// epochs into a nested map
pub fn find_all_enqueued_slashes<S>(
storage: &S,
) -> storage_api::Result<HashMap<Address, BTreeMap<Epoch, Vec<Slash>>>>
Expand Down
28 changes: 20 additions & 8 deletions shared/src/ledger/queries/vp/pos.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
//! Queries router and handlers for PoS validity predicate
use std::collections::{HashMap, HashSet};
use std::collections::{BTreeMap, HashMap, HashSet};

use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use namada_core::ledger::storage_api::collections::lazy_map;
use namada_core::ledger::storage_api::OptionExt;
use namada_proof_of_stake::parameters::PosParams;
use namada_proof_of_stake::types::{
BondId, BondsAndUnbondsDetail, BondsAndUnbondsDetails, CommissionPair,
Slash, ValidatorState, WeightedValidator,
};
use namada_proof_of_stake::{
self, below_capacity_validator_set_handle, bond_amount, bond_handle,
consensus_validator_set_handle, enqueued_slashes_handle,
find_all_enqueued_slashes, find_all_slashes, find_delegation_validators,
find_delegations, read_all_validator_addresses, read_pos_params,
read_total_stake, read_validator_max_commission_rate_change,
read_validator_stake, unbond_handle, validator_commission_rate_handle,
validator_slashes_handle, validator_state_handle,
consensus_validator_set_handle, find_all_enqueued_slashes,
find_all_slashes, find_delegation_validators, find_delegations,
read_all_validator_addresses, read_pos_params, read_total_stake,
read_validator_max_commission_rate_change, read_validator_stake,
unbond_handle, validator_commission_rate_handle, validator_slashes_handle,
validator_state_handle,
};

use crate::ledger::queries::types::RequestCtx;
Expand Down Expand Up @@ -59,6 +60,8 @@ router! {POS,
// TODO: add "below_threshold"
},

( "pos_params") -> PosParams = pos_params,

( "total_stake" / [epoch: opt Epoch] )
-> token::Amount = total_stake,

Expand Down Expand Up @@ -140,6 +143,15 @@ impl<T> Enriched<T> {

// Handlers that implement the functions via `trait StorageRead`:

/// Get the PoS parameters
fn pos_params<D, H>(ctx: RequestCtx<'_, D, H>) -> storage_api::Result<PosParams>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
H: 'static + StorageHasher + Sync,
{
read_pos_params(ctx.wl_storage)
}

/// Find if the given address belongs to a validator account.
fn is_validator<D, H>(
ctx: RequestCtx<'_, D, H>,
Expand Down Expand Up @@ -532,7 +544,7 @@ where
H: 'static + StorageHasher + Sync,
{
let current_epoch = ctx.wl_storage.storage.last_epoch;
find_all_enqueued_slashes(storage)?
find_all_enqueued_slashes(ctx.wl_storage)
}

/// Native validator address by looking up the Tendermint address
Expand Down
26 changes: 25 additions & 1 deletion shared/src/ledger/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use namada_core::types::storage::Key;
use namada_core::types::token::{
Amount, DenominatedAmount, Denomination, MaspDenom, TokenAddress,
};
use namada_proof_of_stake::types::{BondsAndUnbondsDetails, CommissionPair};
use namada_proof_of_stake::parameters::PosParams;
use namada_proof_of_stake::types::{
BondsAndUnbondsDetails, CommissionPair, ValidatorState,
};
use serde::Serialize;
use tokio::time::Duration;

Expand Down Expand Up @@ -678,6 +681,13 @@ pub async fn get_proposal_votes<C: crate::ledger::queries::Client + Sync>(
}
}

/// Get the PoS parameters
pub async fn get_pos_params<C: crate::ledger::queries::Client + Sync>(
client: &C,
) -> PosParams {
unwrap_client_response::<C, _>(RPC.vp().pos().pos_params(client).await)
}

/// Get all validators in the given epoch
pub async fn get_all_validators<C: crate::ledger::queries::Client + Sync>(
client: &C,
Expand Down Expand Up @@ -718,6 +728,20 @@ pub async fn get_validator_stake<C: crate::ledger::queries::Client + Sync>(
.unwrap_or_default()
}

/// Query and return a validator's state
pub async fn get_validator_state<C: crate::ledger::queries::Client + Sync>(
client: &C,
validator: &Address,
epoch: Option<Epoch>,
) -> Option<ValidatorState> {
unwrap_client_response::<C, Option<ValidatorState>>(
RPC.vp()
.pos()
.validator_state(client, validator, &epoch)
.await,
)
}

/// Get the delegator's delegation
pub async fn get_delegators_delegation<
C: crate::ledger::queries::Client + Sync,
Expand Down
63 changes: 57 additions & 6 deletions shared/src/ledger/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use namada_core::types::dec::Dec;
use namada_core::types::storage::Key;
use namada_core::types::token::MaspDenom;
use namada_proof_of_stake::parameters::PosParams;
use namada_proof_of_stake::types::CommissionPair;
use namada_proof_of_stake::types::{CommissionPair, ValidatorState};
use prost::EncodeError;
use sha2::{Digest as Sha2Digest, Sha256};
use thiserror::Error;
Expand Down Expand Up @@ -106,6 +106,18 @@ pub enum Error {
/// Invalid validator address
#[error("The address {0} doesn't belong to any known validator account.")]
InvalidValidatorAddress(Address),
/// Not jailed at pipeline epoch
#[error(
"The validator address {0} is not jailed at epoch when it would be \
restored."
)]
ValidatorNotCurrentlyJailed(Address),
/// Validator still frozen and ineligible to be unjailed
#[error(
"The validator address {0} is currently frozen and ineligible to be \
unjailed."
)]
ValidatorFrozenFromUnjailing(Address),
/// Rate of epoch change too large for current epoch
#[error(
"New rate, {0}, is too large of a change with respect to the \
Expand Down Expand Up @@ -608,11 +620,7 @@ pub async fn submit_validator_commission_change<
.await
.unwrap();

// TODO: put following two let statements in its own function
let params_key = crate::ledger::pos::params_key();
let params = rpc::query_storage_value::<C, PosParams>(client, &params_key)
.await
.expect("Parameter should be defined.");
let params: PosParams = rpc::get_pos_params(client).await;

let validator = args.validator.clone();
if rpc::is_validator(client, &validator).await {
Expand Down Expand Up @@ -703,6 +711,49 @@ pub async fn submit_unjail_validator<
}
}

let params: PosParams = rpc::get_pos_params(client).await;
let current_epoch = rpc::query_epoch(client).await;
let pipeline_epoch = current_epoch + params.pipeline_len;

let validator_state_at_pipeline =
rpc::get_validator_state(client, &args.validator, Some(pipeline_epoch))
.await
.expect("Validator state should be defined.");
if validator_state_at_pipeline != ValidatorState::Jailed {
eprintln!(
"The given validator address {} is not jailed at the pipeline \
epoch when it would be restored to one of the validator sets.",
&args.validator
);
if !args.tx.force {
return Err(Error::ValidatorNotCurrentlyJailed(
args.validator.clone(),
));
}
}

let last_slash_epoch_key =
crate::ledger::pos::validator_last_slash_key(&args.validator);
let last_slash_epoch =
rpc::query_storage_value::<C, Epoch>(client, &last_slash_epoch_key)
.await;
if let Some(last_slash_epoch) = last_slash_epoch {
let eligible_epoch =
last_slash_epoch + params.slash_processing_epoch_offset();
if current_epoch < eligible_epoch {
eprintln!(
"The given validator address {} is currently frozen and not \
yet eligible to be unjailed.",
&args.validator
);
if !args.tx.force {
return Err(Error::ValidatorNotCurrentlyJailed(
args.validator.clone(),
));
}
}
}

let tx_code_hash =
query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap())
.await
Expand Down

0 comments on commit 856e1a6

Please sign in to comment.