mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-08-01 12:33:24 +00:00
Revert "Merge pull request #609 from logos-blockchain/test-address-missed-mutants"
This reverts commit 415964d7f9043a1bfe28da8d0e8b3a6f64abb258, reversing changes made to d1637b65e2479e80bb617b900ec5d4024216457d.
This commit is contained in:
parent
415964d7f9
commit
e4112fc416
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -1854,9 +1854,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-epoch"
|
name = "crossbeam-epoch"
|
||||||
version = "0.9.20"
|
version = "0.9.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -30,8 +30,6 @@ pub mod program_deployment_transaction;
|
|||||||
pub mod public_transaction;
|
pub mod public_transaction;
|
||||||
mod signature;
|
mod signature;
|
||||||
mod state;
|
mod state;
|
||||||
#[cfg(feature = "test-utils")]
|
|
||||||
pub mod test_utils;
|
|
||||||
mod validated_state_diff;
|
mod validated_state_diff;
|
||||||
|
|
||||||
mod privacy_preserving_circuit {
|
mod privacy_preserving_circuit {
|
||||||
|
|||||||
@ -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<AccountId, Account>,
|
|
||||||
) -> ValidatedStateDiff {
|
|
||||||
ValidatedStateDiff::new_unchecked(StateDiff {
|
|
||||||
signer_account_ids: Vec::new(),
|
|
||||||
public_diff,
|
|
||||||
new_commitments: Vec::new(),
|
|
||||||
new_nullifiers: Vec::new(),
|
|
||||||
program: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -35,24 +35,10 @@ pub struct StateDiff {
|
|||||||
|
|
||||||
/// The validated output of executing or verifying a transaction, ready to be applied to the state.
|
/// 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
|
/// Can only be constructed by the transaction validation functions inside this crate, ensuring the
|
||||||
/// the diff has been checked before any state mutation occurs. Under the `test-utils` feature the
|
/// diff has been checked before any state mutation occurs.
|
||||||
/// [`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.
|
|
||||||
pub struct ValidatedStateDiff(StateDiff);
|
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 {
|
impl ValidatedStateDiff {
|
||||||
pub fn from_public_transaction(
|
pub fn from_public_transaction(
|
||||||
tx: &PublicTransaction,
|
tx: &PublicTransaction,
|
||||||
|
|||||||
@ -25,6 +25,3 @@ log.workspace = true
|
|||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
borsh.workspace = true
|
borsh.workspace = true
|
||||||
logos-blockchain-common-http-client.workspace = true
|
logos-blockchain-common-http-client.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
lee = { workspace = true, features = ["test-utils"] }
|
|
||||||
|
|||||||
@ -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;
|
use lee::AccountId;
|
||||||
#[cfg(test)]
|
|
||||||
use lee::{Account, PrivateKey, PublicKey, V03State, ValidatedStateDiff};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
HashType,
|
HashType,
|
||||||
@ -21,33 +13,6 @@ pub fn sequencer_sign_key_for_testing() -> lee::PrivateKey {
|
|||||||
lee::PrivateKey::try_new([37; 32]).unwrap()
|
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
|
// Dummy producers
|
||||||
|
|
||||||
/// Produce dummy block with provided transactions + clock transaction an the end.
|
/// Produce dummy block with provided transactions + clock transaction an the end.
|
||||||
|
|||||||
@ -260,112 +260,9 @@ fn validate_doesnt_modify_account(
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use lee::{Account, AccountId, PrivateKey, PublicKey, V03State};
|
use lee::{AccountId, PrivateKey, PublicKey, V03State};
|
||||||
use lee_core::account::Nonce;
|
|
||||||
|
|
||||||
use super::validate_doesnt_modify_account;
|
use crate::test_utils::create_transaction_native_token_transfer;
|
||||||
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",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn system_account_ids_are_distinct_and_non_default() {
|
fn system_account_ids_are_distinct_and_non_default() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user