Skip to content

Commit

Permalink
look-up validator by native address and query consensus key
Browse files Browse the repository at this point in the history
  • Loading branch information
tzemanovic committed Jan 5, 2024
1 parent 76840b5 commit 178a40a
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 29 deletions.
28 changes: 21 additions & 7 deletions apps/src/lib/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3031,7 +3031,7 @@ pub mod args {
pub const TEMPLATES_PATH: Arg<PathBuf> = arg("templates-path");
pub const TIMEOUT_HEIGHT: ArgOpt<u64> = arg_opt("timeout-height");
pub const TIMEOUT_SEC_OFFSET: ArgOpt<u64> = arg_opt("timeout-sec-offset");
pub const TM_ADDRESS: Arg<String> = arg("tm-address");
pub const TM_ADDRESS: ArgOpt<String> = arg_opt("tm-address");
pub const TOKEN_OPT: ArgOpt<WalletAddress> = TOKEN.opt();
pub const TOKEN: Arg<WalletAddress> = arg("token");
pub const TOKEN_STR: Arg<String> = arg("token");
Expand Down Expand Up @@ -5733,15 +5733,26 @@ pub mod args {
fn parse(matches: &ArgMatches) -> Self {
let query = Query::parse(matches);
let tm_addr = TM_ADDRESS.parse(matches);
Self { query, tm_addr }
let validator_addr = VALIDATOR_OPT.parse(matches);
Self {
query,
tm_addr,
validator_addr,
}
}

fn def(app: App) -> App {
app.add_args::<Query<CliTypes>>().arg(
TM_ADDRESS
.def()
.help("The address of the validator in Tendermint."),
)
app.add_args::<Query<CliTypes>>()
.arg(
TM_ADDRESS
.def()
.help("The address of the validator in Tendermint."),
)
.arg(
VALIDATOR_OPT
.def()
.help("The native address of the validator."),
)
}
}

Expand All @@ -5750,6 +5761,9 @@ pub mod args {
QueryFindValidator::<SdkTypes> {
query: self.query.to_sdk(ctx),
tm_addr: self.tm_addr,
validator_addr: self
.validator_addr
.map(|x| ctx.borrow_chain_or_exit().get(&x)),
}
}
}
Expand Down
74 changes: 53 additions & 21 deletions apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2245,33 +2245,65 @@ pub async fn query_find_validator<N: Namada>(
context: &N,
args: args::QueryFindValidator,
) {
let args::QueryFindValidator { query: _, tm_addr } = args;
if tm_addr.len() != 40 {
edisplay_line!(
context.io(),
"Expected 40 characters in Tendermint address, got {}",
tm_addr.len()
let args::QueryFindValidator {
query: _,
tm_addr,
mut validator_addr,
} = args;
if let Some(tm_addr) = tm_addr {
if tm_addr.len() != 40 {
edisplay_line!(
context.io(),
"Expected 40 characters in Tendermint address, got {}",
tm_addr.len()
);
cli::safe_exit(1);
}
let tm_addr = tm_addr.to_ascii_uppercase();
let validator = unwrap_client_response::<N::Client, _>(
RPC.vp()
.pos()
.validator_by_tm_addr(context.client(), &tm_addr)
.await,
);
cli::safe_exit(1);
match validator {
Some(address) => {
display_line!(
context.io(),
"Found validator address \"{address}\"."
);
if validator_addr.is_none() {
validator_addr = Some(address);
}
}
None => {
display_line!(
context.io(),
"No validator with Tendermint address {tm_addr} found."
)
}
}
}
let tm_addr = tm_addr.to_ascii_uppercase();
let validator = unwrap_client_response::<N::Client, _>(
RPC.vp()
.pos()
.validator_by_tm_addr(context.client(), &tm_addr)
.await,
);
match validator {
Some(address) => {
if let Some(validator_addr) = validator_addr {
if let Some(consensus_key) = unwrap_client_response::<N::Client, _>(
RPC.vp()
.pos()
.consensus_key(context.client(), &validator_addr)
.await,
) {
let pkh: PublicKeyHash = (&consensus_key).into();
display_line!(context.io(), "Consensus key: {consensus_key}");
display_line!(
context.io(),
"Found validator address \"{address}\"."
)
}
None => {
"Tendermint key: {}",
tm_consensus_key_raw_hash(&consensus_key)
);
display_line!(context.io(), "Consensus key hash: {}", pkh);
} else {
display_line!(
context.io(),
"No validator with Tendermint address {tm_addr} found."
"Consensus key for validator {validator_addr} could not be \
found."
)
}
}
Expand Down
13 changes: 13 additions & 0 deletions proof_of_stake/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,3 +846,16 @@ where
let handle = LazySet::open(key);
handle.contains(storage, consensus_key)
}

/// Find a consensus key of a validator account.
pub fn get_consensus_key<S>(
storage: &S,
addr: &Address,
epoch: Epoch,
) -> storage_api::Result<Option<common::PublicKey>>
where
S: StorageRead,
{
let params = read_pos_params(storage)?;
validator_consensus_key_handle(addr).get(storage, epoch, &params)
}
4 changes: 3 additions & 1 deletion sdk/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1812,7 +1812,9 @@ pub struct QueryFindValidator<C: NamadaTypes = SdkTypes> {
/// Common query args
pub query: Query<C>,
/// Tendermint address
pub tm_addr: String,
pub tm_addr: Option<String>,
/// Native validator address
pub validator_addr: Option<C::Address>,
}

/// Query the raw bytes of given storage key
Expand Down
19 changes: 19 additions & 0 deletions sdk/src/queries/vp/pos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ router! {POS,
( "validator" ) = {
( "is_validator" / [addr: Address] ) -> bool = is_validator,

( "consensus_key" / [addr: Address] ) -> Option<common::PublicKey> = consensus_key,

( "addresses" / [epoch: opt Epoch] )
-> HashSet<Address> = validator_addresses,

Expand Down Expand Up @@ -194,6 +196,23 @@ where
namada_proof_of_stake::is_validator(ctx.wl_storage, &addr)
}

/// Find a consensus key of a validator account.
fn consensus_key<D, H, V, T>(
ctx: RequestCtx<'_, D, H, V, T>,
addr: Address,
) -> storage_api::Result<Option<common::PublicKey>>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
H: 'static + StorageHasher + Sync,
{
let current_epoch = ctx.wl_storage.storage.last_epoch;
namada_proof_of_stake::storage::get_consensus_key(
ctx.wl_storage,
&addr,
current_epoch,
)
}

/// Find if the given address is a delegator
fn is_delegator<D, H, V, T>(
ctx: RequestCtx<'_, D, H, V, T>,
Expand Down

0 comments on commit 178a40a

Please sign in to comment.