diff --git a/.changelog/unreleased/SDK/2051-native-masp.md b/.changelog/unreleased/SDK/2051-native-masp.md
new file mode 100644
index 0000000000..1187eb12fd
--- /dev/null
+++ b/.changelog/unreleased/SDK/2051-native-masp.md
@@ -0,0 +1,3 @@
+- Masp as internal address. Updated `aux_signing_data`
+ to return no key and 0 threshold if owner is masp.
+ ([\#2051](https://github.com/anoma/namada/pull/2051))
\ No newline at end of file
diff --git a/.changelog/unreleased/improvements/2051-native-masp.md b/.changelog/unreleased/improvements/2051-native-masp.md
new file mode 100644
index 0000000000..46bc4db2be
--- /dev/null
+++ b/.changelog/unreleased/improvements/2051-native-masp.md
@@ -0,0 +1,2 @@
+- Moved the masp vp to native.
+ ([\#2051](https://github.com/anoma/namada/pull/2051))
\ No newline at end of file
diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs
index 2cfb817bf6..34e88f7fab 100644
--- a/apps/src/lib/client/rpc.rs
+++ b/apps/src/lib/client/rpc.rs
@@ -39,7 +39,7 @@ use namada::ledger::pos::PosParams;
use namada::ledger::queries::RPC;
use namada::ledger::storage::ConversionState;
use namada::proof_of_stake::types::{ValidatorState, WeightedValidator};
-use namada::types::address::{masp, Address, InternalAddress};
+use namada::types::address::{Address, InternalAddress, MASP};
use namada::types::hash::Hash;
use namada::types::ibc::{is_ibc_denom, IbcTokenHash};
use namada::types::io::Io;
@@ -203,7 +203,7 @@ pub async fn query_transfers<'a>(
);
// Display the transparent changes first
for (account, MaspChange { ref asset, change }) in tfer_delta {
- if account != masp() {
+ if account != MASP {
display!(context.io(), " {}:", account);
let token_alias =
lookup_token_alias(context, asset, &account).await;
@@ -230,7 +230,7 @@ pub async fn query_transfers<'a>(
display!(context.io(), " {}:", fvk_map[&account]);
for (token_addr, val) in masp_change {
let token_alias =
- lookup_token_alias(context, &token_addr, &masp()).await;
+ lookup_token_alias(context, &token_addr, &MASP).await;
let sign = match val.cmp(&Change::zero()) {
Ordering::Greater => "+",
Ordering::Less => "-",
@@ -528,7 +528,7 @@ pub async fn query_pinned_balance<'a>(
.format_amount(token_addr, (*value).into())
.await;
let token_alias =
- lookup_token_alias(context, token_addr, &masp()).await;
+ lookup_token_alias(context, token_addr, &MASP).await;
display_line!(
context.io(),
" {}: {}",
@@ -821,7 +821,7 @@ pub async fn query_shielded_balance<'a>(
// Here the user wants to know the balance for a specific token
(Some(base_token), true) => {
let tokens =
- query_tokens(context, Some(&base_token), Some(&masp())).await;
+ query_tokens(context, Some(&base_token), Some(&MASP)).await;
for (token_alias, token) in tokens {
// Query the multi-asset balance at the given spending key
let viewing_key =
@@ -939,7 +939,7 @@ pub async fn query_shielded_balance<'a>(
}
for ((fvk, token), token_balance) in balance_map {
// Only assets with the current timestamp count
- let alias = lookup_token_alias(context, &token, &masp()).await;
+ let alias = lookup_token_alias(context, &token, &MASP).await;
display_line!(context.io(), "Shielded Token {}:", alias);
let formatted =
context.format_amount(&token, token_balance.into()).await;
@@ -1066,7 +1066,7 @@ pub async fn print_decoded_balance<'a>(
display_line!(
context.io(),
"{} : {}",
- lookup_token_alias(context, token_addr, &masp()).await,
+ lookup_token_alias(context, token_addr, &MASP).await,
context.format_amount(token_addr, (*amount).into()).await,
);
}
@@ -2335,7 +2335,7 @@ pub async fn query_conversions<'a>(
.wallet()
.await
.get_addresses_with_vp_type(AddressVpType::Token);
- let masp_addr = masp();
+ let masp_addr = MASP;
let key_prefix: Key = masp_addr.to_db_key().into();
let state_key = key_prefix
.push(&(token::CONVERSION_KEY_PREFIX.to_owned()))
diff --git a/apps/src/lib/config/genesis/chain.rs b/apps/src/lib/config/genesis/chain.rs
index 0f7b9cdd7e..bab430d4b1 100644
--- a/apps/src/lib/config/genesis/chain.rs
+++ b/apps/src/lib/config/genesis/chain.rs
@@ -5,7 +5,7 @@ use std::str::FromStr;
use borsh::{BorshDeserialize, BorshSerialize};
use borsh_ext::BorshSerializeExt;
use namada::ledger::parameters::EpochDuration;
-use namada::types::address::{masp, Address, EstablishedAddressGen};
+use namada::types::address::{Address, EstablishedAddressGen, MASP};
use namada::types::chain::{ChainId, ChainIdPrefix};
use namada::types::dec::Dec;
use namada::types::hash::Hash;
@@ -410,7 +410,7 @@ impl Finalized {
pub fn get_user_address(&self, alias: &Alias) -> Option
{
if alias.to_string() == *"masp" {
- return Some(masp());
+ return Some(MASP);
}
let established = self.transactions.established_account.as_ref()?;
let validators = self.transactions.validator_account.as_ref()?;
diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs
index e14b74da2d..f33f655a45 100644
--- a/apps/src/lib/node/ledger/shell/init_chain.rs
+++ b/apps/src/lib/node/ledger/shell/init_chain.rs
@@ -293,7 +293,7 @@ where
.insert(alias, address.clone());
}
}
- let key_prefix: Key = address::masp().to_db_key().into();
+ let key_prefix: Key = address::MASP.to_db_key().into();
// Save the current conversion state
let state_key = key_prefix
.push(&(token::CONVERSION_KEY_PREFIX.to_owned()))
@@ -355,11 +355,6 @@ where
genesis: &genesis::chain::Finalized,
vp_cache: &mut HashMap>,
) {
- let vp_code = self.lookup_vp("vp_masp", genesis, vp_cache);
- let code_hash = CodeHash::sha256(&vp_code);
- self.wl_storage
- .write_bytes(&Key::validity_predicate(&address::masp()), code_hash)
- .unwrap();
if let Some(txs) = genesis.transactions.established_account.as_ref() {
for FinalizedEstablishedAccountTx {
address,
diff --git a/apps/src/lib/wallet/defaults.rs b/apps/src/lib/wallet/defaults.rs
index e994203c88..71be346c70 100644
--- a/apps/src/lib/wallet/defaults.rs
+++ b/apps/src/lib/wallet/defaults.rs
@@ -73,6 +73,7 @@ mod dev {
("christel".into(), christel_address()),
("daewon".into(), daewon_address()),
("ester".into(), ester_address()),
+ ("masp".into(), namada::types::address::MASP),
]
.into_iter()
.collect();
diff --git a/benches/native_vps.rs b/benches/native_vps.rs
index b3eff8041b..b72de2d29e 100644
--- a/benches/native_vps.rs
+++ b/benches/native_vps.rs
@@ -33,24 +33,29 @@ use namada::ledger::native_vp::ethereum_bridge::nut::NonUsableTokens;
use namada::ledger::native_vp::ethereum_bridge::vp::EthBridge;
use namada::ledger::native_vp::ibc::context::PseudoExecutionContext;
use namada::ledger::native_vp::ibc::Ibc;
+use namada::ledger::native_vp::masp::MaspVp;
use namada::ledger::native_vp::multitoken::MultitokenVp;
use namada::ledger::native_vp::parameters::ParametersVp;
use namada::ledger::native_vp::{Ctx, NativeVp};
use namada::ledger::pgf::PgfVp;
use namada::ledger::pos::PosVP;
+use namada::namada_sdk::masp::verify_shielded_tx;
+use namada::namada_sdk::masp_primitives::transaction::Transaction;
use namada::proof_of_stake;
use namada::proof_of_stake::KeySeg;
use namada::proto::{Code, Section, Tx};
use namada::types::address::InternalAddress;
use namada::types::eth_bridge_pool::{GasFee, PendingTransfer};
+use namada::types::masp::{TransferSource, TransferTarget};
use namada::types::storage::{Epoch, TxIndex};
use namada::types::transaction::governance::{
InitProposalData, VoteProposalData,
};
use namada_apps::bench_utils::{
- generate_foreign_key_tx, BenchShell, TX_BRIDGE_POOL_WASM, TX_IBC_WASM,
- TX_INIT_PROPOSAL_WASM, TX_RESIGN_STEWARD, TX_TRANSFER_WASM,
- TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL_WASM,
+ generate_foreign_key_tx, BenchShell, BenchShieldedCtx,
+ ALBERT_PAYMENT_ADDRESS, ALBERT_SPENDING_KEY, BERTHA_PAYMENT_ADDRESS,
+ TX_BRIDGE_POOL_WASM, TX_IBC_WASM, TX_INIT_PROPOSAL_WASM, TX_RESIGN_STEWARD,
+ TX_TRANSFER_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL_WASM,
};
use namada_apps::wallet::defaults;
@@ -464,6 +469,135 @@ fn vp_multitoken(c: &mut Criterion) {
}
}
+// Generate and run masp transaction to be verified
+fn setup_storage_for_masp_verification(
+ bench_name: &str,
+) -> (BenchShieldedCtx, Tx) {
+ let amount = Amount::native_whole(500);
+ let mut shielded_ctx = BenchShieldedCtx::default();
+
+ let albert_spending_key = shielded_ctx
+ .wallet
+ .find_spending_key(ALBERT_SPENDING_KEY, None)
+ .unwrap()
+ .to_owned();
+ let albert_payment_addr = shielded_ctx
+ .wallet
+ .find_payment_addr(ALBERT_PAYMENT_ADDRESS)
+ .unwrap()
+ .to_owned();
+ let bertha_payment_addr = shielded_ctx
+ .wallet
+ .find_payment_addr(BERTHA_PAYMENT_ADDRESS)
+ .unwrap()
+ .to_owned();
+
+ // Shield some tokens for Albert
+ let shield_tx = shielded_ctx.generate_masp_tx(
+ amount,
+ TransferSource::Address(defaults::albert_address()),
+ TransferTarget::PaymentAddress(albert_payment_addr),
+ );
+ shielded_ctx.shell.execute_tx(&shield_tx);
+ shielded_ctx.shell.wl_storage.commit_tx();
+ shielded_ctx.shell.commit();
+
+ let signed_tx = match bench_name {
+ "shielding" => shielded_ctx.generate_masp_tx(
+ amount,
+ TransferSource::Address(defaults::albert_address()),
+ TransferTarget::PaymentAddress(albert_payment_addr),
+ ),
+ "unshielding" => shielded_ctx.generate_masp_tx(
+ amount,
+ TransferSource::ExtendedSpendingKey(albert_spending_key),
+ TransferTarget::Address(defaults::albert_address()),
+ ),
+ "shielded" => shielded_ctx.generate_masp_tx(
+ amount,
+ TransferSource::ExtendedSpendingKey(albert_spending_key),
+ TransferTarget::PaymentAddress(bertha_payment_addr),
+ ),
+ _ => panic!("Unexpected bench test"),
+ };
+ shielded_ctx.shell.execute_tx(&signed_tx);
+
+ (shielded_ctx, signed_tx)
+}
+
+fn masp(c: &mut Criterion) {
+ let mut group = c.benchmark_group("vp_masp");
+
+ for bench_name in ["shielding", "unshielding", "shielded"] {
+ group.bench_function(bench_name, |b| {
+ let (shielded_ctx, signed_tx) =
+ setup_storage_for_masp_verification(bench_name);
+ let (verifiers, keys_changed) = shielded_ctx
+ .shell
+ .wl_storage
+ .write_log
+ .verifiers_and_changed_keys(&BTreeSet::default());
+
+ let masp = MaspVp {
+ ctx: Ctx::new(
+ &Address::Internal(InternalAddress::Masp),
+ &shielded_ctx.shell.wl_storage.storage,
+ &shielded_ctx.shell.wl_storage.write_log,
+ &signed_tx,
+ &TxIndex(0),
+ VpGasMeter::new_from_tx_meter(
+ &TxGasMeter::new_from_sub_limit(u64::MAX.into()),
+ ),
+ &keys_changed,
+ &verifiers,
+ shielded_ctx.shell.vp_wasm_cache.clone(),
+ ),
+ };
+
+ b.iter(|| {
+ assert!(
+ masp.validate_tx(
+ &signed_tx,
+ masp.ctx.keys_changed,
+ masp.ctx.verifiers,
+ )
+ .unwrap()
+ );
+ })
+ });
+ }
+
+ group.finish();
+}
+
+fn masp_verify_shielded_tx(c: &mut Criterion) {
+ let mut group = c.benchmark_group("vp_masp_verify_shielded_tx");
+
+ for bench_name in ["shielding", "unshielding", "shielded"] {
+ group.bench_function(bench_name, |b| {
+ let (_, signed_tx) =
+ setup_storage_for_masp_verification(bench_name);
+
+ let transaction = signed_tx
+ .sections
+ .into_iter()
+ .filter_map(|section| match section {
+ Section::MaspTx(transaction) => Some(transaction),
+ _ => None,
+ })
+ .collect::>()
+ .first()
+ .unwrap()
+ .to_owned();
+ b.iter(|| {
+ assert!(verify_shielded_tx(&transaction));
+ })
+ });
+ }
+
+ group.finish();
+}
+
fn pgf(c: &mut Criterion) {
let mut group = c.benchmark_group("vp_pgf");
@@ -1146,6 +1280,8 @@ criterion_group!(
governance,
// slash_fund,
ibc,
+ masp,
+ masp_verify_shielded_tx,
vp_multitoken,
pgf,
eth_bridge_nut,
diff --git a/benches/vps.rs b/benches/vps.rs
index 9023e38bcd..16883d3547 100644
--- a/benches/vps.rs
+++ b/benches/vps.rs
@@ -14,24 +14,21 @@ use namada::ledger::gas::{TxGasMeter, VpGasMeter};
use namada::proto::{Code, Section};
use namada::types::hash::Hash;
use namada::types::key::ed25519;
-use namada::types::masp::{TransferSource, TransferTarget};
use namada::types::storage::{Key, TxIndex};
use namada::types::transaction::governance::VoteProposalData;
use namada::types::transaction::pos::{Bond, CommissionChange};
use namada::vm::wasm::run;
use namada_apps::bench_utils::{
- generate_foreign_key_tx, BenchShell, BenchShieldedCtx,
- ALBERT_PAYMENT_ADDRESS, ALBERT_SPENDING_KEY, BERTHA_PAYMENT_ADDRESS,
- TX_BOND_WASM, TX_CHANGE_VALIDATOR_COMMISSION_WASM, TX_REVEAL_PK_WASM,
- TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UPDATE_ACCOUNT_WASM,
- TX_VOTE_PROPOSAL_WASM, VP_VALIDATOR_WASM,
+ generate_foreign_key_tx, BenchShell, TX_BOND_WASM,
+ TX_CHANGE_VALIDATOR_COMMISSION_WASM, TX_REVEAL_PK_WASM, TX_TRANSFER_WASM,
+ TX_UNBOND_WASM, TX_UPDATE_ACCOUNT_WASM, TX_VOTE_PROPOSAL_WASM,
+ VP_VALIDATOR_WASM,
};
use namada_apps::wallet::defaults;
use sha2::Digest;
const VP_USER_WASM: &str = "vp_user.wasm";
const VP_IMPLICIT_WASM: &str = "vp_implicit.wasm";
-const VP_MASP_WASM: &str = "vp_masp.wasm";
fn vp_user(c: &mut Criterion) {
let mut group = c.benchmark_group("vp_user");
@@ -469,94 +466,5 @@ fn vp_validator(c: &mut Criterion) {
group.finish();
}
-fn vp_masp(c: &mut Criterion) {
- let mut group = c.benchmark_group("vp_masp");
-
- let amount = Amount::native_whole(500);
-
- for bench_name in ["shielding", "unshielding", "shielded"] {
- group.bench_function(bench_name, |b| {
- let mut shielded_ctx = BenchShieldedCtx::default();
- let vp_code_hash: Hash = shielded_ctx
- .shell
- .read_storage_key(&Key::wasm_hash(VP_MASP_WASM))
- .unwrap();
-
- let albert_spending_key = shielded_ctx
- .wallet
- .find_spending_key(ALBERT_SPENDING_KEY, None)
- .unwrap()
- .to_owned();
- let albert_payment_addr = shielded_ctx
- .wallet
- .find_payment_addr(ALBERT_PAYMENT_ADDRESS)
- .unwrap()
- .to_owned();
- let bertha_payment_addr = shielded_ctx
- .wallet
- .find_payment_addr(BERTHA_PAYMENT_ADDRESS)
- .unwrap()
- .to_owned();
-
- // Shield some tokens for Albert
- let shield_tx = shielded_ctx.generate_masp_tx(
- amount,
- TransferSource::Address(defaults::albert_address()),
- TransferTarget::PaymentAddress(albert_payment_addr),
- );
- shielded_ctx.shell.execute_tx(&shield_tx);
- shielded_ctx.shell.wl_storage.commit_tx();
- shielded_ctx.shell.commit();
-
- let signed_tx = match bench_name {
- "shielding" => shielded_ctx.generate_masp_tx(
- amount,
- TransferSource::Address(defaults::albert_address()),
- TransferTarget::PaymentAddress(albert_payment_addr),
- ),
- "unshielding" => shielded_ctx.generate_masp_tx(
- amount,
- TransferSource::ExtendedSpendingKey(albert_spending_key),
- TransferTarget::Address(defaults::albert_address()),
- ),
- "shielded" => shielded_ctx.generate_masp_tx(
- amount,
- TransferSource::ExtendedSpendingKey(albert_spending_key),
- TransferTarget::PaymentAddress(bertha_payment_addr),
- ),
- _ => panic!("Unexpected bench test"),
- };
- shielded_ctx.shell.execute_tx(&signed_tx);
- let (verifiers, keys_changed) = shielded_ctx
- .shell
- .wl_storage
- .write_log
- .verifiers_and_changed_keys(&BTreeSet::default());
-
- b.iter(|| {
- assert!(
- run::vp(
- vp_code_hash,
- &signed_tx,
- &TxIndex(0),
- &defaults::validator_address(),
- &shielded_ctx.shell.wl_storage.storage,
- &shielded_ctx.shell.wl_storage.write_log,
- &mut VpGasMeter::new_from_tx_meter(
- &TxGasMeter::new_from_sub_limit(u64::MAX.into())
- ),
- &keys_changed,
- &verifiers,
- shielded_ctx.shell.vp_wasm_cache.clone(),
- )
- .unwrap()
- );
- })
- });
- }
-
- group.finish();
-}
-
-criterion_group!(whitelisted_vps, vp_user, vp_implicit, vp_validator, vp_masp,);
+criterion_group!(whitelisted_vps, vp_user, vp_implicit, vp_validator,);
criterion_main!(whitelisted_vps);
diff --git a/core/src/ledger/gas.rs b/core/src/ledger/gas.rs
index 0fefccd983..092c0ba3b2 100644
--- a/core/src/ledger/gas.rs
+++ b/core/src/ledger/gas.rs
@@ -53,6 +53,8 @@ pub const WASM_MEMORY_PAGE_GAS: u32 =
pub const IBC_ACTION_VALIDATE_GAS: u64 = 7_511;
/// The cost to execute an Ibc action
pub const IBC_ACTION_EXECUTE_GAS: u64 = 47_452;
+/// The cost to execute a masp tx verification
+pub const MASP_VERIFY_SHIELDED_TX_GAS: u64 = 62_381_957;
/// Gas module result for functions that may fail
pub type Result = std::result::Result;
diff --git a/core/src/ledger/ibc/mod.rs b/core/src/ledger/ibc/mod.rs
index cf0962cdbd..2a4919100e 100644
--- a/core/src/ledger/ibc/mod.rs
+++ b/core/src/ledger/ibc/mod.rs
@@ -31,7 +31,7 @@ use crate::ibc::core::ics24_host::identifier::{
use crate::ibc::core::router::ModuleId;
use crate::ibc::core::{execute, validate, MsgEnvelope, RouterError};
use crate::ibc_proto::google::protobuf::Any;
-use crate::types::address::{masp, Address};
+use crate::types::address::{Address, MASP};
use crate::types::ibc::{
get_shielded_transfer, is_ibc_denom, EVENT_TYPE_DENOM_TRACE,
EVENT_TYPE_PACKET,
@@ -190,7 +190,7 @@ where
.or_else(|_| {
// Replace it with MASP address when the receiver is a
// payment address
- PaymentAddress::from_str(receiver).map(|_| masp())
+ PaymentAddress::from_str(receiver).map(|_| MASP)
})
.map_err(|_| {
Error::Denom(format!(
diff --git a/core/src/ledger/storage/masp_conversions.rs b/core/src/ledger/storage/masp_conversions.rs
index 5cbbca570a..87f9095dcb 100644
--- a/core/src/ledger/storage/masp_conversions.rs
+++ b/core/src/ledger/storage/masp_conversions.rs
@@ -13,7 +13,7 @@ use crate::ledger::inflation::{RewardsController, ValsToUpdate};
use crate::ledger::parameters;
use crate::ledger::storage_api::token::read_denom;
use crate::ledger::storage_api::{StorageRead, StorageWrite};
-use crate::types::address::Address;
+use crate::types::address::{Address, MASP};
use crate::types::dec::Dec;
use crate::types::storage::Epoch;
use crate::types::token::MaspDenom;
@@ -58,7 +58,7 @@ where
// a thousandth of the given asset.
let precision = 10u128.pow(std::cmp::max(u32::from(denomination.0), 3) - 3);
- let masp_addr = address::masp();
+ let masp_addr = MASP;
// Query the storage for information
//// information about the amount of tokens on the chain
@@ -213,7 +213,7 @@ where
use crate::types::storage::{self, KeySeg};
// The derived conversions will be placed in MASP address space
- let masp_addr = address::masp();
+ let masp_addr = MASP;
let key_prefix: storage::Key = masp_addr.to_db_key().into();
let tokens = address::tokens();
diff --git a/core/src/ledger/storage/mod.rs b/core/src/ledger/storage/mod.rs
index d12352ee71..999a0cbe93 100644
--- a/core/src/ledger/storage/mod.rs
+++ b/core/src/ledger/storage/mod.rs
@@ -41,7 +41,7 @@ use crate::ledger::storage::merkle_tree::{
};
use crate::tendermint::merkle::proof::ProofOps;
use crate::types::address::{
- masp, Address, EstablishedAddressGen, InternalAddress,
+ Address, EstablishedAddressGen, InternalAddress, MASP,
};
use crate::types::chain::{ChainId, CHAIN_ID_LENGTH};
use crate::types::hash::{Error as HashError, Hash};
@@ -491,7 +491,7 @@ where
.or_else(|_| self.rebuild_full_merkle_tree(height))?;
if self.block.height.0 > 0 {
// The derived conversions will be placed in MASP address space
- let masp_addr = masp();
+ let masp_addr = MASP;
let key_prefix: Key = masp_addr.to_db_key().into();
// Load up the conversions currently being given as query
// results
diff --git a/core/src/ledger/vp_env.rs b/core/src/ledger/vp_env.rs
index 1241adfed7..664e030786 100644
--- a/core/src/ledger/vp_env.rs
+++ b/core/src/ledger/vp_env.rs
@@ -109,7 +109,7 @@ where
/// Get the shielded action including the transfer and the masp tx
fn get_shielded_action(
&self,
- tx_data: Tx,
+ tx_data: &Tx,
) -> Result<(Transfer, Transaction), storage_api::Error> {
let signed = tx_data;
if let Ok(transfer) =
@@ -143,9 +143,6 @@ where
})
}
- /// Verify a MASP transaction
- fn verify_masp(&self, tx: Vec) -> Result;
-
/// Charge the provided gas for the current vp
fn charge_gas(&self, used_gas: u64) -> Result<(), storage_api::Error>;
diff --git a/core/src/types/address.rs b/core/src/types/address.rs
index 8656ee0598..2543fc7f54 100644
--- a/core/src/types/address.rs
+++ b/core/src/types/address.rs
@@ -60,6 +60,8 @@ pub const POS_SLASH_POOL: Address =
Address::Internal(InternalAddress::PosSlashPool);
/// Internal Governance address
pub const GOV: Address = Address::Internal(InternalAddress::Governance);
+/// Internal MASP address
+pub const MASP: Address = Address::Internal(InternalAddress::Masp);
/// Error from decoding address from string
pub type DecodeError = string_encoding::DecodeError;
@@ -121,6 +123,7 @@ impl From> for Address {
raw::Discriminant::IbcToken => Address::Internal(
InternalAddress::IbcToken(IbcTokenHash(*raw_addr.data())),
),
+ raw::Discriminant::Masp => Address::Internal(InternalAddress::Masp),
}
}
}
@@ -210,6 +213,11 @@ impl<'addr> From<&'addr Address> for raw::Address<'addr, raw::Validated> {
.validate()
.expect("This raw address is valid")
}
+ Address::Internal(InternalAddress::Masp) => {
+ raw::Address::from_discriminant(raw::Discriminant::Masp)
+ .validate()
+ .expect("This raw address is valid")
+ }
}
}
}
@@ -346,7 +354,7 @@ impl TryFrom for Address {
Address::decode(signer.as_ref()).or(
match crate::types::masp::PaymentAddress::from_str(signer.as_ref())
{
- Ok(_) => Ok(masp()),
+ Ok(_) => Ok(MASP),
Err(_) => Err(DecodeError::InvalidInnerEncoding(format!(
"Invalid address for IBC transfer: {signer}"
))),
@@ -485,6 +493,8 @@ pub enum InternalAddress {
Multitoken,
/// Pgf
Pgf,
+ /// Masp
+ Masp,
}
impl Display for InternalAddress {
@@ -505,6 +515,7 @@ impl Display for InternalAddress {
Self::Nut(eth_addr) => format!("Non-usable token: {eth_addr}"),
Self::Multitoken => "Multitoken".to_string(),
Self::Pgf => "PublicGoodFundings".to_string(),
+ Self::Masp => "MASP".to_string(),
}
)
}
@@ -519,6 +530,7 @@ impl InternalAddress {
"ethbridge" => Some(InternalAddress::EthBridge),
"bridgepool" => Some(InternalAddress::EthBridgePool),
"governance" => Some(InternalAddress::Governance),
+ "masp" => Some(InternalAddress::Masp),
_ => None,
}
}
@@ -566,12 +578,6 @@ pub fn kartoffel() -> Address {
.expect("The token address decoding shouldn't fail")
}
-/// Temporary helper for testing
-pub fn masp() -> Address {
- Address::decode("tnam1q9lm5pvkxhnw9wwwhu33vkvtylwfkn5kw53xwud8")
- .expect("The token address decoding shouldn't fail")
-}
-
/// Sentinel secret key to indicate a MASP source
pub fn masp_tx_key() -> crate::types::key::common::SecretKey {
use crate::types::key::common;
@@ -809,6 +815,7 @@ pub mod testing {
InternalAddress::Erc20(_) => {}
InternalAddress::Nut(_) => {}
InternalAddress::Pgf => {}
+ InternalAddress::Masp => {}
InternalAddress::Multitoken => {} /* Add new addresses in the
* `prop_oneof` below. */
};
@@ -825,6 +832,7 @@ pub mod testing {
Just(arb_nut()),
Just(InternalAddress::Multitoken),
Just(InternalAddress::Pgf),
+ Just(InternalAddress::Masp),
]
}
diff --git a/core/src/types/address/raw.rs b/core/src/types/address/raw.rs
index aade2af3a4..d975d219f9 100644
--- a/core/src/types/address/raw.rs
+++ b/core/src/types/address/raw.rs
@@ -63,6 +63,8 @@ pub enum Discriminant {
Nut = 12,
/// IBC token raw address.
IbcToken = 13,
+ /// MASP raw address.
+ Masp = 14,
}
/// Raw address representation.
diff --git a/core/src/types/masp.rs b/core/src/types/masp.rs
index 685394f72c..89994539b2 100644
--- a/core/src/types/masp.rs
+++ b/core/src/types/masp.rs
@@ -8,7 +8,7 @@ use borsh_ext::BorshSerializeExt;
use sha2::{Digest, Sha256};
use crate::impl_display_and_from_str_via_format;
-use crate::types::address::{masp, Address, DecodeError, HASH_HEX_LEN};
+use crate::types::address::{Address, DecodeError, HASH_HEX_LEN, MASP};
use crate::types::string_encoding::{
self, MASP_EXT_FULL_VIEWING_KEY_HRP, MASP_EXT_SPENDING_KEY_HRP,
MASP_PAYMENT_ADDRESS_HRP,
@@ -303,7 +303,7 @@ impl TransferSource {
Self::Address(x) => x.clone(),
// An ExtendedSpendingKey for a source effectively means that
// assets will be drawn from the MASP
- Self::ExtendedSpendingKey(_) => masp(),
+ Self::ExtendedSpendingKey(_) => MASP,
}
}
@@ -349,7 +349,7 @@ impl TransferTarget {
Self::Address(x) => x.clone(),
// An ExtendedSpendingKey for a source effectively means that
// assets will be drawn from the MASP
- Self::PaymentAddress(_) => masp(),
+ Self::PaymentAddress(_) => MASP,
}
}
diff --git a/core/src/types/token.rs b/core/src/types/token.rs
index 1b0e7a40d2..fbee830b47 100644
--- a/core/src/types/token.rs
+++ b/core/src/types/token.rs
@@ -18,7 +18,7 @@ use crate::ledger::storage as ledger_storage;
use crate::ledger::storage_api::token::read_denom;
use crate::ledger::storage_api::{self, StorageRead, StorageWrite};
use crate::types::address::{
- masp, Address, DecodeError as AddressError, InternalAddress,
+ Address, DecodeError as AddressError, InternalAddress, MASP,
};
use crate::types::dec::Dec;
use crate::types::hash::Hash;
@@ -1123,7 +1123,7 @@ pub fn is_denom_key(token_addr: &Address, key: &Key) -> bool {
pub fn is_masp_key(key: &Key) -> bool {
matches!(&key.segments[..],
[DbKeySeg::AddressSeg(addr), DbKeySeg::StringSeg(key)]
- if *addr == masp()
+ if *addr == MASP
&& (key == HEAD_TX_KEY
|| key.starts_with(TX_KEY_PREFIX)
|| key.starts_with(PIN_KEY_PREFIX)))
diff --git a/core/src/types/transaction/wrapper.rs b/core/src/types/transaction/wrapper.rs
index 8c4f1fb4a9..f9b032b3f4 100644
--- a/core/src/types/transaction/wrapper.rs
+++ b/core/src/types/transaction/wrapper.rs
@@ -15,7 +15,7 @@ pub mod wrapper_tx {
use thiserror::Error;
use crate::proto::{Code, Data, Section, Tx};
- use crate::types::address::{masp, Address};
+ use crate::types::address::{Address, MASP};
use crate::types::hash::Hash;
use crate::types::key::*;
use crate::types::storage::Epoch;
@@ -310,7 +310,7 @@ pub mod wrapper_tx {
);
let transfer = Transfer {
- source: masp(),
+ source: MASP,
target: self.fee_payer(),
token: self.fee.token.clone(),
amount: DenominatedAmount {
diff --git a/genesis/localnet/validity-predicates.toml b/genesis/localnet/validity-predicates.toml
index a0c2570121..907e7c522b 100644
--- a/genesis/localnet/validity-predicates.toml
+++ b/genesis/localnet/validity-predicates.toml
@@ -12,6 +12,3 @@ filename = "vp_user.wasm"
[wasm.vp_validator]
filename = "vp_validator.wasm"
-# MASP VP
-[wasm.vp_masp]
-filename = "vp_masp.wasm"
diff --git a/genesis/starter/validity-predicates.toml b/genesis/starter/validity-predicates.toml
index 863ec7ec38..9c9e76fc83 100644
--- a/genesis/starter/validity-predicates.toml
+++ b/genesis/starter/validity-predicates.toml
@@ -16,7 +16,3 @@ filename = "vp_validator.wasm"
[wasm.vp_token]
filename = "vp_token.wasm"
-# MASP VP
-[wasm.vp_masp]
-filename = "vp_masp.wasm"
-
diff --git a/sdk/src/masp.rs b/sdk/src/masp.rs
index 2ead173e52..68459688e0 100644
--- a/sdk/src/masp.rs
+++ b/sdk/src/masp.rs
@@ -48,7 +48,7 @@ use masp_proofs::bellman::groth16::PreparedVerifyingKey;
use masp_proofs::bls12_381::Bls12;
use masp_proofs::prover::LocalTxProver;
use masp_proofs::sapling::SaplingVerificationContext;
-use namada_core::types::address::{masp, Address};
+use namada_core::types::address::{Address, MASP};
use namada_core::types::masp::{
BalanceOwner, ExtendedViewingKey, PaymentAddress, TransferSource,
TransferTarget,
@@ -740,7 +740,7 @@ impl ShieldedContext {
Error,
> {
// The address of the MASP account
- let masp_addr = masp();
+ let masp_addr = MASP;
// Construct the key where last transaction pointer is stored
let head_tx_key = Key::from(masp_addr.to_db_key())
.push(&HEAD_TX_KEY.to_owned())
@@ -1340,7 +1340,7 @@ impl ShieldedContext {
}
}
// The address of the MASP account
- let masp_addr = masp();
+ let masp_addr = MASP;
// Construct the key for where the transaction ID would be stored
let pin_key = Key::from(masp_addr.to_db_key())
.push(&(PIN_KEY_PREFIX.to_owned() + &owner.hash()))
@@ -1919,8 +1919,8 @@ impl ShieldedContext {
if let Some(transfer) = transfer {
// Skip MASP addresses as they are already handled
// by ShieldedContext
- if transfer.source == masp()
- || transfer.target == masp()
+ if transfer.source == MASP
+ || transfer.target == MASP
{
continue;
}
diff --git a/sdk/src/signing.rs b/sdk/src/signing.rs
index 39120f8261..fb35662017 100644
--- a/sdk/src/signing.rs
+++ b/sdk/src/signing.rs
@@ -14,7 +14,7 @@ use namada_core::ledger::parameters::storage as parameter_storage;
use namada_core::proto::SignatureIndex;
use namada_core::types::account::AccountPublicKeysMap;
use namada_core::types::address::{
- masp, masp_tx_key, Address, ImplicitAddress,
+ masp_tx_key, Address, ImplicitAddress, InternalAddress, MASP,
};
use namada_core::types::key::*;
use namada_core::types::masp::{ExtendedViewingKey, PaymentAddress};
@@ -184,7 +184,7 @@ pub async fn tx_signers<'a>(
// Now actually fetch the signing key and apply it
match signer {
- Some(signer) if signer == masp() => Ok(vec![masp_tx_key().ref_to()]),
+ Some(signer) if signer == MASP => Ok(vec![masp_tx_key().ref_to()]),
Some(signer) => Ok(vec![find_pk(context, &signer).await?]),
None => other_err(
@@ -348,9 +348,14 @@ pub async fn aux_signing_data<'a>(
Some(AccountPublicKeysMap::from_iter(public_keys.clone())),
1u8,
),
- Some(owner @ Address::Internal(_)) => {
- return Err(Error::from(TxError::InvalidAccount(owner.encode())));
- }
+ Some(owner @ Address::Internal(internal)) => match internal {
+ InternalAddress::Masp => (None, 0u8),
+ _ => {
+ return Err(Error::from(TxError::InvalidAccount(
+ owner.encode(),
+ )));
+ }
+ },
None => (None, 0u8),
};
@@ -786,9 +791,9 @@ pub async fn make_ledger_masp_endpoints<'a>(
builder: Option<&MaspBuilder>,
assets: &HashMap,
) {
- if transfer.source != masp() {
+ if transfer.source != MASP {
output.push(format!("Sender : {}", transfer.source));
- if transfer.target == masp() {
+ if transfer.target == MASP {
make_ledger_amount_addr(
tokens,
output,
@@ -813,9 +818,9 @@ pub async fn make_ledger_masp_endpoints<'a>(
.await;
}
}
- if transfer.target != masp() {
+ if transfer.target != MASP {
output.push(format!("Destination : {}", transfer.target));
- if transfer.source == masp() {
+ if transfer.source == MASP {
make_ledger_amount_addr(
tokens,
output,
@@ -840,7 +845,7 @@ pub async fn make_ledger_masp_endpoints<'a>(
.await;
}
}
- if transfer.source != masp() && transfer.target != masp() {
+ if transfer.source != MASP && transfer.target != MASP {
make_ledger_amount_addr(
tokens,
output,
diff --git a/sdk/src/tx.rs b/sdk/src/tx.rs
index 2e1a786d12..1600f1e493 100644
--- a/sdk/src/tx.rs
+++ b/sdk/src/tx.rs
@@ -31,7 +31,7 @@ use namada_core::ledger::governance::storage::proposal::ProposalType;
use namada_core::ledger::governance::storage::vote::StorageProposalVote;
use namada_core::ledger::ibc::storage::channel_key;
use namada_core::ledger::pgf::cli::steward::Commission;
-use namada_core::types::address::{masp, Address, InternalAddress};
+use namada_core::types::address::{Address, InternalAddress, MASP};
use namada_core::types::dec::Dec;
use namada_core::types::hash::Hash;
use namada_core::types::ibc::IbcShieldedTransfer;
@@ -2212,7 +2212,7 @@ pub async fn build_transfer<'a, N: Namada<'a>>(
token: args.token.clone(),
});
- let masp_addr = masp();
+ let masp_addr = MASP;
// For MASP sources, use a special sentinel key recognized by VPs as default
// signer. Also, if the transaction is shielded, redact the amount and token
@@ -2556,7 +2556,7 @@ pub async fn gen_ibc_shielded_transfer<'a, N: Namada<'a>>(
let transfer = token::Transfer {
source: source.clone(),
- target: masp(),
+ target: MASP,
token: token.clone(),
amount: validated_amount,
key,
diff --git a/shared/src/ledger/native_vp/ibc/context.rs b/shared/src/ledger/native_vp/ibc/context.rs
index defdd1a177..ffe2faa2f5 100644
--- a/shared/src/ledger/native_vp/ibc/context.rs
+++ b/shared/src/ledger/native_vp/ibc/context.rs
@@ -11,7 +11,7 @@ use crate::ledger::native_vp::CtxPreStorageRead;
use crate::ledger::storage::write_log::StorageModification;
use crate::ledger::storage::{self as ledger_storage, StorageHasher};
use crate::ledger::storage_api::{self, StorageRead, StorageWrite};
-use crate::types::address::{self, Address, InternalAddress};
+use crate::types::address::{Address, InternalAddress, MASP};
use crate::types::ibc::{IbcEvent, IbcShieldedTransfer};
use crate::types::storage::{
BlockHash, BlockHeight, Epoch, Header, Key, KeySeg, TxIndex,
@@ -216,7 +216,7 @@ where
}
fn handle_masp_tx(&mut self, shielded: &IbcShieldedTransfer) -> Result<()> {
- let masp_addr = address::masp();
+ let masp_addr = MASP;
let head_tx_key = Key::from(masp_addr.to_db_key())
.push(&HEAD_TX_KEY.to_owned())
.expect("Cannot obtain a storage key");
diff --git a/shared/src/ledger/native_vp/masp.rs b/shared/src/ledger/native_vp/masp.rs
new file mode 100644
index 0000000000..54048f6759
--- /dev/null
+++ b/shared/src/ledger/native_vp/masp.rs
@@ -0,0 +1,300 @@
+//! MASP native VP
+
+use std::cmp::Ordering;
+use std::collections::BTreeSet;
+
+use borsh_ext::BorshSerializeExt;
+use masp_primitives::asset_type::AssetType;
+use masp_primitives::transaction::components::I128Sum;
+use namada_core::ledger::gas::MASP_VERIFY_SHIELDED_TX_GAS;
+use namada_core::ledger::storage;
+use namada_core::ledger::storage_api::OptionExt;
+use namada_core::ledger::vp_env::VpEnv;
+use namada_core::proto::Tx;
+use namada_core::types::address::Address;
+use namada_core::types::address::InternalAddress::Masp;
+use namada_core::types::storage::{Epoch, Key};
+use namada_core::types::token;
+use namada_sdk::masp::verify_shielded_tx;
+use ripemd::Digest as RipemdDigest;
+use sha2::Digest as Sha2Digest;
+use thiserror::Error;
+
+use crate::ledger::native_vp;
+use crate::ledger::native_vp::{Ctx, NativeVp};
+use crate::vm::WasmCacheAccess;
+
+#[allow(missing_docs)]
+#[derive(Error, Debug)]
+pub enum Error {
+ #[error("Native VP error: {0}")]
+ NativeVpError(native_vp::Error),
+}
+
+/// MASP VP result
+pub type Result = std::result::Result;
+
+/// MASP VP
+pub struct MaspVp<'a, DB, H, CA>
+where
+ DB: storage::DB + for<'iter> storage::DBIter<'iter>,
+ H: storage::StorageHasher,
+ CA: WasmCacheAccess,
+{
+ /// Context to interact with the host structures.
+ pub ctx: Ctx<'a, DB, H, CA>,
+}
+
+/// Generates the current asset type given the current epoch and an
+/// unique token address
+fn asset_type_from_epoched_address(
+ epoch: Epoch,
+ token: &Address,
+ denom: token::MaspDenom,
+) -> AssetType {
+ // Timestamp the chosen token with the current epoch
+ let token_bytes = (token, denom, epoch.0).serialize_to_vec();
+ // Generate the unique asset identifier from the unique token address
+ AssetType::new(token_bytes.as_ref()).expect("unable to create asset type")
+}
+
+/// Checks if the asset type matches the expected asset type, Adds a
+/// debug log if the values do not match.
+fn valid_asset_type(
+ asset_type: &AssetType,
+ asset_type_to_test: &AssetType,
+) -> bool {
+ let res =
+ asset_type.get_identifier() == asset_type_to_test.get_identifier();
+ if !res {
+ tracing::debug!(
+ "The asset type must be derived from the token address and \
+ current epoch"
+ );
+ }
+ res
+}
+
+/// Checks if the reported transparent amount and the unshielded
+/// values agree, if not adds to the debug log
+fn valid_transfer_amount(
+ reporeted_transparent_value: u64,
+ unshielded_transfer_value: u64,
+) -> bool {
+ let res = reporeted_transparent_value == unshielded_transfer_value;
+ if !res {
+ tracing::debug!(
+ "The unshielded amount {} disagrees with the calculated masp \
+ transparented value {}",
+ unshielded_transfer_value,
+ reporeted_transparent_value
+ );
+ }
+ res
+}
+
+/// Convert Namada amount and token type to MASP equivalents
+fn convert_amount(
+ epoch: Epoch,
+ token: &Address,
+ val: token::Amount,
+ denom: token::MaspDenom,
+) -> (AssetType, I128Sum) {
+ let asset_type = asset_type_from_epoched_address(epoch, token, denom);
+ // Combine the value and unit into one amount
+ let amount =
+ I128Sum::from_nonnegative(asset_type, denom.denominate(&val) as i128)
+ .expect("invalid value or asset type for amount");
+ (asset_type, amount)
+}
+
+impl<'a, DB, H, CA> NativeVp for MaspVp<'a, DB, H, CA>
+where
+ DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
+ H: 'static + storage::StorageHasher,
+ CA: 'static + WasmCacheAccess,
+{
+ type Error = Error;
+
+ fn validate_tx(
+ &self,
+ tx_data: &Tx,
+ _keys_changed: &BTreeSet,
+ _verifiers: &BTreeSet,
+ ) -> Result {
+ let epoch = self.ctx.get_block_epoch()?;
+ let (transfer, shielded_tx) = self.ctx.get_shielded_action(tx_data)?;
+ let mut transparent_tx_pool = I128Sum::zero();
+ // The Sapling value balance adds to the transparent tx pool
+ transparent_tx_pool += shielded_tx.sapling_value_balance();
+
+ if transfer.source != Address::Internal(Masp) {
+ // Handle transparent input
+ // Note that the asset type is timestamped so shields
+ // where the shielded value has an incorrect timestamp
+ // are automatically rejected
+ for denom in token::MaspDenom::iter() {
+ let (_transp_asset, transp_amt) = convert_amount(
+ epoch,
+ &transfer.token,
+ transfer.amount.into(),
+ denom,
+ );
+
+ // Non-masp sources add to transparent tx pool
+ transparent_tx_pool += transp_amt;
+ }
+ } else {
+ // Handle shielded input
+ // The following boundary conditions must be satisfied
+ // 1. Zero transparent input
+ // 2. the transparent transaction value pool's amount must equal
+ // the containing wrapper transaction's fee
+ // amount Satisfies 1.
+ if let Some(transp_bundle) = shielded_tx.transparent_bundle() {
+ if !transp_bundle.vin.is_empty() {
+ tracing::debug!(
+ "Transparent input to a transaction from the masp \
+ must be 0 but is {}",
+ transp_bundle.vin.len()
+ );
+ return Ok(false);
+ }
+ }
+ }
+
+ if transfer.target != Address::Internal(Masp) {
+ // Handle transparent output
+ // The following boundary conditions must be satisfied
+ // 1. One to 4 transparent outputs
+ // 2. Asset type must be properly derived
+ // 3. Value from the output must be the same as the containing
+ // transfer
+ // 4. Public key must be the hash of the target
+
+ // Satisfies 1.
+ let transp_bundle =
+ shielded_tx.transparent_bundle().ok_or_err_msg(
+ "Expected transparent outputs in unshielding transaction",
+ )?;
+
+ let out_length = transp_bundle.vout.len();
+ if !(1..=4).contains(&out_length) {
+ tracing::debug!(
+ "Transparent output to a transaction to the masp must be \
+ beteween 1 and 4 but is {}",
+ transp_bundle.vout.len()
+ );
+
+ return Ok(false);
+ }
+ let mut outs = transp_bundle.vout.iter();
+ let mut valid_count = 0;
+ for denom in token::MaspDenom::iter() {
+ let out = match outs.next() {
+ Some(out) => out,
+ None => continue,
+ };
+
+ let expected_asset_type: AssetType =
+ asset_type_from_epoched_address(
+ epoch,
+ &transfer.token,
+ denom,
+ );
+
+ // Satisfies 2. and 3.
+ if !valid_asset_type(&expected_asset_type, &out.asset_type) {
+ // we don't know which masp denoms are necessary
+ // apriori. This is encoded via
+ // the asset types.
+ continue;
+ }
+ if !valid_transfer_amount(
+ out.value,
+ denom.denominate(&transfer.amount.amount),
+ ) {
+ return Ok(false);
+ }
+
+ let (_transp_asset, transp_amt) = convert_amount(
+ epoch,
+ &transfer.token,
+ transfer.amount.amount,
+ denom,
+ );
+
+ // Non-masp destinations subtract from transparent tx pool
+ transparent_tx_pool -= transp_amt;
+
+ // Satisfies 4.
+ let target_enc = transfer.target.serialize_to_vec();
+
+ let hash = ripemd::Ripemd160::digest(sha2::Sha256::digest(
+ &target_enc,
+ ));
+
+ if <[u8; 20]>::from(hash) != out.address.0 {
+ tracing::debug!(
+ "the public key of the output account does not match \
+ the transfer target"
+ );
+ return Ok(false);
+ }
+ valid_count += 1;
+ }
+ // one or more of the denoms in the batch failed to verify
+ // the asset derivation.
+ if valid_count != out_length {
+ return Ok(false);
+ }
+ } else {
+ // Handle shielded output
+ // The following boundary conditions must be satisfied
+ // 1. Zero transparent output
+
+ // Satisfies 1.
+ if let Some(transp_bundle) = shielded_tx.transparent_bundle() {
+ if !transp_bundle.vout.is_empty() {
+ tracing::debug!(
+ "Transparent output to a transaction from the masp \
+ must be 0 but is {}",
+ transp_bundle.vout.len()
+ );
+ return Ok(false);
+ }
+ }
+ }
+
+ match transparent_tx_pool.partial_cmp(&I128Sum::zero()) {
+ None | Some(Ordering::Less) => {
+ tracing::debug!(
+ "Transparent transaction value pool must be nonnegative. \
+ Violation may be caused by transaction being constructed \
+ in previous epoch. Maybe try again."
+ );
+ // Section 3.4: The remaining value in the transparent
+ // transaction value pool MUST be nonnegative.
+ return Ok(false);
+ }
+ Some(Ordering::Greater) => {
+ tracing::debug!(
+ "Transaction fees cannot be paid inside MASP transaction."
+ );
+ return Ok(false);
+ }
+ _ => {}
+ }
+ // Verify the proofs and charge the gas for the expensive execution
+ self.ctx
+ .charge_gas(MASP_VERIFY_SHIELDED_TX_GAS)
+ .map_err(Error::NativeVpError)?;
+ Ok(verify_shielded_tx(&shielded_tx))
+ }
+}
+
+impl From for Error {
+ fn from(err: native_vp::Error) -> Self {
+ Self::NativeVpError(err)
+ }
+}
diff --git a/shared/src/ledger/native_vp/mod.rs b/shared/src/ledger/native_vp/mod.rs
index a590a1e433..a18d5f5404 100644
--- a/shared/src/ledger/native_vp/mod.rs
+++ b/shared/src/ledger/native_vp/mod.rs
@@ -3,6 +3,7 @@
pub mod ethereum_bridge;
pub mod ibc;
+pub mod masp;
pub mod multitoken;
pub mod parameters;
@@ -564,10 +565,6 @@ where
}
}
- fn verify_masp(&self, _tx: Vec) -> Result {
- unimplemented!("no masp native vp")
- }
-
fn charge_gas(&self, used_gas: u64) -> Result<(), storage_api::Error> {
self.gas_meter.borrow_mut().consume(used_gas).map_err(|_| {
Error::SimpleMessage("Gas limit exceeded in native vp")
diff --git a/shared/src/ledger/protocol/mod.rs b/shared/src/ledger/protocol/mod.rs
index d142781127..64021faf6b 100644
--- a/shared/src/ledger/protocol/mod.rs
+++ b/shared/src/ledger/protocol/mod.rs
@@ -22,6 +22,7 @@ use crate::ledger::native_vp::ethereum_bridge::bridge_pool_vp::BridgePoolVp;
use crate::ledger::native_vp::ethereum_bridge::nut::NonUsableTokens;
use crate::ledger::native_vp::ethereum_bridge::vp::EthBridge;
use crate::ledger::native_vp::ibc::Ibc;
+use crate::ledger::native_vp::masp::MaspVp;
use crate::ledger::native_vp::multitoken::MultitokenVp;
use crate::ledger::native_vp::parameters::{self, ParametersVp};
use crate::ledger::native_vp::{self, NativeVp};
@@ -90,6 +91,8 @@ pub enum Error {
BridgePoolNativeVpError(native_vp::ethereum_bridge::bridge_pool_vp::Error),
#[error("Non usable tokens native VP error: {0}")]
NutNativeVpError(native_vp::ethereum_bridge::nut::Error),
+ #[error("MASP native VP error: {0}")]
+ MaspNativeVpError(native_vp::masp::Error),
#[error("Access to an internal address {0} is forbidden")]
AccessForbidden(InternalAddress),
}
@@ -1005,6 +1008,16 @@ where
ctx.sentinel.into_inner(),
)
}
+ InternalAddress::Masp => {
+ let masp = MaspVp { ctx };
+ let result = masp
+ .validate_tx(tx, &keys_changed, &verifiers)
+ .map_err(Error::MaspNativeVpError);
+ // Take the gas meter and the sentinel back out
+ // of the context
+ gas_meter = masp.ctx.gas_meter.into_inner();
+ (result, masp.ctx.sentinel.into_inner())
+ }
};
accepted.map_err(|err| {
diff --git a/shared/src/vm/host_env.rs b/shared/src/vm/host_env.rs
index 2ea0037f9a..9dd19c1d74 100644
--- a/shared/src/vm/host_env.rs
+++ b/shared/src/vm/host_env.rs
@@ -10,7 +10,7 @@ use masp_primitives::transaction::Transaction;
use namada_core::ledger::gas::{
GasMetering, TxGasMeter, MEMORY_ACCESS_GAS_PER_BYTE,
};
-use namada_core::types::address::ESTABLISHED_ADDRESS_BYTES_LEN;
+use namada_core::types::address::{ESTABLISHED_ADDRESS_BYTES_LEN, MASP};
use namada_core::types::internal::KeyVal;
use namada_core::types::storage::TX_INDEX_LENGTH;
use namada_core::types::transaction::TxSentinel;
@@ -1945,40 +1945,6 @@ where
}
}
-/// Verify a ShieldedTransaction.
-pub fn vp_verify_masp(
- env: &VpVmEnv,
- tx_ptr: u64,
- tx_len: u64,
-) -> vp_host_fns::EnvResult
-where
- MEM: VmMemory,
- DB: storage::DB + for<'iter> storage::DBIter<'iter>,
- H: StorageHasher,
- EVAL: VpEvaluator,
- CA: WasmCacheAccess,
-{
- let gas_meter = unsafe { env.ctx.gas_meter.get() };
- let sentinel = unsafe { env.ctx.sentinel.get() };
- let (tx_bytes, gas) = env
- .memory
- .read_bytes(tx_ptr, tx_len as _)
- .map_err(|e| vp_host_fns::RuntimeError::MemoryError(Box::new(e)))?;
- vp_host_fns::add_gas(gas_meter, gas, sentinel)?;
-
- let shielded: Transaction =
- BorshDeserialize::try_from_slice(tx_bytes.as_slice())
- .map_err(vp_host_fns::RuntimeError::EncodingError)?;
-
- Ok(
- // TODO: once the runtime gas meter is implemented we need to benchmark
- // this funcion and charge the gas here. For the moment, the cost of
- // this is included in the benchmark of the masp vp
- HostEnvResult::from(namada_sdk::masp::verify_shielded_tx(&shielded))
- .to_i64(),
- )
-}
-
/// Log a string from exposed to the wasm VM Tx environment. The message will be
/// printed at the [`tracing::Level::INFO`]. This function is for development
/// only.
@@ -2431,7 +2397,7 @@ where
&mut self,
shielded: &IbcShieldedTransfer,
) -> Result<(), storage_api::Error> {
- let masp_addr = address::masp();
+ let masp_addr = MASP;
let head_tx_key = Key::from(masp_addr.to_db_key())
.push(&HEAD_TX_KEY.to_owned())
.expect("Cannot obtain a storage key");
diff --git a/shared/src/vm/wasm/host_env.rs b/shared/src/vm/wasm/host_env.rs
index a7dc51cc6f..fc5a5d5594 100644
--- a/shared/src/vm/wasm/host_env.rs
+++ b/shared/src/vm/wasm/host_env.rs
@@ -130,7 +130,6 @@ where
"namada_vp_get_block_epoch" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_block_epoch),
"namada_vp_get_ibc_events" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_ibc_events),
"namada_vp_verify_tx_section_signature" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_verify_tx_section_signature),
- "namada_vp_verify_masp" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_verify_masp),
"namada_vp_eval" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_eval),
"namada_vp_get_native_token" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_native_token),
"namada_vp_log_string" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_log_string),
diff --git a/test_fixtures/masp_proofs/0044C26D5E4F29FA81F3970709A98182D17943D69AB701C24FA90E1EFC1876F0.bin b/test_fixtures/masp_proofs/0044C26D5E4F29FA81F3970709A98182D17943D69AB701C24FA90E1EFC1876F0.bin
new file mode 100644
index 0000000000..4eecf0358b
Binary files /dev/null and b/test_fixtures/masp_proofs/0044C26D5E4F29FA81F3970709A98182D17943D69AB701C24FA90E1EFC1876F0.bin differ
diff --git a/test_fixtures/masp_proofs/0198EA2E90E59AE189F8E4D2148EFC768FE777B9F1B84CA71D843A0062EB1509.bin b/test_fixtures/masp_proofs/0198EA2E90E59AE189F8E4D2148EFC768FE777B9F1B84CA71D843A0062EB1509.bin
deleted file mode 100644
index 91158992f1..0000000000
Binary files a/test_fixtures/masp_proofs/0198EA2E90E59AE189F8E4D2148EFC768FE777B9F1B84CA71D843A0062EB1509.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/0754547040784C17718C4F689F4C5AEBFA800AD1ABEF2487C53BF97362CC90B0.bin b/test_fixtures/masp_proofs/0754547040784C17718C4F689F4C5AEBFA800AD1ABEF2487C53BF97362CC90B0.bin
new file mode 100644
index 0000000000..3331bfe608
Binary files /dev/null and b/test_fixtures/masp_proofs/0754547040784C17718C4F689F4C5AEBFA800AD1ABEF2487C53BF97362CC90B0.bin differ
diff --git a/test_fixtures/masp_proofs/0BB61ED029B895FEEB7681A39C6EDC5CC89E90D6FF92E31C8C872DCAB358239A.bin b/test_fixtures/masp_proofs/0BB61ED029B895FEEB7681A39C6EDC5CC89E90D6FF92E31C8C872DCAB358239A.bin
deleted file mode 100644
index e5e6e93ec1..0000000000
Binary files a/test_fixtures/masp_proofs/0BB61ED029B895FEEB7681A39C6EDC5CC89E90D6FF92E31C8C872DCAB358239A.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/125E61BD706AB533F815E6E2869A7952F44DD3927485DEC3F649AEA68C3374C8.bin b/test_fixtures/masp_proofs/125E61BD706AB533F815E6E2869A7952F44DD3927485DEC3F649AEA68C3374C8.bin
new file mode 100644
index 0000000000..dfd5a43f15
Binary files /dev/null and b/test_fixtures/masp_proofs/125E61BD706AB533F815E6E2869A7952F44DD3927485DEC3F649AEA68C3374C8.bin differ
diff --git a/test_fixtures/masp_proofs/256ED96C075E42B8FEA99ABECA59DB09065F2CC91CBB86AD65A92E8B92B43743.bin b/test_fixtures/masp_proofs/256ED96C075E42B8FEA99ABECA59DB09065F2CC91CBB86AD65A92E8B92B43743.bin
new file mode 100644
index 0000000000..8cb606ab8d
Binary files /dev/null and b/test_fixtures/masp_proofs/256ED96C075E42B8FEA99ABECA59DB09065F2CC91CBB86AD65A92E8B92B43743.bin differ
diff --git a/test_fixtures/masp_proofs/30F09813D596F8277911C99FF1C6B362D244EDD624244876F9B5F541EBA07FC5.bin b/test_fixtures/masp_proofs/30F09813D596F8277911C99FF1C6B362D244EDD624244876F9B5F541EBA07FC5.bin
deleted file mode 100644
index 1329396ab9..0000000000
Binary files a/test_fixtures/masp_proofs/30F09813D596F8277911C99FF1C6B362D244EDD624244876F9B5F541EBA07FC5.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/315FBEBD16884E62FCFB437CEA4D13376048954D074973BAD19846CC5570D984.bin b/test_fixtures/masp_proofs/315FBEBD16884E62FCFB437CEA4D13376048954D074973BAD19846CC5570D984.bin
deleted file mode 100644
index 3e42d029c4..0000000000
Binary files a/test_fixtures/masp_proofs/315FBEBD16884E62FCFB437CEA4D13376048954D074973BAD19846CC5570D984.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/50A4057E7DCFD57E26F23DFBF861DE6890ADDBC8CFB85C76A4E7885280D684F4.bin b/test_fixtures/masp_proofs/50A4057E7DCFD57E26F23DFBF861DE6890ADDBC8CFB85C76A4E7885280D684F4.bin
new file mode 100644
index 0000000000..ed9a42045d
Binary files /dev/null and b/test_fixtures/masp_proofs/50A4057E7DCFD57E26F23DFBF861DE6890ADDBC8CFB85C76A4E7885280D684F4.bin differ
diff --git a/test_fixtures/masp_proofs/50C53F3CA843689FC9C1C3233686DF79F7E021A374BFCF3C6CA82DAC391C6533.bin b/test_fixtures/masp_proofs/50C53F3CA843689FC9C1C3233686DF79F7E021A374BFCF3C6CA82DAC391C6533.bin
deleted file mode 100644
index 5d71d8783a..0000000000
Binary files a/test_fixtures/masp_proofs/50C53F3CA843689FC9C1C3233686DF79F7E021A374BFCF3C6CA82DAC391C6533.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/520C3ACC87D01E58CF1E907FA00A87507CCAA8EB7647CB2974EB9250922A0580.bin b/test_fixtures/masp_proofs/520C3ACC87D01E58CF1E907FA00A87507CCAA8EB7647CB2974EB9250922A0580.bin
new file mode 100644
index 0000000000..0bc5155fb5
Binary files /dev/null and b/test_fixtures/masp_proofs/520C3ACC87D01E58CF1E907FA00A87507CCAA8EB7647CB2974EB9250922A0580.bin differ
diff --git a/test_fixtures/masp_proofs/5219A58EE0E0BE74F6AFE1184C0CFF18DB68FAB6D994F680AAEA7EF99DF3C872.bin b/test_fixtures/masp_proofs/5219A58EE0E0BE74F6AFE1184C0CFF18DB68FAB6D994F680AAEA7EF99DF3C872.bin
new file mode 100644
index 0000000000..b4f5db3059
Binary files /dev/null and b/test_fixtures/masp_proofs/5219A58EE0E0BE74F6AFE1184C0CFF18DB68FAB6D994F680AAEA7EF99DF3C872.bin differ
diff --git a/test_fixtures/masp_proofs/4CCF96B9008D42BA633988264D3E116D3BC8B780C76EAEC072E1A71D709AE66F.bin b/test_fixtures/masp_proofs/59BBC98F00DE442A5EC9E1CE884333592C4A00DDC30896E174422F6863F71D32.bin
similarity index 53%
rename from test_fixtures/masp_proofs/4CCF96B9008D42BA633988264D3E116D3BC8B780C76EAEC072E1A71D709AE66F.bin
rename to test_fixtures/masp_proofs/59BBC98F00DE442A5EC9E1CE884333592C4A00DDC30896E174422F6863F71D32.bin
index 3887ce9a44..0dcda6bda3 100644
Binary files a/test_fixtures/masp_proofs/4CCF96B9008D42BA633988264D3E116D3BC8B780C76EAEC072E1A71D709AE66F.bin and b/test_fixtures/masp_proofs/59BBC98F00DE442A5EC9E1CE884333592C4A00DDC30896E174422F6863F71D32.bin differ
diff --git a/test_fixtures/masp_proofs/5AF17E0AB182339D31853B3A1FC35062071533243874C260C81A6AEBE8480987.bin b/test_fixtures/masp_proofs/5AF17E0AB182339D31853B3A1FC35062071533243874C260C81A6AEBE8480987.bin
new file mode 100644
index 0000000000..16c730b09c
Binary files /dev/null and b/test_fixtures/masp_proofs/5AF17E0AB182339D31853B3A1FC35062071533243874C260C81A6AEBE8480987.bin differ
diff --git a/test_fixtures/masp_proofs/7FEE0379CDF35F061B75B7B2145E4DB0A1861A41897246DE5EA7C6FD27651C8E.bin b/test_fixtures/masp_proofs/7FEE0379CDF35F061B75B7B2145E4DB0A1861A41897246DE5EA7C6FD27651C8E.bin
new file mode 100644
index 0000000000..6516676ff6
Binary files /dev/null and b/test_fixtures/masp_proofs/7FEE0379CDF35F061B75B7B2145E4DB0A1861A41897246DE5EA7C6FD27651C8E.bin differ
diff --git a/test_fixtures/masp_proofs/819FB7D977389C0AC073BE200FCE87F8358272338A32B5B411E93BD43D963AE0.bin b/test_fixtures/masp_proofs/819FB7D977389C0AC073BE200FCE87F8358272338A32B5B411E93BD43D963AE0.bin
deleted file mode 100644
index f537b76d38..0000000000
Binary files a/test_fixtures/masp_proofs/819FB7D977389C0AC073BE200FCE87F8358272338A32B5B411E93BD43D963AE0.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/8686859C447B47946DC21922D83C2404E7EBDFF543A6EAA34544FFF644F08FA9.bin b/test_fixtures/masp_proofs/8686859C447B47946DC21922D83C2404E7EBDFF543A6EAA34544FFF644F08FA9.bin
deleted file mode 100644
index a6d6153a3a..0000000000
Binary files a/test_fixtures/masp_proofs/8686859C447B47946DC21922D83C2404E7EBDFF543A6EAA34544FFF644F08FA9.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/931AE522191249FAFA4A38C9740412000E423E0085AB074BF8C493574AF3226B.bin b/test_fixtures/masp_proofs/931AE522191249FAFA4A38C9740412000E423E0085AB074BF8C493574AF3226B.bin
deleted file mode 100644
index 4e66ffffab..0000000000
Binary files a/test_fixtures/masp_proofs/931AE522191249FAFA4A38C9740412000E423E0085AB074BF8C493574AF3226B.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/9EF9FF93C65A60615530272351A86DBF2921ACB1380E8F256AD0CE25151C869C.bin b/test_fixtures/masp_proofs/9EF9FF93C65A60615530272351A86DBF2921ACB1380E8F256AD0CE25151C869C.bin
deleted file mode 100644
index b232255a68..0000000000
Binary files a/test_fixtures/masp_proofs/9EF9FF93C65A60615530272351A86DBF2921ACB1380E8F256AD0CE25151C869C.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/A28F93297BBBBD119DE0A2B2044027765771A646BC53E4AF92CA7A643EED36FC.bin b/test_fixtures/masp_proofs/A28F93297BBBBD119DE0A2B2044027765771A646BC53E4AF92CA7A643EED36FC.bin
new file mode 100644
index 0000000000..8466cb8841
Binary files /dev/null and b/test_fixtures/masp_proofs/A28F93297BBBBD119DE0A2B2044027765771A646BC53E4AF92CA7A643EED36FC.bin differ
diff --git a/test_fixtures/masp_proofs/C37373E2478B837D2468FBEE5CCA5D2C40DFF157E5FB70DDC84202C160D01CD3.bin b/test_fixtures/masp_proofs/C37373E2478B837D2468FBEE5CCA5D2C40DFF157E5FB70DDC84202C160D01CD3.bin
deleted file mode 100644
index 944c1a805c..0000000000
Binary files a/test_fixtures/masp_proofs/C37373E2478B837D2468FBEE5CCA5D2C40DFF157E5FB70DDC84202C160D01CD3.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/DB978B3F08838665C1ECD7BEA4E600461287D8046692CDB4AA2CF94A1AC7F8F6.bin b/test_fixtures/masp_proofs/DB978B3F08838665C1ECD7BEA4E600461287D8046692CDB4AA2CF94A1AC7F8F6.bin
deleted file mode 100644
index 8c5888b087..0000000000
Binary files a/test_fixtures/masp_proofs/DB978B3F08838665C1ECD7BEA4E600461287D8046692CDB4AA2CF94A1AC7F8F6.bin and /dev/null differ
diff --git a/test_fixtures/masp_proofs/3EE70DC758071936C6AADB82E56C536AAC74604CB002CA3558559CACCC24B5EB.bin b/test_fixtures/masp_proofs/EBE3E35A8D4CBD2FC7A12736DB5399B77FF4B05B8C78BF1F016C6101367F0639.bin
similarity index 55%
rename from test_fixtures/masp_proofs/3EE70DC758071936C6AADB82E56C536AAC74604CB002CA3558559CACCC24B5EB.bin
rename to test_fixtures/masp_proofs/EBE3E35A8D4CBD2FC7A12736DB5399B77FF4B05B8C78BF1F016C6101367F0639.bin
index 92f501db51..6192916b9f 100644
Binary files a/test_fixtures/masp_proofs/3EE70DC758071936C6AADB82E56C536AAC74604CB002CA3558559CACCC24B5EB.bin and b/test_fixtures/masp_proofs/EBE3E35A8D4CBD2FC7A12736DB5399B77FF4B05B8C78BF1F016C6101367F0639.bin differ
diff --git a/test_fixtures/masp_proofs/FBCAABF07FCA704A568838EAE2DA0C2C77847B19AE5C80C957F73BD81AD4C78D.bin b/test_fixtures/masp_proofs/FBCAABF07FCA704A568838EAE2DA0C2C77847B19AE5C80C957F73BD81AD4C78D.bin
new file mode 100644
index 0000000000..691f353b5c
Binary files /dev/null and b/test_fixtures/masp_proofs/FBCAABF07FCA704A568838EAE2DA0C2C77847B19AE5C80C957F73BD81AD4C78D.bin differ
diff --git a/tests/src/e2e/setup.rs b/tests/src/e2e/setup.rs
index cda8422001..644110bba6 100644
--- a/tests/src/e2e/setup.rs
+++ b/tests/src/e2e/setup.rs
@@ -1092,7 +1092,6 @@ pub mod constants {
pub const DAEWON_KEY: &str = "Daewon-key";
pub const ESTER: &str = "Ester";
pub const MATCHMAKER_KEY: &str = "matchmaker-key";
- pub const MASP: &str = "tnam1q9lm5pvkxhnw9wwwhu33vkvtylwfkn5kw53xwud8";
// Shielded spending and viewing keys and payment addresses
pub const A_SPENDING_KEY: &str = "zsknam1qqqqqqqqqqqqqq9v0sls5r5de7njx8ehu49pqgmqr9ygelg87l5x8y4s9r0pjlvu69au6gn3su5ewneas486hdccyayx32hxvt64p3d0hfuprpgcgv2q9gdx3jvxrn02f0nnp3jtdd6f5vwscfuyum083cvfv4jun75ak5sdgrm2pthzj3sflxc0jx0edrakx3vdcngrfjmru8ywkguru8mxss2uuqxdlglaz6undx5h8w7g70t2es850g48xzdkqay5qs0yw06rtxc9q0cqr";
@@ -1115,6 +1114,7 @@ pub mod constants {
// Native VP aliases
pub const GOVERNANCE_ADDRESS: &str = "governance";
+ pub const MASP: &str = "masp";
// Fungible token addresses
pub const NAM: &str = "NAM";
diff --git a/tx_prelude/src/token.rs b/tx_prelude/src/token.rs
index 6067c82a46..009cccb36d 100644
--- a/tx_prelude/src/token.rs
+++ b/tx_prelude/src/token.rs
@@ -1,5 +1,5 @@
use masp_primitives::transaction::Transaction;
-use namada_core::types::address::Address;
+use namada_core::types::address::{Address, MASP};
use namada_core::types::storage::KeySeg;
use namada_core::types::token;
pub use namada_core::types::token::*;
@@ -38,7 +38,7 @@ pub fn handle_masp_tx(
transfer: &Transfer,
shielded: &Transaction,
) -> TxResult {
- let masp_addr = address::masp();
+ let masp_addr = MASP;
ctx.insert_verifier(&masp_addr)?;
let head_tx_key = storage::Key::from(masp_addr.to_db_key())
.push(&HEAD_TX_KEY.to_owned())
diff --git a/vm_env/src/lib.rs b/vm_env/src/lib.rs
index c3497c5c27..87331ee5ba 100644
--- a/vm_env/src/lib.rs
+++ b/vm_env/src/lib.rs
@@ -229,8 +229,6 @@ pub mod vp {
input_data_len: u64,
) -> i64;
- pub fn namada_vp_verify_masp(tx_ptr: u64, tx_len: u64) -> i64;
-
/// Charge the provided amount of gas for the current vp
pub fn namada_vp_charge_gas(used_gas: u64);
}
diff --git a/vp_prelude/src/lib.rs b/vp_prelude/src/lib.rs
index 3c2d4f7b88..abd034236a 100644
--- a/vp_prelude/src/lib.rs
+++ b/vp_prelude/src/lib.rs
@@ -352,12 +352,6 @@ impl<'view> VpEnv<'view> for Ctx {
})
}
- fn verify_masp(&self, tx: Vec) -> Result {
- let valid =
- unsafe { namada_vp_verify_masp(tx.as_ptr() as _, tx.len() as _) };
- Ok(HostEnvResult::is_success(valid))
- }
-
fn charge_gas(&self, used_gas: u64) -> Result<(), Error> {
unsafe { namada_vp_charge_gas(used_gas) };
Ok(())
diff --git a/wasm/wasm_source/Cargo.toml b/wasm/wasm_source/Cargo.toml
index 8daba98389..e3293b5523 100644
--- a/wasm/wasm_source/Cargo.toml
+++ b/wasm/wasm_source/Cargo.toml
@@ -35,7 +35,6 @@ tx_withdraw = ["namada_tx_prelude"]
tx_update_steward_commission = ["namada_tx_prelude"]
tx_resign_steward = ["namada_tx_prelude"]
vp_implicit = ["namada_vp_prelude", "once_cell"]
-vp_masp = ["namada_vp_prelude", "masp_primitives"]
vp_token = ["namada_vp_prelude"]
vp_user = ["namada_vp_prelude", "once_cell"]
vp_validator = ["namada_vp_prelude", "once_cell"]
diff --git a/wasm/wasm_source/Makefile b/wasm/wasm_source/Makefile
index ca60559ccc..aa19173bd1 100644
--- a/wasm/wasm_source/Makefile
+++ b/wasm/wasm_source/Makefile
@@ -27,7 +27,6 @@ wasms += tx_withdraw
wasms += tx_update_steward_commission
wasms += tx_resign_steward
wasms += vp_implicit
-wasms += vp_masp
wasms += vp_user
wasms += vp_validator
diff --git a/wasm/wasm_source/src/lib.rs b/wasm/wasm_source/src/lib.rs
index c633505e67..15d365484a 100644
--- a/wasm/wasm_source/src/lib.rs
+++ b/wasm/wasm_source/src/lib.rs
@@ -43,8 +43,6 @@ pub mod tx_withdraw;
#[cfg(feature = "vp_implicit")]
pub mod vp_implicit;
-#[cfg(feature = "vp_masp")]
-pub mod vp_masp;
#[cfg(feature = "vp_user")]
pub mod vp_user;
#[cfg(feature = "vp_validator")]
diff --git a/wasm/wasm_source/src/vp_masp.rs b/wasm/wasm_source/src/vp_masp.rs
deleted file mode 100644
index c04ba1b844..0000000000
--- a/wasm/wasm_source/src/vp_masp.rs
+++ /dev/null
@@ -1,252 +0,0 @@
-use std::cmp::Ordering;
-
-use masp_primitives::asset_type::AssetType;
-use masp_primitives::transaction::components::I128Sum;
-/// Multi-asset shielded pool VP.
-use namada_vp_prelude::address::masp;
-use namada_vp_prelude::borsh_ext::BorshSerializeExt;
-use namada_vp_prelude::storage::Epoch;
-use namada_vp_prelude::*;
-use ripemd::{Digest, Ripemd160};
-
-/// Generates the current asset type given the current epoch and an
-/// unique token address
-fn asset_type_from_epoched_address(
- epoch: Epoch,
- token: &Address,
- denom: token::MaspDenom,
-) -> AssetType {
- // Timestamp the chosen token with the current epoch
- let token_bytes = (token, denom, epoch.0).serialize_to_vec();
- // Generate the unique asset identifier from the unique token address
- AssetType::new(token_bytes.as_ref()).expect("unable to create asset type")
-}
-
-/// Checks if the asset type matches the expected asset type, Adds a
-/// debug log if the values do not match.
-fn valid_asset_type(
- asset_type: &AssetType,
- asset_type_to_test: &AssetType,
-) -> bool {
- let res =
- asset_type.get_identifier() == asset_type_to_test.get_identifier();
- if !res {
- debug_log!(
- "The asset type must be derived from the token address and \
- current epoch"
- );
- }
- res
-}
-
-/// Checks if the reported transparent amount and the unshielded
-/// values agree, if not adds to the debug log
-fn valid_transfer_amount(
- reporeted_transparent_value: u64,
- unshielded_transfer_value: u64,
-) -> bool {
- let res = reporeted_transparent_value == unshielded_transfer_value;
- if !res {
- debug_log!(
- "The unshielded amount {} disagrees with the calculated masp \
- transparented value {}",
- unshielded_transfer_value,
- reporeted_transparent_value
- );
- }
- res
-}
-
-/// Convert Namada amount and token type to MASP equivalents
-fn convert_amount(
- epoch: Epoch,
- token: &Address,
- val: token::Amount,
- denom: token::MaspDenom,
-) -> (AssetType, I128Sum) {
- let asset_type = asset_type_from_epoched_address(epoch, token, denom);
- // Combine the value and unit into one amount
- let amount =
- I128Sum::from_nonnegative(asset_type, denom.denominate(&val) as i128)
- .expect("invalid value or asset type for amount");
- (asset_type, amount)
-}
-
-#[validity_predicate(gas = 62210635)]
-fn validate_tx(
- ctx: &Ctx,
- tx_data: Tx,
- addr: Address,
- keys_changed: BTreeSet,
- verifiers: BTreeSet,
-) -> VpResult {
- debug_log!(
- "vp_masp called with {} bytes data, address {}, keys_changed {:?}, \
- verifiers {:?}",
- tx_data.data().as_ref().map(|x| x.len()).unwrap_or(0),
- addr,
- keys_changed,
- verifiers,
- );
-
- let (transfer, shielded_tx) = ctx.get_shielded_action(tx_data)?;
- let mut transparent_tx_pool = I128Sum::zero();
- // The Sapling value balance adds to the transparent tx pool
- transparent_tx_pool += shielded_tx.sapling_value_balance();
-
- if transfer.source != masp() {
- // Handle transparent input
- // Note that the asset type is timestamped so shields
- // where the shielded value has an incorrect timestamp
- // are automatically rejected
- for denom in token::MaspDenom::iter() {
- let (_transp_asset, transp_amt) = convert_amount(
- ctx.get_block_epoch().unwrap(),
- &transfer.token,
- transfer.amount.into(),
- denom,
- );
-
- // Non-masp sources add to transparent tx pool
- transparent_tx_pool += transp_amt;
- }
- } else {
- // Handle shielded input
- // The following boundary conditions must be satisfied
- // 1. Zero transparent input
- // 2. the transparent transaction value pool's amount must equal the
- // containing wrapper transaction's fee amount
- // Satisfies 1.
- if let Some(transp_bundle) = shielded_tx.transparent_bundle() {
- if !transp_bundle.vin.is_empty() {
- debug_log!(
- "Transparent input to a transaction from the masp must be \
- 0 but is {}",
- transp_bundle.vin.len()
- );
- return reject();
- }
- }
- }
-
- if transfer.target != masp() {
- // Handle transparent output
- // The following boundary conditions must be satisfied
- // 1. One to 4 transparent outputs
- // 2. Asset type must be properly derived
- // 3. Value from the output must be the same as the containing
- // transfer
- // 4. Public key must be the hash of the target
-
- // Satisfies 1.
- let transp_bundle = shielded_tx.transparent_bundle().ok_or_err_msg(
- "Expected transparent outputs in unshielding transaction",
- )?;
-
- let out_length = transp_bundle.vout.len();
- if !(1..=4).contains(&out_length) {
- debug_log!(
- "Transparent output to a transaction to the masp must be \
- beteween 1 and 4 but is {}",
- transp_bundle.vout.len()
- );
-
- return reject();
- }
- let mut outs = transp_bundle.vout.iter();
- let mut valid_count = 0;
- for denom in token::MaspDenom::iter() {
- let out = match outs.next() {
- Some(out) => out,
- None => continue,
- };
-
- let expected_asset_type: AssetType =
- asset_type_from_epoched_address(
- ctx.get_block_epoch().unwrap(),
- &transfer.token,
- denom,
- );
-
- // Satisfies 2. and 3.
- if !valid_asset_type(&expected_asset_type, &out.asset_type) {
- // we don't know which masp denoms are necessary apriori.
- // This is encoded via the asset types.
- continue;
- }
- if !valid_transfer_amount(
- out.value,
- denom.denominate(&transfer.amount.amount),
- ) {
- return reject();
- }
-
- let (_transp_asset, transp_amt) = convert_amount(
- ctx.get_block_epoch().unwrap(),
- &transfer.token,
- transfer.amount.amount,
- denom,
- );
-
- // Non-masp destinations subtract from transparent tx pool
- transparent_tx_pool -= transp_amt;
-
- // Satisfies 4.
- let target_enc = transfer.target.serialize_to_vec();
-
- let hash = Ripemd160::digest(sha256(&target_enc).0.as_slice());
-
- if <[u8; 20]>::from(hash) != out.address.0 {
- debug_log!(
- "the public key of the output account does not match the \
- transfer target"
- );
- return reject();
- }
- valid_count += 1;
- }
- // one or more of the denoms in the batch failed to verify
- // the asset derivation.
- if valid_count != out_length {
- return reject();
- }
- } else {
- // Handle shielded output
- // The following boundary conditions must be satisfied
- // 1. Zero transparent output
-
- // Satisfies 1.
- if let Some(transp_bundle) = shielded_tx.transparent_bundle() {
- if !transp_bundle.vout.is_empty() {
- debug_log!(
- "Transparent output to a transaction from the masp must \
- be 0 but is {}",
- transp_bundle.vout.len()
- );
- return reject();
- }
- }
- }
-
- match transparent_tx_pool.partial_cmp(&I128Sum::zero()) {
- None | Some(Ordering::Less) => {
- debug_log!(
- "Transparent transaction value pool must be nonnegative. \
- Violation may be caused by transaction being constructed in \
- previous epoch. Maybe try again."
- );
- // Section 3.4: The remaining value in the transparent
- // transaction value pool MUST be nonnegative.
- return reject();
- }
- Some(Ordering::Greater) => {
- debug_log!(
- "Transaction fees cannot be paid inside MASP transaction."
- );
- return reject();
- }
- _ => {}
- }
- // Do the expensive proof verification in the VM at the end.
- ctx.verify_masp(shielded_tx.serialize_to_vec())
-}
diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs
index 6e81bcdac1..7799a30ad8 100644
--- a/wasm/wasm_source/src/vp_user.rs
+++ b/wasm/wasm_source/src/vp_user.rs
@@ -8,7 +8,6 @@
//!
//! Any other storage key changes are allowed only with a valid signature.
-use namada_vp_prelude::address::masp;
use namada_vp_prelude::storage::KeySeg;
use namada_vp_prelude::*;
use once_cell::unsync::Lazy;
@@ -82,8 +81,7 @@ fn validate_tx(
ctx.read_post(key)?.unwrap_or_default();
let change = post.change() - pre.change();
// debit has to signed, credit doesn't
- let valid =
- change.non_negative() || addr == masp() || *valid_sig;
+ let valid = change.non_negative() || *valid_sig;
debug_log!(
"token key: {}, change: {:?}, valid_sig: {}, valid \
modification: {}",