Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove masp vp dependency on Transfer #3232

Merged
merged 13 commits into from
May 31, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Removed any dependency on the specific transaction data from the masp vp.
([\#3232](https://github.com/anoma/namada/pull/3232))
19 changes: 19 additions & 0 deletions crates/core/src/masp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};

use crate::address::{Address, DecodeError, HASH_HEX_LEN, MASP};
use crate::hash::Hash;
use crate::impl_display_and_from_str_via_format;
use crate::storage::Epoch;
use crate::string_encoding::{
Expand Down Expand Up @@ -532,3 +533,21 @@ impl FromStr for MaspValue {
})
}
}

/// The masp transactions' references of a given batch
#[derive(Default, Clone, Serialize, Deserialize)]
pub struct MaspTxRefs(pub Vec<Hash>);

impl Display for MaspTxRefs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", serde_json::to_string(self).unwrap())
}
}

impl FromStr for MaspTxRefs {
type Err = serde_json::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
24 changes: 5 additions & 19 deletions crates/events/src/extend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::str::FromStr;

use namada_core::collections::HashMap;
use namada_core::hash::Hash;
use namada_core::masp::MaspTxRefs;
use namada_core::storage::{BlockHeight, TxIndex};

use super::*;
Expand Down Expand Up @@ -498,28 +499,13 @@ impl EventAttributeEntry<'static> for MaspTxBlockIndex {
}
}

/// A displyable collection of hashes.
#[derive(Serialize, Deserialize)]
pub struct DisplayableHashVec(Vec<Hash>);

impl Display for DisplayableHashVec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", serde_json::to_string(self).unwrap())
}
}

impl From<Vec<Hash>> for DisplayableHashVec {
fn from(value: Vec<Hash>) -> Self {
Self(value)
}
}

/// Extend an [`Event`] with `masp_tx_batch_refs` data, indicating the specific
/// inner transactions inside the batch that are valid masp txs.
pub struct MaspTxBatchRefs(pub DisplayableHashVec);
/// inner transactions inside the batch that are valid masp txs and the
/// references to the relative masp sections.
pub struct MaspTxBatchRefs(pub MaspTxRefs);

impl EventAttributeEntry<'static> for MaspTxBatchRefs {
type Value = DisplayableHashVec;
type Value = MaspTxRefs;
type ValueOwned = Self::Value;

const KEY: &'static str = "masp_tx_batch_refs";
Expand Down
20 changes: 19 additions & 1 deletion crates/namada/src/ledger/native_vp/masp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,25 @@ where
) -> Result<()> {
let epoch = self.ctx.get_block_epoch()?;
let conversion_state = self.ctx.state.in_mem().get_conversion_state();
let shielded_tx = self.ctx.get_shielded_action(tx_data)?;

// Get the Transaction object from the actions
let masp_section_ref = namada_tx::action::get_masp_section_ref(
&self.ctx,
)?
.ok_or_else(|| {
native_vp::Error::new_const(
"Missing MASP section reference in action",
)
})?;
let shielded_tx = tx_data
.tx
.get_section(&masp_section_ref)
.and_then(|section| section.masp_tx())
.ok_or_else(|| {
native_vp::Error::new_const(
"Missing MASP section in transaction",
)
})?;

if u64::from(self.ctx.get_block_height()?)
> u64::from(shielded_tx.expiry_height())
Expand Down
164 changes: 103 additions & 61 deletions crates/namada/src/ledger/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use namada_state::StorageWrite;
use namada_token::event::{TokenEvent, TokenOperation, UserAccount};
use namada_tx::data::protocol::ProtocolTxType;
use namada_tx::data::{
BatchResults, BatchedTxResult, TxResult, TxType, VpStatusFlags, VpsResult,
WrapperTx,
BatchResults, BatchedTxResult, ExtendedTxResult, TxResult, TxType,
VpStatusFlags, VpsResult, WrapperTx,
};
use namada_tx::{BatchedTxRef, Tx};
use namada_vote_ext::EthereumTxData;
Expand Down Expand Up @@ -63,8 +63,6 @@ pub enum Error {
TxRunnerError(vm::wasm::run::Error),
#[error("{0:?}")]
ProtocolTxError(#[from] eyre::Error),
#[error("Txs must either be encrypted or a decryption of an encrypted tx")]
TxTypeError,
#[error("The atomic batch failed at inner transaction {0}")]
FailingAtomicBatch(Hash),
#[error("Gas error: {0}")]
Expand Down Expand Up @@ -165,8 +163,9 @@ pub type Result<T> = std::result::Result<T, Error>;
pub struct DispatchError {
/// The result of the function call
pub error: Error,
/// The tx result produced. It could produced even in case of an error
pub tx_result: Option<TxResult<Error>>,
/// The extended tx result produced. It could be produced even in case of
/// an error
pub tx_result: Option<ExtendedTxResult<Error>>,
}

impl From<Error> for DispatchError {
Expand All @@ -191,7 +190,7 @@ pub fn dispatch_tx<'a, D, H, CA>(
vp_wasm_cache: &'a mut VpCache<CA>,
tx_wasm_cache: &'a mut TxCache<CA>,
block_proposer: Option<&Address>,
) -> std::result::Result<TxResult<Error>, DispatchError>
) -> std::result::Result<ExtendedTxResult<Error>, DispatchError>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
H: 'static + StorageHasher + Sync,
Expand Down Expand Up @@ -220,7 +219,8 @@ where
.into_iter()
.collect(),
),
})
}
.to_extended_result(None))
}
TxType::Protocol(protocol_tx) => {
// No bundles of protocol transactions, only take the first one
Expand All @@ -235,10 +235,11 @@ where
.collect(),
),
..Default::default()
})
}
.to_extended_result(None))
}
TxType::Wrapper(ref wrapper) => {
let mut tx_result = apply_wrapper_tx(
let tx_result = apply_wrapper_tx(
tx.clone(),
wrapper,
tx_bytes,
Expand All @@ -263,62 +264,103 @@ where
});
}

