diff --git a/.changelog/unreleased/improvments/2285-remove-hardcoded-masp-tokens.md b/.changelog/unreleased/improvments/2285-remove-hardcoded-masp-tokens.md new file mode 100644 index 0000000000..512ab72cb0 --- /dev/null +++ b/.changelog/unreleased/improvments/2285-remove-hardcoded-masp-tokens.md @@ -0,0 +1,5 @@ +- Previously, a hardcoded set of tokens were expected to be used in Masp conversions. + If these tokens did not have configs in genesis, this would lead to a panic after the first + epoch change. This PR fixes this to use the tokens found in genesis belonging to the MASP + rewards whitelist instead of hardcoding the tokens. + ([\#2285](https://github.com/anoma/namada/pull/2285)) \ No newline at end of file diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index c04f5a531b..68257787d1 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -246,6 +246,7 @@ pub mod cmds { .subcommand(QueryAccount::def().display_order(5)) .subcommand(QueryTransfers::def().display_order(5)) .subcommand(QueryConversions::def().display_order(5)) + .subcommand(QueryMaspRewardTokens::def().display_order(5)) .subcommand(QueryBlock::def().display_order(5)) .subcommand(QueryBalance::def().display_order(5)) .subcommand(QueryBonds::def().display_order(5)) @@ -313,6 +314,8 @@ pub mod cmds { let query_transfers = Self::parse_with_ctx(matches, QueryTransfers); let query_conversions = Self::parse_with_ctx(matches, QueryConversions); + let query_masp_reward_tokens = + Self::parse_with_ctx(matches, QueryMaspRewardTokens); let query_block = Self::parse_with_ctx(matches, QueryBlock); let query_balance = Self::parse_with_ctx(matches, QueryBalance); let query_bonds = Self::parse_with_ctx(matches, QueryBonds); @@ -370,6 +373,7 @@ pub mod cmds { .or(query_epoch) .or(query_transfers) .or(query_conversions) + .or(query_masp_reward_tokens) .or(query_block) .or(query_balance) .or(query_bonds) @@ -456,6 +460,7 @@ pub mod cmds { QueryAccount(QueryAccount), QueryTransfers(QueryTransfers), QueryConversions(QueryConversions), + QueryMaspRewardTokens(QueryMaspRewardTokens), QueryBlock(QueryBlock), QueryBalance(QueryBalance), QueryBonds(QueryBonds), @@ -1670,6 +1675,28 @@ pub mod cmds { } } + #[derive(Clone, Debug)] + pub struct QueryMaspRewardTokens(pub args::Query); + + impl SubCmd for QueryMaspRewardTokens { + const CMD: &'static str = "masp-reward-tokens"; + + fn parse(matches: &ArgMatches) -> Option { + matches.subcommand_matches(Self::CMD).map(|matches| { + QueryMaspRewardTokens(args::Query::parse(matches)) + }) + } + + fn def() -> App { + App::new(Self::CMD) + .about( + "Query the tokens which can earn MASP rewards while \ + shielded.", + ) + .add_args::>() + } + } + #[derive(Clone, Debug)] pub struct QueryBlock(pub args::Query); diff --git a/apps/src/lib/cli/client.rs b/apps/src/lib/cli/client.rs index 9602f80cdd..73728898c8 100644 --- a/apps/src/lib/cli/client.rs +++ b/apps/src/lib/cli/client.rs @@ -416,6 +416,16 @@ impl CliApi { let namada = ctx.to_sdk(client, io); rpc::query_conversions(&namada, args).await; } + Sub::QueryMaspRewardTokens(QueryMaspRewardTokens( + mut args, + )) => { + let client = client.unwrap_or_else(|| { + C::from_tendermint_address(&mut args.ledger_address) + }); + client.wait_until_node_is_synced(&io).await?; + let namada = ctx.to_sdk(client, io); + rpc::query_masp_reward_tokens(&namada).await; + } Sub::QueryBlock(QueryBlock(mut args)) => { let client = client.unwrap_or_else(|| { C::from_tendermint_address(&mut args.ledger_address) diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index 43acdc9302..343a8c9bf6 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -2428,6 +2428,17 @@ pub async fn query_conversion( namada_sdk::rpc::query_conversion(client, asset_type).await } +/// Query to read the tokens that earn masp rewards. +pub async fn query_masp_reward_tokens(context: &impl Namada) { + let tokens = namada_sdk::rpc::query_masp_reward_tokens(context.client()) + .await + .expect("The tokens that may earn MASP rewards should be defined"); + display_line!(context.io(), "The following tokens may ear MASP rewards:"); + for (alias, address) in tokens { + display_line!(context.io(), "{}: {}", alias, address); + } +} + /// Query a wasm code hash pub async fn query_wasm_code_hash( context: &impl Namada, diff --git a/core/src/ledger/masp_conversions.rs b/core/src/ledger/masp_conversions.rs index ab915c22e2..a1fef729ef 100644 --- a/core/src/ledger/masp_conversions.rs +++ b/core/src/ledger/masp_conversions.rs @@ -214,29 +214,15 @@ where }; use rayon::prelude::ParallelSlice; - use crate::types::address; - // The derived conversions will be placed in MASP address space let masp_addr = MASP; - let tokens = address::tokens(); - let mut masp_reward_keys: Vec<_> = tokens - .into_keys() - .map(|k| { - wl_storage - .storage - .conversion_state - .tokens - .get(k) - .unwrap_or_else(|| { - panic!( - "Could not find token alias {} in MASP conversion \ - state.", - k - ) - }) - .clone() - }) + let mut masp_reward_keys: Vec<_> = wl_storage + .storage + .conversion_state + .tokens + .values() + .cloned() .collect(); // Put the native rewards first because other inflation computations depend // on it diff --git a/sdk/src/queries/shell.rs b/sdk/src/queries/shell.rs index 23f7441cae..813348dacb 100644 --- a/sdk/src/queries/shell.rs +++ b/sdk/src/queries/shell.rs @@ -84,6 +84,10 @@ router! {SHELL, // Conversion state access - read conversion ( "conversions" ) -> BTreeMap = read_conversions, + + // Conversion state access - read conversion + ( "masp_reward_tokens" ) -> BTreeMap = masp_reward_tokens, + // Block results access - read bit-vec ( "results" ) -> Vec = read_results, @@ -210,6 +214,17 @@ where } } +/// Query to read the tokens that earn masp rewards. +fn masp_reward_tokens( + ctx: RequestCtx<'_, D, H, V, T>, +) -> storage_api::Result> +where + D: 'static + DB + for<'iter> DBIter<'iter> + Sync, + H: 'static + StorageHasher + Sync, +{ + Ok(ctx.wl_storage.storage.conversion_state.tokens.clone()) +} + fn epoch( ctx: RequestCtx<'_, D, H, V, T>, ) -> storage_api::Result diff --git a/sdk/src/rpc.rs b/sdk/src/rpc.rs index 6dc6850193..fd46ac2642 100644 --- a/sdk/src/rpc.rs +++ b/sdk/src/rpc.rs @@ -283,6 +283,13 @@ pub async fn query_conversions( convert_response::(RPC.shell().read_conversions(client).await) } +/// Query to read the tokens that earn masp rewards. +pub async fn query_masp_reward_tokens( + client: &C, +) -> Result, Error> { + convert_response::(RPC.shell().masp_reward_tokens(client).await) +} + /// Query a wasm code hash pub async fn query_wasm_code_hash( context: &impl Namada,