Skip to content

Commit

Permalink
eth/nut_vp: env agnostic VP
Browse files Browse the repository at this point in the history
  • Loading branch information
tzemanovic committed Sep 12, 2024
1 parent 1fd6410 commit c3fe124
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 77 deletions.
11 changes: 6 additions & 5 deletions crates/benches/native_vps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,7 @@ fn eth_bridge_nut(c: &mut Criterion) {
Address::Internal(InternalAddress::Nut(native_erc20_addres));
let gas_meter =
RefCell::new(VpGasMeter::new_from_tx_meter(&TxGasMeter::new(u64::MAX)));
let nut = EthBridgeNutVp::new(Ctx::new(
let ctx = Ctx::new(
&vp_address,
&shell.state,
&signed_tx.tx,
Expand All @@ -1332,15 +1332,16 @@ fn eth_bridge_nut(c: &mut Criterion) {
&keys_changed,
&verifiers,
shell.vp_wasm_cache.clone(),
));
);

c.bench_function("vp_eth_bridge_nut", |b| {
b.iter(|| {
assert!(
nut.validate_tx(
EthBridgeNutVp::validate_tx(
&ctx,
&signed_tx.to_ref(),
nut.ctx.keys_changed,
nut.ctx.verifiers,
ctx.keys_changed,
ctx.verifiers,
)
.is_ok()
)
Expand Down
91 changes: 30 additions & 61 deletions crates/ethereum_bridge/src/vp/nut_vp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,27 @@ use std::marker::PhantomData;
use namada_core::address::{Address, InternalAddress};
use namada_core::booleans::BoolResultUnitExt;
use namada_core::storage::Key;
use namada_state::StateRead;
use namada_systems::trans_token::{self as token, Amount};
use namada_tx::BatchedTxRef;
use namada_vp::native_vp::{self, Ctx, Error, NativeVp, Result, VpEvaluator};
use namada_vp::VpEnv;
use namada_vp_env::{Error, Result, VpEnv};

/// Validity predicate for non-usable tokens.
///
/// All this VP does is reject NUT transfers whose destination
/// address is not the Bridge pool escrow address.
pub struct NonUsableTokens<'ctx, S, CA, EVAL, TokenKeys>
where
S: 'static + StateRead,
{
/// Context to interact with the host structures.
pub ctx: Ctx<'ctx, S, CA, EVAL>,
pub struct NonUsableTokens<'ctx, CTX, TokenKeys> {
/// Generic types for DI
pub _marker: PhantomData<TokenKeys>,
pub _marker: PhantomData<(&'ctx CTX, TokenKeys)>,
}

impl<'view, 'ctx: 'view, S, CA, EVAL, TokenKeys> NativeVp<'view>
for NonUsableTokens<'ctx, S, CA, EVAL, TokenKeys>
impl<'ctx, CTX, TokenKeys> NonUsableTokens<'ctx, CTX, TokenKeys>
where
S: 'static + StateRead,
EVAL: 'static + VpEvaluator<'ctx, S, CA, EVAL>,
CA: 'static + Clone,
CTX: VpEnv<'ctx> + namada_tx::action::Read<Err = Error>,
TokenKeys: token::Keys,
{
fn validate_tx(
&'view self,
/// Run the validity predicate
pub fn validate_tx(
ctx: &'ctx CTX,
_: &BatchedTxRef<'_>,
keys_changed: &BTreeSet<Key>,
verifiers: &BTreeSet<Address>,
Expand Down Expand Up @@ -65,10 +56,8 @@ where
});

for (changed_key, token_owner) in nut_owners {
let pre: Amount =
self.ctx.read_pre(changed_key)?.unwrap_or_default();
let post: Amount =
self.ctx.read_post(changed_key)?.unwrap_or_default();
let pre: Amount = ctx.read_pre(changed_key)?.unwrap_or_default();
let post: Amount = ctx.read_post(changed_key)?.unwrap_or_default();

match token_owner {
// the NUT balance of the bridge pool should increase
Expand All @@ -80,7 +69,7 @@ where
post_amount = ?post,
"Bridge pool balance should have increased"
);
return Err(native_vp::Error::new_alloc(format!(
return Err(Error::new_alloc(format!(
"Bridge pool balance should have increased. The \
previous balance was {pre:?}, the post balance \
is {post:?}.",
Expand All @@ -96,7 +85,7 @@ where
post_amount = ?post,
"Balance should have decreased"
);
return Err(native_vp::Error::new_alloc(format!(
return Err(Error::new_alloc(format!(
"Balance should have decreased. The previous \
balance was {pre:?}, the post balance is \
{post:?}."
Expand All @@ -110,22 +99,6 @@ where
}
}

impl<'ctx, S, CA, EVAL, TokenKeys> NonUsableTokens<'ctx, S, CA, EVAL, TokenKeys>
where
S: 'static + StateRead,
EVAL: 'static + VpEvaluator<'ctx, S, CA, EVAL>,
CA: 'static + Clone,
TokenKeys: token::Keys,
{
/// Instantiate NUT VP
pub fn new(ctx: Ctx<'ctx, S, CA, EVAL>) -> Self {
Self {
ctx,
_marker: PhantomData,
}
}
}

#[cfg(test)]
mod test_nuts {
use std::cell::RefCell;
Expand All @@ -137,27 +110,25 @@ mod test_nuts {
use namada_core::storage::TxIndex;
use namada_gas::{TxGasMeter, VpGasMeter};
use namada_state::testing::TestState;
use namada_state::StorageWrite;
use namada_state::{StateRead, StorageWrite};
use namada_trans_token::storage_key::balance_key;
use namada_tx::data::TxType;
use namada_tx::Tx;
use namada_vm::wasm::run::VpEvalWasm;
use namada_vm::wasm::VpCache;
use namada_vm::WasmCacheRwAccess;
use namada_vp::native_vp;
use proptest::prelude::*;

use super::*;
use crate::storage::wrapped_erc20s;

type CA = WasmCacheRwAccess;
type Eval = VpEvalWasm<
<TestState as StateRead>::D,
<TestState as StateRead>::H,
CA,
>;
type Eval<S> = VpEvalWasm<<S as StateRead>::D, <S as StateRead>::H, CA>;
type Ctx<'ctx, S> = native_vp::Ctx<'ctx, S, VpCache<CA>, Eval<S>>;
type TokenKeys = namada_token::Store<()>;
type NonUsableTokens<'a, S> =
super::NonUsableTokens<'a, S, VpCache<CA>, Eval, TokenKeys>;
type NonUsableTokens<'ctx, S> =
super::NonUsableTokens<'ctx, Ctx<'ctx, S>, TokenKeys>;

/// Run a VP check on a NUT transfer between the two provided addresses.
fn check_nut_transfer(src: Address, dst: Address) -> bool {
Expand Down Expand Up @@ -215,7 +186,7 @@ mod test_nuts {
&TxGasMeter::new(u64::MAX),
));
let batched_tx = tx.batch_ref_first_tx().unwrap();
let ctx = Ctx::<_, VpCache<WasmCacheRwAccess>, Eval>::new(
let ctx = Ctx::new(
&Address::Internal(InternalAddress::Nut(DAI_ERC20_ETH_ADDRESS)),
&state,
batched_tx.tx,
Expand All @@ -226,25 +197,23 @@ mod test_nuts {
&verifiers,
VpCache::new(temp_dir(), 100usize),
);
let vp = NonUsableTokens::new(ctx);

// print debug info in case we run into failures
for key in &keys_changed {
let pre: Amount = vp
.ctx
.read_pre(key)
.expect("Test failed")
.unwrap_or_default();
let post: Amount = vp
.ctx
.read_post(key)
.expect("Test failed")
.unwrap_or_default();
let pre: Amount =
ctx.read_pre(key).expect("Test failed").unwrap_or_default();
let post: Amount =
ctx.read_post(key).expect("Test failed").unwrap_or_default();
println!("{key}: PRE={pre:?} POST={post:?}");
}

vp.validate_tx(&batched_tx, &keys_changed, &verifiers)
.map_or_else(|_| false, |()| true)
NonUsableTokens::validate_tx(
&ctx,
&batched_tx,
&keys_changed,
&verifiers,
)
.map_or_else(|_| false, |()| true)
}

proptest! {
Expand Down
16 changes: 7 additions & 9 deletions crates/node/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1305,15 +1305,13 @@ where
.map_err(Error::NativeVpError)
}
InternalAddress::Nut(_) => {
let non_usable_tokens =
EthBridgeNutVp::new(ctx);
non_usable_tokens
.validate_tx(
batched_tx,
&keys_changed,
&verifiers,
)
.map_err(Error::NativeVpError)
EthBridgeNutVp::validate_tx(
&ctx,
batched_tx,
&keys_changed,
&verifiers,
)
.map_err(Error::NativeVpError)
}
internal_addr @ (InternalAddress::IbcToken(_)
| InternalAddress::Erc20(_)) => {
Expand Down
4 changes: 2 additions & 2 deletions crates/sdk/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ pub type EthBridgePoolVp<'ctx, CTX> =
eth_bridge::vp::BridgePool<'ctx, CTX, TokenKeys>;

/// Native ETH bridge NUT VP
pub type EthBridgeNutVp<'a, S, CA> =
eth_bridge::vp::NonUsableTokens<'a, S, VpCache<CA>, Eval<S, CA>, TokenKeys>;
pub type EthBridgeNutVp<'ctx, CTX> =
eth_bridge::vp::NonUsableTokens<'ctx, CTX, TokenKeys>;

/// Governance store implementation over the native prior context
pub type GovPreStore<'a, S, CA> =
Expand Down

0 comments on commit c3fe124

Please sign in to comment.