// TODO(namada#2597): handle masp fee payment in the first inner tx
// if necessary
for cmt in tx.commitments() {
match apply_wasm_tx(
tx.batch_ref_tx(cmt),
&tx_index,
ShellParams {
tx_gas_meter,
state,
vp_wasm_cache,
tx_wasm_cache,
},
) {
Err(Error::GasError(ref msg)) => {
// Gas error aborts the execution of the entire batch
tx_result.gas_used =
tx_gas_meter.borrow().get_tx_consumed_gas();
tx_result.batch_results.0.insert(
cmt.get_hash(),
Err(Error::GasError(msg.to_owned())),
);
state.write_log_mut().drop_tx();
dispatch_inner_txs(
tx,
tx_result,
tx_index,
tx_gas_meter,
state,
vp_wasm_cache,
tx_wasm_cache,
)
}
}
}

fn dispatch_inner_txs<'a, D, H, CA>(
tx: Tx,
tx_result: TxResult<Error>,
tx_index: TxIndex,
tx_gas_meter: &'a RefCell<TxGasMeter>,
state: &'a mut WlState<D, H>,
vp_wasm_cache: &'a mut VpCache<CA>,
tx_wasm_cache: &'a mut TxCache<CA>,
) -> std::result::Result<ExtendedTxResult<Error>, DispatchError>
where
D: 'static + DB + for<'iter> DBIter<'iter> + Sync,
H: 'static + StorageHasher + Sync,
CA: 'static + WasmCacheAccess + Sync,
{
let mut extended_tx_result = tx_result.to_extended_result(None);

// TODO(namada#2597): handle masp fee payment in the first inner tx
// if necessary
for cmt in tx.commitments() {
match apply_wasm_tx(
tx.batch_ref_tx(cmt),
&tx_index,
ShellParams {
tx_gas_meter,
state,
vp_wasm_cache,
tx_wasm_cache,
},
) {
Err(Error::GasError(ref msg)) => {
// Gas error aborts the execution of the entire batch
extended_tx_result.tx_result.gas_used =
tx_gas_meter.borrow().get_tx_consumed_gas();
extended_tx_result.tx_result.batch_results.0.insert(
cmt.get_hash(),
Err(Error::GasError(msg.to_owned())),
);
state.write_log_mut().drop_tx();
return Err(DispatchError {
error: Error::GasError(msg.to_owned()),
tx_result: Some(extended_tx_result),
});
}
res => {
let is_accepted =
matches!(&res, Ok(result) if result.is_accepted());

extended_tx_result
.tx_result
.batch_results
.0
.insert(cmt.get_hash(), res);
extended_tx_result.tx_result.gas_used =
tx_gas_meter.borrow().get_tx_consumed_gas();
if is_accepted {
// If the transaction was a masp one append the
// transaction refs for the events
if let Some(masp_section_ref) =
namada_tx::action::get_masp_section_ref(state)
.map_err(Error::StateError)?
{
extended_tx_result
.masp_tx_refs
.0
.push(masp_section_ref);
}
state.write_log_mut().commit_tx_to_batch();
} else {
state.write_log_mut().drop_tx();

if tx.header.atomic {
// Stop the execution of an atomic batch at the
// first failed transaction
return Err(DispatchError {
error: Error::GasError(msg.to_owned()),
tx_result: Some(tx_result),
error: Error::FailingAtomicBatch(cmt.get_hash()),
tx_result: Some(extended_tx_result),
});
}
res => {
let is_accepted =
matches!(&res, Ok(result) if result.is_accepted());

tx_result.batch_results.0.insert(cmt.get_hash(), res);
tx_result.gas_used =
tx_gas_meter.borrow().get_tx_consumed_gas();
if is_accepted {
state.write_log_mut().commit_tx_to_batch();
} else {
state.write_log_mut().drop_tx();

if tx.header.atomic {
// Stop the execution of an atomic batch at the
// first failed transaction
return Err(DispatchError {
error: Error::FailingAtomicBatch(
cmt.get_hash(),
),
tx_result: Some(tx_result),
});
}
}
}
};
}
}
Ok(tx_result)
}
};
}

Ok(extended_tx_result)
}

/// Load the wasm hash for a transfer from storage.
Expand Down
19 changes: 13 additions & 6 deletions crates/node/src/bench_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ use namada::ledger::native_vp::ibc::get_dummy_header;
use namada::ledger::queries::{
Client, EncodedResponseQuery, RequestCtx, RequestQuery, Router, RPC,
};
use namada::masp::MaspTxRefs;
use namada::state::StorageRead;
use namada::tx::data::pos::Bond;
use namada::tx::data::{
Expand Down Expand Up @@ -922,12 +923,18 @@ impl Client for BenchShell {
.with(MaspTxBlockIndex(TxIndex::must_from_usize(
idx,
)))
.with(MaspTxBatchRefs(
vec![
tx.first_commitments().unwrap().get_hash(),
]
.into(),
))
.with(MaspTxBatchRefs(MaspTxRefs(vec![
tx.sections
.iter()
.find_map(|section| {
if let Section::MaspTx(_) = section {
Some(section.get_hash())
} else {
None
}
})
.unwrap(),
])))
.into();
namada::tendermint::abci::Event::from(event)
})
Expand Down
Loading
Loading