Skip to content

Commit

Permalink
Merge 'origin/tomas/find-validator-by-tm' (#1344)
Browse files Browse the repository at this point in the history
* origin/tomas/find-validator-by-tm:
  changelog: add #1344
  pos: add a query to find validator by Tendermint address
  • Loading branch information
Fraccaman committed May 23, 2023
2 parents 2c6283f + 607ddb1 commit 819d0ed
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/unreleased/features/1344-find-validator-by-tm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- PoS: Added a client command `find-validator --tm-address <address>`
to find validator's Namada address by Tendermint address.
([\#1344](https://github.com/anoma/namada/pull/1344))
7 changes: 7 additions & 0 deletions apps/src/bin/namada-client/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,13 @@ pub async fn main() -> Result<()> {
rpc::query_delegations(&client, &mut ctx.wallet, args)
.await;
}
Sub::QueryFindValidator(QueryFindValidator(args)) => {
let client =
HttpClient::new(args.query.ledger_address.clone())
.unwrap();
let args = args.to_sdk(&mut ctx);
rpc::query_find_validator(&client, args).await;
}
Sub::QueryResult(QueryResult(args)) => {
wait_until_node_is_synched(&args.query.ledger_address)
.await;
Expand Down
53 changes: 53 additions & 0 deletions apps/src/lib/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ pub mod cmds {
.subcommand(QueryBondedStake::def().display_order(3))
.subcommand(QuerySlashes::def().display_order(3))
.subcommand(QueryDelegations::def().display_order(3))
.subcommand(QueryFindValidator::def().display_order(3))
.subcommand(QueryResult::def().display_order(3))
.subcommand(QueryRawBytes::def().display_order(3))
.subcommand(QueryProposal::def().display_order(3))
Expand Down Expand Up @@ -213,6 +214,8 @@ pub mod cmds {
let query_slashes = Self::parse_with_ctx(matches, QuerySlashes);
let query_delegations =
Self::parse_with_ctx(matches, QueryDelegations);
let query_find_validator =
Self::parse_with_ctx(matches, QueryFindValidator);
let query_result = Self::parse_with_ctx(matches, QueryResult);
let query_raw_bytes = Self::parse_with_ctx(matches, QueryRawBytes);
let query_proposal = Self::parse_with_ctx(matches, QueryProposal);
Expand Down Expand Up @@ -242,6 +245,7 @@ pub mod cmds {
.or(query_bonded_stake)
.or(query_slashes)
.or(query_delegations)
.or(query_find_validator)
.or(query_result)
.or(query_raw_bytes)
.or(query_proposal)
Expand Down Expand Up @@ -306,6 +310,7 @@ pub mod cmds {
QueryCommissionRate(QueryCommissionRate),
QuerySlashes(QuerySlashes),
QueryDelegations(QueryDelegations),
QueryFindValidator(QueryFindValidator),
QueryRawBytes(QueryRawBytes),
QueryProposal(QueryProposal),
QueryProposalResult(QueryProposalResult),
Expand Down Expand Up @@ -1461,6 +1466,28 @@ pub mod cmds {
}
}

#[derive(Clone, Debug)]
pub struct QueryFindValidator(pub args::QueryFindValidator<args::CliTypes>);

impl SubCmd for QueryFindValidator {
const CMD: &'static str = "find-validator";

fn parse(matches: &ArgMatches) -> Option<Self>
where
Self: Sized,
{
matches.subcommand_matches(Self::CMD).map(|matches| {
QueryFindValidator(args::QueryFindValidator::parse(matches))
})
}

fn def() -> App {
App::new(Self::CMD)
.about("Find a PoS validator by its Tendermint address.")
.add_args::<args::QueryFindValidator<args::CliTypes>>()
}
}

#[derive(Clone, Debug)]
pub struct QueryRawBytes(pub args::QueryRawBytes<args::CliTypes>);

Expand Down Expand Up @@ -1847,6 +1874,7 @@ pub mod args {
pub const TENDERMINT_TX_INDEX: ArgFlag = flag("tx-index");
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 TOKEN_OPT: ArgOpt<WalletAddress> = TOKEN.opt();
pub const TOKEN: Arg<WalletAddress> = arg("token");
pub const TRANSFER_SOURCE: Arg<WalletTransferSource> = arg("source");
Expand Down Expand Up @@ -3169,6 +3197,31 @@ pub mod args {
}
}

impl Args for QueryFindValidator<CliTypes> {
fn parse(matches: &ArgMatches) -> Self {
let query = Query::parse(matches);
let tm_addr = TM_ADDRESS.parse(matches);
Self { query, tm_addr }
}

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

impl CliToSdk<QueryFindValidator<SdkTypes>> for QueryFindValidator<CliTypes> {
fn to_sdk(self, ctx: &mut Context) -> QueryFindValidator<SdkTypes> {
QueryFindValidator::<SdkTypes> {
query: self.query.to_sdk(ctx),
tm_addr: self.tm_addr,
}
}
}

impl CliToSdk<QueryRawBytes<SdkTypes>> for QueryRawBytes<CliTypes> {
fn to_sdk(self, ctx: &mut Context) -> QueryRawBytes<SdkTypes> {
QueryRawBytes::<SdkTypes> {
Expand Down
24 changes: 24 additions & 0 deletions apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1562,6 +1562,30 @@ pub async fn query_delegations<C: namada::ledger::queries::Client + Sync>(
}
}

pub async fn query_find_validator<C: namada::ledger::queries::Client + Sync>(
client: &C,
args: args::QueryFindValidator,
) {
let args::QueryFindValidator { query: _, tm_addr } = args;
if tm_addr.len() != 40 {
eprintln!(
"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::<C, _>(
RPC.vp().pos().validator_by_tm_addr(client, &tm_addr).await,
);
match validator {
Some(address) => println!("Found validator address \"{address}\"."),
None => {
println!("No validator with Tendermint address {tm_addr} found.")
}
}
}

/// Dry run a transaction
pub async fn dry_run_tx<C: namada::ledger::queries::Client + Sync>(
client: &C,
Expand Down
9 changes: 9 additions & 0 deletions shared/src/ledger/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,15 @@ pub struct QueryDelegations<C: NamadaTypes = SdkTypes> {
pub owner: C::Address,
}

/// Query PoS to find a validator
#[derive(Clone, Debug)]
pub struct QueryFindValidator<C: NamadaTypes = SdkTypes> {
/// Common query args
pub query: Query<C>,
/// Tendermint address
pub tm_addr: String,
}

/// Query the raw bytes of given storage key
#[derive(Clone, Debug)]
pub struct QueryRawBytes<C: NamadaTypes = SdkTypes> {
Expand Down
15 changes: 15 additions & 0 deletions shared/src/ledger/queries/vp/pos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ router! {POS,

( "is_delegator" / [addr: Address ] / [epoch: opt Epoch] ) -> bool = is_delegator,

( "validator_by_tm_addr" / [tm_addr: String] )
-> Option<Address> = validator_by_tm_addr,

}

// Handlers that implement the functions via `trait StorageRead`:
Expand Down Expand Up @@ -459,3 +462,15 @@ where
{
find_all_slashes(ctx.wl_storage)
}

/// All slashes
fn validator_by_tm_addr<D, H>(
ctx: RequestCtx<'_, D, H>,
tm_addr: String,
) -> storage_api::Result<Option<Address>>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
H: 'static + StorageHasher + Sync,
{
namada_proof_of_stake::find_validator_by_raw_hash(ctx.wl_storage, tm_addr)
}

0 comments on commit 819d0ed

Please sign in to comment.