diff --git a/Cargo.lock b/Cargo.lock index 7cef4c57..84b5e1d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1854,9 +1854,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.20" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] diff --git a/lee/state_machine/src/lib.rs b/lee/state_machine/src/lib.rs index 0bd2c901..f8cc034a 100644 --- a/lee/state_machine/src/lib.rs +++ b/lee/state_machine/src/lib.rs @@ -30,8 +30,6 @@ pub mod program_deployment_transaction; pub mod public_transaction; mod signature; mod state; -#[cfg(feature = "test-utils")] -pub mod test_utils; mod validated_state_diff; mod privacy_preserving_circuit { diff --git a/lee/state_machine/src/test_utils.rs b/lee/state_machine/src/test_utils.rs deleted file mode 100644 index f9325ddd..00000000 --- a/lee/state_machine/src/test_utils.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! Test-only constructors for otherwise-opaque state types. -//! -//! A [`ValidatedStateDiff`] can normally only be produced by the transaction validation -//! functions, which guarantees it has been checked before any state mutation. These -//! helpers let downstream crates unit-test *post-execution* validation logic — e.g. the -//! system-account and bridge guards in `common` — against a hand-built diff, without -//! running a program in the zkVM. - -use std::collections::HashMap; - -use crate::{ - Account, AccountId, - validated_state_diff::{StateDiff, ValidatedStateDiff}, -}; - -/// Builds a [`ValidatedStateDiff`] carrying only the given public-account changes. -#[must_use] -pub const fn validated_state_diff_from_public_diff( - public_diff: HashMap, -) -> ValidatedStateDiff { - ValidatedStateDiff::new_unchecked(StateDiff { - signer_account_ids: Vec::new(), - public_diff, - new_commitments: Vec::new(), - new_nullifiers: Vec::new(), - program: None, - }) -} diff --git a/lee/state_machine/src/validated_state_diff.rs b/lee/state_machine/src/validated_state_diff.rs index 4b754dd9..44a307af 100644 --- a/lee/state_machine/src/validated_state_diff.rs +++ b/lee/state_machine/src/validated_state_diff.rs @@ -35,24 +35,10 @@ pub struct StateDiff { /// The validated output of executing or verifying a transaction, ready to be applied to the state. /// -/// It can only be constructed by the transaction validation functions inside this crate, ensuring -/// the diff has been checked before any state mutation occurs. Under the `test-utils` feature the -/// [`crate::test_utils`] module additionally exposes a hand-rolled constructor for unit-testing -/// downstream validation logic; that feature must never be enabled in a production build. +/// Can only be constructed by the transaction validation functions inside this crate, ensuring the +/// diff has been checked before any state mutation occurs. pub struct ValidatedStateDiff(StateDiff); -#[cfg(feature = "test-utils")] -impl ValidatedStateDiff { - /// Test-only constructor that wraps an already-built [`StateDiff`] **without validating it**. - /// - /// Kept in this module so the wrapped field can stay private: in a normal build (feature off) - /// the only ways to obtain a `ValidatedStateDiff` remain the `from_*_transaction` validators. - #[must_use] - pub const fn new_unchecked(state_diff: StateDiff) -> Self { - Self(state_diff) - } -} - impl ValidatedStateDiff { pub fn from_public_transaction( tx: &PublicTransaction, diff --git a/lez/common/Cargo.toml b/lez/common/Cargo.toml index 7582e885..8b2aa322 100644 --- a/lez/common/Cargo.toml +++ b/lez/common/Cargo.toml @@ -25,6 +25,3 @@ log.workspace = true hex.workspace = true borsh.workspace = true logos-blockchain-common-http-client.workspace = true - -[dev-dependencies] -lee = { workspace = true, features = ["test-utils"] } diff --git a/lez/common/src/test_utils.rs b/lez/common/src/test_utils.rs index 4a9ab992..7afda3dd 100644 --- a/lez/common/src/test_utils.rs +++ b/lez/common/src/test_utils.rs @@ -1,12 +1,4 @@ -// Backs the hand-built state/diff helpers below, which are compiled only for `common`'s own -// unit tests. They rely on `lee::test_utils`, gated behind `lee`'s `test-utils` feature and -// enabled here via dev-dependencies, so it never reaches a production build. -#[cfg(test)] -use std::collections::HashMap; - use lee::AccountId; -#[cfg(test)] -use lee::{Account, PrivateKey, PublicKey, V03State, ValidatedStateDiff}; use crate::{ HashType, @@ -21,33 +13,6 @@ pub fn sequencer_sign_key_for_testing() -> lee::PrivateKey { lee::PrivateKey::try_new([37; 32]).unwrap() } -/// A syntactically valid `Public` transaction. Its contents are irrelevant to the -/// bridge guard, which only branches on the transaction *variant* and the diff. -#[cfg(test)] -#[must_use] -pub fn any_public_transaction() -> LeeTransaction { - let sender_key = PrivateKey::try_new([9_u8; 32]).expect("valid key"); - let sender_id = AccountId::from(&PublicKey::new_from_private_key(&sender_key)); - let recipient_key = PrivateKey::try_new([8_u8; 32]).expect("valid key"); - let recipient_id = AccountId::from(&PublicKey::new_from_private_key(&recipient_key)); - create_transaction_native_token_transfer(sender_id, 0, recipient_id, 1, &sender_key) -} - -/// Builds a state whose only entry is `account_id` (set to `pre`) and a single-entry diff -/// that maps `account_id` to `post`, so the validation guards can be exercised in isolation. -#[cfg(test)] -#[must_use] -pub fn state_and_diff( - account_id: AccountId, - pre: Account, - post: Account, -) -> (V03State, ValidatedStateDiff) { - let state = V03State::new().with_public_accounts([(account_id, pre)]); - let diff = - lee::test_utils::validated_state_diff_from_public_diff(HashMap::from([(account_id, post)])); - (state, diff) -} - // Dummy producers /// Produce dummy block with provided transactions + clock transaction an the end. diff --git a/lez/common/src/transaction.rs b/lez/common/src/transaction.rs index 64725738..b5aee648 100644 --- a/lez/common/src/transaction.rs +++ b/lez/common/src/transaction.rs @@ -260,112 +260,9 @@ fn validate_doesnt_modify_account( #[cfg(test)] mod tests { - use lee::{Account, AccountId, PrivateKey, PublicKey, V03State}; - use lee_core::account::Nonce; + use lee::{AccountId, PrivateKey, PublicKey, V03State}; - use super::validate_doesnt_modify_account; - use crate::test_utils::{ - any_public_transaction, create_transaction_native_token_transfer, state_and_diff, - }; - - #[test] - fn bridge_guard_allows_balance_only_increase() { - // A diff that *only* increases the bridge balance (the legitimate deposit shape) - // must be accepted. - let bridge_id = system_accounts::bridge_account_id(); - let pre = Account { - balance: 500, - nonce: Nonce(7), - ..Account::default() - }; - let post = Account { - balance: 600, - ..pre.clone() - }; - let (state, diff) = state_and_diff(bridge_id, pre, post); - - let tx = any_public_transaction(); - assert!( - tx.validate_bridge_account_modification(&state, &diff) - .is_ok(), - "a balance-only increase of the bridge account must be allowed", - ); - } - - #[test] - fn bridge_guard_rejects_data_modification_even_when_balance_increases() { - // A diff that changes the bridge account's data (here: the nonce) while *also* - // increasing its balance must be rejected. - let bridge_id = system_accounts::bridge_account_id(); - let pre = Account { - balance: 500, - nonce: Nonce(7), - ..Account::default() - }; - let post = Account { - balance: 600, - nonce: Nonce(8), - ..pre.clone() - }; - let (state, diff) = state_and_diff(bridge_id, pre, post); - - let tx = any_public_transaction(); - assert!( - tx.validate_bridge_account_modification(&state, &diff) - .is_err(), - "modifying bridge account data must be rejected even if the balance increases", - ); - } - - #[test] - fn bridge_guard_rejects_zero_value_deposit() { - // A diff that touches the bridge account without *strictly* increasing its balance - // must be rejected — a zero-value deposit is not a real credit. - let bridge_id = system_accounts::bridge_account_id(); - let pre = Account { - balance: 500, - nonce: Nonce(7), - ..Account::default() - }; - let post = pre.clone(); - let (state, diff) = state_and_diff(bridge_id, pre, post); - - let tx = any_public_transaction(); - assert!( - tx.validate_bridge_account_modification(&state, &diff) - .is_err(), - "a bridge diff that does not strictly increase the balance must be rejected", - ); - } - - #[test] - fn validate_doesnt_modify_account_flags_a_changed_account() { - // Directly exercise the system-account guard with a diff that genuinely changes a - // clock account, then with one that leaves it untouched. The inverted comparison would - // treat a changed account as unchanged and wave it through (and would flag an *unchanged* - // account instead). - let clock_id = system_accounts::clock_account_ids()[0]; - let pre = Account { - balance: 1_000, - ..Account::default() - }; - - let changed = Account { - balance: 2_000, - ..Account::default() - }; - let (state, diff) = state_and_diff(clock_id, pre.clone(), changed); - assert!( - validate_doesnt_modify_account(&state, &diff, clock_id).is_err(), - "a diff that changes a system account must be rejected", - ); - - let (unchanged_state, unchanged_diff) = state_and_diff(clock_id, pre.clone(), pre); - assert!( - validate_doesnt_modify_account(&unchanged_state, &unchanged_diff, clock_id).is_ok(), - "a diff that leaves a system account unchanged must be accepted", - ); - } + use crate::test_utils::create_transaction_native_token_transfer; #[test] fn system_account_ids_are_distinct_and_non_default() {