From a5d1e91810b25a72b3a9dd6cf03ae8beee195031 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 13 Feb 2024 13:03:38 +0100 Subject: [PATCH] Adds vp update wasm tests --- wasm/wasm_source/src/vp_user.rs | 128 +++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 4 deletions(-) diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs index 5267e7fef6..315b1cb922 100644 --- a/wasm/wasm_source/src/vp_user.rs +++ b/wasm/wasm_source/src/vp_user.rs @@ -339,11 +339,13 @@ fn validate_pos_changes( #[cfg(test)] mod tests { use address::testing::arb_non_internal_address; + use namada::governance; use namada::ledger::pos::{GenesisValidator, PosParams}; use namada::tx::data::{self, TxType}; use namada::tx::{Code, Data, Signature}; use namada::types::dec::Dec; use namada::types::storage::Epoch; + use namada_test_utils::TestWasms; // Use this as `#[test]` annotation to enable logging use namada_tests::log::test; use namada_tests::native_vp::pos::init_pos; @@ -1263,10 +1265,10 @@ mod tests { } } - /// Test that a validity predicate update without a valid signature is + /// Test that a threshold update without a valid signature is /// rejected. #[test] - fn test_unsigned_vp_update_rejected() { + fn test_unsigned_threshold_update_rejected() { // Initialize a tx environment let mut tx_env = TestTxEnv::default(); @@ -1296,10 +1298,10 @@ mod tests { ); } - /// Test that a validity predicate update with a valid signature is + /// Test that a threshold update with a valid signature is /// accepted. #[test] - fn test_signed_vp_update_accepted() { + fn test_signed_threshold_update_accepted() { // Initialize a tx environment let mut tx_env = TestTxEnv::default(); tx_env.init_parameters(None, None, None, None); @@ -1341,4 +1343,122 @@ mod tests { .unwrap() ); } + + /// Test that a validity predicate update is rejected even if the vp is + /// whitelisted and the tx is correctly signed + #[test] + fn test_vp_update_rejected() { + // Initialize a tx environment + let mut tx_env = TestTxEnv::default(); + + let vp_owner = address::testing::established_address_1(); + let keypair = key::testing::keypair_1(); + let public_key = keypair.ref_to(); + let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); + let vp_hash = sha256(&vp_code); + // for the update + tx_env.store_wasm_code(vp_code); + + tx_env.init_parameters( + None, + Some(vec![vp_hash.to_string()]), + None, + None, + ); + + // Spawn the accounts to be able to modify their storage + tx_env.spawn_accounts([&vp_owner]); + tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); + + // Initialize VP environment from a transaction + vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { + // Update VP in a transaction + let key = Key::validity_predicate(address); + tx::ctx().write(&key, vp_hash).unwrap(); + }); + + let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); + let mut vp_env = vp_host_env::take(); + let mut tx = vp_env.tx.clone(); + tx.set_data(Data::new(vec![])); + tx.set_code(Code::new(vec![], None)); + tx.add_section(Section::Signature(Signature::new( + vec![tx.raw_header_hash()], + pks_map.index_secret_keys(vec![keypair]), + None, + ))); + let signed_tx = tx.clone(); + vp_env.tx = signed_tx.clone(); + let keys_changed: BTreeSet = + vp_env.all_touched_storage_keys(); + let verifiers: BTreeSet
= BTreeSet::default(); + vp_host_env::set(vp_env); + assert!( + !validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) + .unwrap() + ); + } + + /// Test that a validity predicate update is accepted if it comes from a + /// governance proposal + #[test] + fn test_governance_vp_update_accepted() { + // Initialize a tx environment + let mut tx_env = TestTxEnv::default(); + + let vp_owner = address::testing::established_address_1(); + let keypair = key::testing::keypair_1(); + let public_key = keypair.ref_to(); + let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); + let vp_hash = sha256(&vp_code); + // for the update + tx_env.store_wasm_code(vp_code); + + tx_env.init_parameters( + None, + Some(vec![vp_hash.to_string()]), + None, + None, + ); + + // Spawn the accounts to be able to modify their storage + tx_env.spawn_accounts([&vp_owner]); + tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); + + // Mock governance proposal execution. Write the proposal id in the + // block write log before the execution of the tx + let proposal_execution_key = + governance::storage::keys::get_proposal_execution_key(1u64); + tx_env + .wl_storage + .write(&proposal_execution_key, ()) + .unwrap(); + // Initialize VP environment from a transaction + vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { + // Update VP in a transaction + let key = Key::validity_predicate(address); + tx::ctx().write(&key, vp_hash).unwrap(); + }); + + let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); + let mut vp_env = vp_host_env::take(); + let mut tx = vp_env.tx.clone(); + tx.set_data(Data::new(1u64.serialize_to_vec())); + tx.set_code(Code::new(vec![], None)); + tx.add_section(Section::Signature(Signature::new( + vec![tx.raw_header_hash()], + pks_map.index_secret_keys(vec![keypair]), + None, + ))); + let signed_tx = tx.clone(); + vp_env.tx = signed_tx.clone(); + let keys_changed: BTreeSet = + vp_env.all_touched_storage_keys(); + let verifiers: BTreeSet
= BTreeSet::default(); + vp_host_env::set(vp_env); + assert!( + validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) + .unwrap() + ); + } }