chore: synchronize with latest lee introduction

This commit is contained in:
Roman 2026-06-05 11:12:26 +08:00
parent 2adc491361
commit ccd08aed6f
No known key found for this signature in database
GPG Key ID: 583BDF43C238B83E
16 changed files with 1329 additions and 504 deletions

836
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -52,11 +52,13 @@ unsafe_code = "deny"
[workspace.dependencies]
# ── LEZ crates — expects logos-execution-zone/ to be cloned at ../logos-execution-zone ──
nssa = { path = "../logos-execution-zone/nssa" }
nssa_core = { path = "../logos-execution-zone/nssa/core" }
common = { path = "../logos-execution-zone/common" }
key_protocol = { path = "../logos-execution-zone/key_protocol" }
testnet_initial_state = { path = "../logos-execution-zone/testnet_initial_state" }
# LEZ reorganised its directory layout; the package= key keeps the old dependency
# alias so that fuzz_props source code (use nssa::...) compiles unchanged.
nssa = { path = "../logos-execution-zone/lee/state_machine", package = "lee" }
nssa_core = { path = "../logos-execution-zone/lee/state_machine/core", package = "lee_core" }
common = { path = "../logos-execution-zone/lez/common" }
key_protocol = { path = "../logos-execution-zone/lee/key_protocol" }
testnet_initial_state = { path = "../logos-execution-zone/lez/testnet_initial_state" }
token_core = { path = "../logos-execution-zone/programs/token/core" }
test_program_methods = { path = "../logos-execution-zone/test_program_methods" }

View File

@ -788,10 +788,13 @@ mutants-protocol PACKAGES="nssa common":
# ── Housekeeping ──────────────────────────────────────────────────────────────
# Remove all Cargo build artefacts (workspace + fuzz sub-crate)
# Remove all Cargo build artefacts (workspace + fuzz sub-crate + logos-execution-zone)
# Each command is prefixed with `-` so that a missing sibling workspace (LEZ not cloned)
# does not abort the recipe — cargo clean still removes whatever targets are present.
clean:
cargo clean
cargo clean --manifest-path fuzz/Cargo.toml
-cargo clean
-cargo clean --manifest-path fuzz/Cargo.toml
-cargo clean --manifest-path ../logos-execution-zone/Cargo.toml
# Remove libFuzzer crash/timeout artifacts for all targets (corpus is kept)
clean-artifacts:

View File

@ -116,7 +116,7 @@ just fuzz-props
| Target | Protocol layer | Entry point |
|--------|---------------|-------------|
| `fuzz_transaction_decoding` | Borsh decoding of all tx/block types (`NSSATransaction`, `Block`, `HashableBlockData`) with roundtrip re-encoding | `fuzz/fuzz_targets/fuzz_transaction_decoding.rs` |
| `fuzz_transaction_decoding` | Borsh decoding of all tx/block types (`LeeTransaction`, `Block`, `HashableBlockData`) with roundtrip re-encoding | `fuzz/fuzz_targets/fuzz_transaction_decoding.rs` |
| `fuzz_stateless_verification` | `transaction_stateless_check()` no-panic + idempotency | `fuzz/fuzz_targets/fuzz_stateless_verification.rs` |
| `fuzz_state_transition` | `V03State` transition: StateIsolationOnFailure + BalanceConservation + ReplayRejection invariants across up to 8 txs with fuzz-driven state | `fuzz/fuzz_targets/fuzz_state_transition.rs` |
| `fuzz_block_verification` | Block hash integrity: HashRoundTrip · HashPreimage completeness (block_id/prev_hash/timestamp) · TxOrderCommitment | `fuzz/fuzz_targets/fuzz_block_verification.rs` |

View File

@ -103,7 +103,7 @@ just fuzz-regression
| Target | What it fuzzes | Entry point |
|--------|---------------|-------------|
| `fuzz_transaction_decoding` | Borsh decoding of `NSSATransaction`, `Block`, and `HashableBlockData`; roundtrip re-encoding of successfully decoded transactions | `fuzz/fuzz_targets/fuzz_transaction_decoding.rs` |
| `fuzz_transaction_decoding` | Borsh decoding of `LeeTransaction`, `Block`, and `HashableBlockData`; roundtrip re-encoding of successfully decoded transactions | `fuzz/fuzz_targets/fuzz_transaction_decoding.rs` |
| `fuzz_stateless_verification` | `transaction_stateless_check()` no-panic on arbitrary bytes; idempotency — a transaction that passes the check must pass it again | `fuzz/fuzz_targets/fuzz_stateless_verification.rs` |
| `fuzz_state_transition` | `execute_check_on_state()` across up to 8 transactions with fuzz-driven initial state and monotonically-advancing block context; asserts **StateIsolationOnFailure** (balances unchanged on rejection), **BalanceConservation** (total balance unchanged on success), and **ReplayRejection** (nonce consumed on first acceptance) | `fuzz/fuzz_targets/fuzz_state_transition.rs` |
| `fuzz_block_verification` | Three block-hash invariants: **HashRoundTrip** (`HashableBlockData::from(Block)` is lossless), **HashPreimage** (block_id, prev_block_hash, timestamp each individually affect the hash), **TxOrderCommitment** (reversing the transaction list changes the hash) | `fuzz/fuzz_targets/fuzz_block_verification.rs` |
@ -558,19 +558,19 @@ fuzz target parameters for zero-boilerplate structured fuzzing.
| `ArbWitnessSet` | `WitnessSet` (03 `(Signature, PublicKey)` pairs; mixes valid and invalid) |
| `ArbPublicTransaction` | `PublicTransaction` (composed from `ArbPubTxMessage` + `ArbWitnessSet`) |
| `ArbProgramDeploymentTransaction` | `ProgramDeploymentTransaction` (arbitrary bytecode) |
| `ArbHashableBlockData` | `HashableBlockData` (07 `ArbNSSATransaction` entries, random header fields) |
| `ArbNSSATransaction` | `NSSATransaction` (`Public` or `ProgramDeployment` variant; `PrivacyPreserving` excluded) |
| `ArbHashableBlockData` | `HashableBlockData` (07 `ArbLeeTransaction` entries, random header fields) |
| `ArbLeeTransaction` | `LeeTransaction` (`Public` or `ProgramDeployment` variant; `PrivacyPreserving` excluded) |
### `fuzz_props::generators` (libFuzzer helpers + proptest strategies)
| Generator | Covers |
|-----------|--------|
| `arbitrary_fuzz_state()` | 18 fuzz-driven accounts with arbitrary IDs, balances, and private keys; used by `fuzz_state_transition`, `fuzz_replay_prevention`, `fuzz_validate_execute_consistency`, `fuzz_state_diff_computation` |
| `arb_fuzz_native_transfer()` | Correctly-signed native-transfer `NSSATransaction` referencing accounts from an `arbitrary_fuzz_state()` result; gives the fuzzer a path to successful state transitions |
| `arbitrary_transaction()` | Structured `NSSATransaction` (`Public` or `ProgramDeployment`) from unstructured bytes via `ArbNSSATransaction` |
| `arb_fuzz_native_transfer()` | Correctly-signed native-transfer `LeeTransaction` referencing accounts from an `arbitrary_fuzz_state()` result; gives the fuzzer a path to successful state transitions |
| `arbitrary_transaction()` | Structured `LeeTransaction` (`Public` or `ProgramDeployment`) from unstructured bytes via `ArbLeeTransaction` |
| `arb_borsh_transaction_bytes()` | Raw Borsh bytes including invalid encodings |
| `signer_account_ids()` | Extracts `AccountId`s of all signers from an `NSSATransaction`'s witness set; used to derive signer IDs before `apply_state_diff` consumes the diff |
| `arb_native_transfer_tx()` | Valid native-transfer `NSSATransaction` between known testnet genesis accounts (proptest strategy) |
| `signer_account_ids()` | Extracts `AccountId`s of all signers from an `LeeTransaction`'s witness set; used to derive signer IDs before `apply_state_diff` consumes the diff |
| `arb_native_transfer_tx()` | Valid native-transfer `LeeTransaction` between known testnet genesis accounts (proptest strategy) |
| `test_accounts()` | Returns `(AccountId, PrivateKey)` pairs from `testnet_initial_state` |
| `arb_hashable_block_data()` | `HashableBlockData` with 08 valid native transfers (proptest strategy) |
| `arb_invalid_account_state_tx()` | Phantom accounts + overflow amounts — expected to be rejected (IS-3) |

840
fuzz/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -44,11 +44,11 @@ libfuzzer-sys = { version = "0.4", optional = true }
afl = { version = "0.15", optional = true }
arbitrary = { version = "1", features = ["derive"] }
borsh = "1"
nssa = { path = "../../logos-execution-zone/nssa" }
nssa_core = { path = "../../logos-execution-zone/nssa/core" }
common = { path = "../../logos-execution-zone/common" }
nssa = { path = "../../logos-execution-zone/lee/state_machine", package = "lee" }
nssa_core = { path = "../../logos-execution-zone/lee/state_machine/core", package = "lee_core" }
common = { path = "../../logos-execution-zone/lez/common" }
fuzz_props = { path = "../fuzz_props" }
testnet_initial_state = { path = "../../logos-execution-zone/testnet_initial_state" }
testnet_initial_state = { path = "../../logos-execution-zone/lez/testnet_initial_state" }
[profile.release]
debug = true

View File

@ -33,7 +33,7 @@
use std::collections::HashSet;
use arbitrary::{Arbitrary, Unstructured};
use fuzz_props::arbitrary_types::ArbNSSATransaction;
use fuzz_props::arbitrary_types::ArbLeeTransaction;
use fuzz_props::generators::{arbitrary_fuzz_state, signer_account_ids};
use fuzz_props::invariants::{NonceSnapshot, assert_nonce_increment_correctness};
use nssa::V03State;
@ -52,7 +52,7 @@ fuzz_props::fuzz_entry!(|data: &[u8]| {
.collect();
// Generate and stateless-check a transaction.
let tx_raw = match ArbNSSATransaction::arbitrary(&mut u) {
let tx_raw = match ArbLeeTransaction::arbitrary(&mut u) {
Ok(w) => w.0,
Err(_) => return,
};

View File

@ -38,7 +38,7 @@
use std::collections::HashSet;
use arbitrary::{Arbitrary, Unstructured};
use common::transaction::{NSSATransaction, clock_invocation};
use common::transaction::{LeeTransaction, clock_invocation};
use fuzz_props::generators::{arb_fuzz_native_transfer, arbitrary_fuzz_state, arbitrary_transaction};
use nssa::V03State;
@ -81,7 +81,7 @@ fuzz_props::fuzz_entry!(|data: &[u8]| {
// Accepted transaction list — populated here, consumed by the replayer phase
// so that both pipelines process exactly the same set of transactions.
let mut accepted_txs: Vec<NSSATransaction> = Vec::new();
let mut accepted_txs: Vec<LeeTransaction> = Vec::new();
let n_txs: u8 = u8::arbitrary(&mut u).unwrap_or(0) % 8;

View File

@ -19,7 +19,7 @@
//! specific account shapes such as zero balance or `u128::MAX` — are reachable.
use arbitrary::{Arbitrary, Unstructured};
use common::transaction::NSSATransaction;
use common::transaction::LeeTransaction;
use fuzz_props::arbitrary_types::ArbPublicTransaction;
use fuzz_props::generators::arbitrary_fuzz_state;
use nssa::{V03State, ValidatedStateDiff};
@ -47,7 +47,7 @@ fuzz_props::fuzz_entry!(|data: &[u8]| {
// Collect the set of accounts the transaction declares it will touch.
// `affected_public_account_ids()` returns owned data so `pub_tx` remains
// available for both `from_public_transaction` (borrow) and the later move
// into `NSSATransaction::Public`.
// into `LeeTransaction::Public`.
let affected = pub_tx.affected_public_account_ids();
match ValidatedStateDiff::from_public_transaction(&pub_tx, &state, 1, 0) {
@ -77,7 +77,7 @@ fuzz_props::fuzz_entry!(|data: &[u8]| {
// we do not panic on a structurally malformed transaction.
let mut exec_state = state.clone();
// `pub_tx` is moved here; it is no longer borrowed after this point.
let tx_for_exec = NSSATransaction::Public(pub_tx);
let tx_for_exec = LeeTransaction::Public(pub_tx);
if let Ok(checked_tx) = tx_for_exec.transaction_stateless_check() {
if checked_tx.execute_check_on_state(&mut exec_state, 1, 0).is_ok() {
for acc_id in &affected {

View File

@ -1,7 +1,7 @@
#![cfg_attr(feature = "fuzzer-libfuzzer", no_main)]
use arbitrary::Unstructured;
use common::transaction::NSSATransaction;
use common::transaction::LeeTransaction;
use fuzz_props::generators::arbitrary_transaction;
fuzz_props::fuzz_entry!(|data: &[u8]| {
@ -22,7 +22,7 @@ fuzz_props::fuzz_entry!(|data: &[u8]| {
}
// Path B: raw decode first, then check — must never panic
if let Ok(tx) = borsh::from_slice::<NSSATransaction>(data) {
if let Ok(tx) = borsh::from_slice::<LeeTransaction>(data) {
let _ = tx.transaction_stateless_check();
}
});

View File

@ -2,19 +2,19 @@
use common::{
block::{Block, HashableBlockData},
transaction::NSSATransaction,
transaction::LeeTransaction,
};
fuzz_props::fuzz_entry!(|data: &[u8]| {
// Attempt 1: decode as NSSATransaction and verify roundtrip
if let Ok(tx) = borsh::from_slice::<NSSATransaction>(data) {
// Attempt 1: decode as LeeTransaction and verify roundtrip
if let Ok(tx) = borsh::from_slice::<LeeTransaction>(data) {
let re_encoded = borsh::to_vec(&tx).expect("re-encode of valid tx must succeed");
let tx2 = borsh::from_slice::<NSSATransaction>(&re_encoded)
let tx2 = borsh::from_slice::<LeeTransaction>(&re_encoded)
.expect("second decode of re-encoded tx must succeed");
assert_eq!(
re_encoded,
borsh::to_vec(&tx2).unwrap(),
"NSSATransaction roundtrip encoding divergence"
"LeeTransaction roundtrip encoding divergence"
);
}

View File

@ -25,7 +25,7 @@
//! reachable by the fuzzer.
use arbitrary::{Arbitrary, Unstructured};
use fuzz_props::arbitrary_types::ArbNSSATransaction;
use fuzz_props::arbitrary_types::ArbLeeTransaction;
use fuzz_props::generators::{arbitrary_fuzz_state, signer_account_ids};
use fuzz_props::invariants::{NonceSnapshot, assert_nonce_increment_correctness};
use nssa::V03State;
@ -47,7 +47,7 @@ fuzz_props::fuzz_entry!(|data: &[u8]| {
.collect();
// Generate the transaction from the remaining fuzz bytes.
let tx = match ArbNSSATransaction::arbitrary(&mut u) {
let tx = match ArbLeeTransaction::arbitrary(&mut u) {
Ok(w) => w.0,
Err(_) => return,
};

View File

@ -2,7 +2,7 @@
//!
//! **No changes to `../logos-execution-zone` are required.**
//!
//! The Rust orphan rule forbids `impl Arbitrary for NSSATransaction` when both
//! The Rust orphan rule forbids `impl Arbitrary for LeeTransaction` when both
//! the trait and the type come from external crates. Using newtypes (`ArbXxx`)
//! sidesteps the restriction entirely.
//!
@ -10,10 +10,10 @@
//!
//! ```rust,ignore
//! #![no_main]
//! use fuzz_props::arbitrary_types::ArbNSSATransaction;
//! use fuzz_props::arbitrary_types::ArbLeeTransaction;
//! use libfuzzer_sys::fuzz_target;
//!
//! fuzz_target!(|wrapped: ArbNSSATransaction| {
//! fuzz_target!(|wrapped: ArbLeeTransaction| {
//! let tx = wrapped.0;
//! let Ok(valid_tx) = tx.transaction_stateless_check() else { return; };
//! // …
@ -21,7 +21,7 @@
//! ```
use arbitrary::{Arbitrary, Result as ArbResult, Unstructured};
use common::{HashType, block::HashableBlockData, transaction::NSSATransaction};
use common::{HashType, block::HashableBlockData, transaction::LeeTransaction};
use nssa::{
AccountId, PrivateKey, PublicKey, Signature,
program_deployment_transaction::ProgramDeploymentTransaction,
@ -210,24 +210,24 @@ impl<'a> Arbitrary<'a> for ArbProgramDeploymentTransaction {
}
}
// ── NSSATransaction ───────────────────────────────────────────────────────────
// ── LeeTransaction ───────────────────────────────────────────────────────────
// `PrivacyPreservingTransaction` is intentionally excluded: it embeds a risc0
// ZK receipt that cannot be generated inside a hot fuzzing loop. This matches
// the known limitation documented in `docs/fuzzing.md`.
/// Newtype wrapper providing [`Arbitrary`] for [`NSSATransaction`].
/// Newtype wrapper providing [`Arbitrary`] for [`LeeTransaction`].
///
/// Generates `Public` and `ProgramDeployment` variants only.
#[derive(Debug)]
pub struct ArbNSSATransaction(pub NSSATransaction);
pub struct ArbLeeTransaction(pub LeeTransaction);
impl<'a> Arbitrary<'a> for ArbNSSATransaction {
impl<'a> Arbitrary<'a> for ArbLeeTransaction {
fn arbitrary(u: &mut Unstructured<'a>) -> ArbResult<Self> {
match u8::arbitrary(u)? % 2 {
0 => Ok(Self(NSSATransaction::Public(
0 => Ok(Self(LeeTransaction::Public(
ArbPublicTransaction::arbitrary(u)?.0,
))),
_ => Ok(Self(NSSATransaction::ProgramDeployment(
_ => Ok(Self(LeeTransaction::ProgramDeployment(
ArbProgramDeploymentTransaction::arbitrary(u)?.0,
))),
}
@ -246,7 +246,7 @@ impl<'a> Arbitrary<'a> for ArbHashableBlockData {
fn arbitrary(u: &mut Unstructured<'a>) -> ArbResult<Self> {
// 07 transactions per block
let n = (u8::arbitrary(u)? as usize) % 8;
let transactions = std::iter::repeat_with(|| ArbNSSATransaction::arbitrary(u).map(|t| t.0))
let transactions = std::iter::repeat_with(|| ArbLeeTransaction::arbitrary(u).map(|t| t.0))
.take(n)
.collect::<ArbResult<Vec<_>>>()?;
Ok(Self(HashableBlockData {

View File

@ -1,8 +1,8 @@
use arbitrary::{Arbitrary, Unstructured};
use common::{block::HashableBlockData, transaction::NSSATransaction};
use common::{block::HashableBlockData, transaction::LeeTransaction};
use nssa::{AccountId, PrivateKey};
use crate::arbitrary_types::{ArbAccountId, ArbNSSATransaction, ArbPrivateKey};
use crate::arbitrary_types::{ArbAccountId, ArbLeeTransaction, ArbPrivateKey};
use proptest::prelude::*;
use testnet_initial_state::initial_pub_accounts_private_keys;
@ -12,22 +12,22 @@ use testnet_initial_state::initial_pub_accounts_private_keys;
/// witness set. Used by fuzz targets that need to verify nonce
/// increments after `execute_check_on_state`.
#[must_use]
pub fn signer_account_ids(tx: &common::transaction::NSSATransaction) -> Vec<nssa::AccountId> {
use common::transaction::NSSATransaction;
pub fn signer_account_ids(tx: &common::transaction::LeeTransaction) -> Vec<nssa::AccountId> {
use common::transaction::LeeTransaction;
match tx {
NSSATransaction::Public(pt) => pt
LeeTransaction::Public(pt) => pt
.witness_set()
.signatures_and_public_keys()
.iter()
.map(|(_, pk)| nssa::AccountId::from(pk))
.collect(),
NSSATransaction::PrivacyPreserving(pt) => pt
LeeTransaction::PrivacyPreserving(pt) => pt
.witness_set()
.signatures_and_public_keys()
.iter()
.map(|(_, pk)| nssa::AccountId::from(pk))
.collect(),
NSSATransaction::ProgramDeployment(_) => vec![],
LeeTransaction::ProgramDeployment(_) => vec![],
}
}
@ -74,7 +74,7 @@ pub fn arbitrary_fuzz_state(u: &mut Unstructured<'_>) -> arbitrary::Result<Vec<F
.collect()
}
/// Generate a native-transfer [`NSSATransaction`] between two accounts chosen
/// Generate a native-transfer [`LeeTransaction`] between two accounts chosen
/// from `accounts`.
///
/// Because every account in the slice has a known private key, the resulting
@ -87,7 +87,7 @@ pub fn arbitrary_fuzz_state(u: &mut Unstructured<'_>) -> arbitrary::Result<Vec<F
pub fn arb_fuzz_native_transfer(
u: &mut Unstructured<'_>,
accounts: &[FuzzAccount],
) -> arbitrary::Result<NSSATransaction> {
) -> arbitrary::Result<LeeTransaction> {
if accounts.is_empty() {
return Err(arbitrary::Error::IncorrectFormat);
}
@ -112,9 +112,9 @@ pub fn arb_fuzz_native_transfer(
// ── Arbitrary (for libFuzzer targets) ────────────────────────────────────────
/// Generate a structurally plausible `NSSATransaction` from unstructured bytes.
pub fn arbitrary_transaction(u: &mut Unstructured<'_>) -> arbitrary::Result<NSSATransaction> {
ArbNSSATransaction::arbitrary(u).map(|w| w.0)
/// Generate a structurally plausible `LeeTransaction` from unstructured bytes.
pub fn arbitrary_transaction(u: &mut Unstructured<'_>) -> arbitrary::Result<LeeTransaction> {
ArbLeeTransaction::arbitrary(u).map(|w| w.0)
}
// ── proptest strategies ───────────────────────────────────────────────────────
@ -128,7 +128,7 @@ prop_compose! {
to_idx in 0..accounts.len(),
nonce in 0_u128..1_000_u128,
amount in 0_u128..10_000_u128,
) -> NSSATransaction {
) -> LeeTransaction {
let (from_id, from_key) = &accounts[from_idx];
let (to_id, _) = &accounts[to_idx];
common::test_utils::create_transaction_native_token_transfer(
@ -146,11 +146,11 @@ pub fn test_accounts() -> Vec<(AccountId, PrivateKey)> {
.collect()
}
/// Strategy: raw bytes that are valid borsh encodings of `NSSATransaction`.
/// Strategy: raw bytes that are valid borsh encodings of `LeeTransaction`.
pub fn arb_borsh_transaction_bytes() -> impl Strategy<Value = Vec<u8>> {
any::<Vec<u8>>().prop_map(|bytes| {
// Either pass through raw bytes OR encode a known dummy transaction
if borsh::from_slice::<NSSATransaction>(&bytes).is_ok() {
if borsh::from_slice::<LeeTransaction>(&bytes).is_ok() {
bytes
} else {
borsh::to_vec(&common::test_utils::produce_dummy_empty_transaction()).unwrap()
@ -183,7 +183,7 @@ prop_compose! {
phantom_id_bytes in proptest::array::uniform32(0_u8..),
amount in (u128::MAX / 2)..u128::MAX, // overflow-inducing amount
nonce in 0_u128..10_u128,
) -> NSSATransaction {
) -> LeeTransaction {
let phantom_id = nssa::AccountId::new(phantom_id_bytes);
// Attempt to sign with a key that has no matching on-chain account
let signing_key = nssa::PrivateKey::try_new(phantom_id_bytes)
@ -204,11 +204,11 @@ prop_compose! {
/// attack candidates) and some are re-ordered permutations of a valid sequence.
/// Used in proptest-level tests and as a seed generator for the state-transition
/// fuzz target.
pub fn arb_duplicate_tx_sequence() -> impl Strategy<Value = Vec<NSSATransaction>> {
pub fn arb_duplicate_tx_sequence() -> impl Strategy<Value = Vec<LeeTransaction>> {
let accounts = test_accounts();
proptest::collection::vec(arb_native_transfer_tx(accounts), 1..5_usize).prop_flat_map(|txs| {
// Build a sequence that: original | duplicates | reversed
let duped: Vec<NSSATransaction> = txs
let duped: Vec<LeeTransaction> = txs
.iter()
.cloned()
.chain(txs.iter().cloned()) // append exact duplicates
@ -225,7 +225,7 @@ pub fn arb_duplicate_tx_sequence() -> impl Strategy<Value = Vec<NSSATransaction>
/// - self-transfers (sender == recipient),
/// - max-nonce wrapping,
/// - alternating valid / invalid transactions to test partial-batch isolation.
pub fn arb_pathological_sequence() -> impl Strategy<Value = Vec<NSSATransaction>> {
pub fn arb_pathological_sequence() -> impl Strategy<Value = Vec<LeeTransaction>> {
let accounts = test_accounts();
let n = accounts.len();
proptest::collection::vec((0..n, 0..n, 0_u128..5_u128, any::<bool>()), 1..8_usize).prop_map(

View File

@ -1,4 +1,4 @@
use common::transaction::NSSATransaction;
use common::transaction::LeeTransaction;
use nssa::V03State;
use nssa_core::account::Nonce;
@ -185,7 +185,7 @@ impl ProtocolInvariant for FailedTxNonceStability {
/// # Enforcement
///
/// This invariant **cannot** be enforced through [`InvariantCtx`] because the replay
/// check requires re-applying the `NSSATransaction` that `execute_check_on_state`
/// check requires re-applying the `LeeTransaction` that `execute_check_on_state`
/// consumes and returns on `Ok`. It is therefore **not registered** in
/// [`assert_invariants`]; calling `assert_invariants` alone does **not** cover
/// `ReplayRejection`.
@ -235,7 +235,7 @@ pub struct NonceIncrementCorrectness;
///
/// # Why a standalone function?
///
/// `execute_check_on_state` consumes the `NSSATransaction` and returns it on `Ok`,
/// `execute_check_on_state` consumes the `LeeTransaction` and returns it on `Ok`,
/// so the transaction is not available as a shared reference inside [`InvariantCtx`].
/// This function accepts ownership of the returned transaction and performs the
/// replay in-place.
@ -249,7 +249,7 @@ pub struct NonceIncrementCorrectness;
/// }
/// ```
pub fn assert_replay_rejection(
applied_tx: NSSATransaction,
applied_tx: LeeTransaction,
state: &mut V03State,
next_block_id: u64,
next_timestamp: u64,
@ -270,7 +270,7 @@ pub fn assert_replay_rejection(
/// passing the signer IDs derived from the transaction's witness set, the [`NonceSnapshot`]
/// captured **before** execution, and the post-execution state.
///
/// For a `NSSATransaction::Public(tx)`, derive signer IDs as:
/// For a `LeeTransaction::Public(tx)`, derive signer IDs as:
///
/// ```rust,ignore
/// let signer_ids: Vec<nssa::AccountId> = tx
@ -281,7 +281,7 @@ pub fn assert_replay_rejection(
/// .collect();
/// ```
///
/// For `NSSATransaction::ProgramDeployment`, there are no signers; pass an empty slice.
/// For `LeeTransaction::ProgramDeployment`, there are no signers; pass an empty slice.
///
/// # Why a standalone function?
///
@ -377,7 +377,7 @@ pub fn assert_tx_execution_invariants<E>(
state_after: &mut V03State,
balances_before: BalanceSnapshot,
nonces_before: NonceSnapshot,
execution_result: Result<NSSATransaction, E>,
execution_result: Result<LeeTransaction, E>,
replay_context: (u64, u64),
) {
let execution_succeeded = execution_result.is_ok();
@ -400,19 +400,19 @@ pub fn assert_tx_execution_invariants<E>(
if let Ok(applied_tx) = execution_result {
// Derive signer IDs from the witness set. ProgramDeployment has no signers.
let signer_ids: Vec<nssa::AccountId> = match &applied_tx {
NSSATransaction::Public(pt) => pt
LeeTransaction::Public(pt) => pt
.witness_set()
.signatures_and_public_keys()
.iter()
.map(|(_, pk)| nssa::AccountId::from(pk))
.collect(),
NSSATransaction::PrivacyPreserving(pt) => pt
LeeTransaction::PrivacyPreserving(pt) => pt
.witness_set()
.signatures_and_public_keys()
.iter()
.map(|(_, pk)| nssa::AccountId::from(pk))
.collect(),
NSSATransaction::ProgramDeployment(_) => vec![],
LeeTransaction::ProgramDeployment(_) => vec![],
};
assert_nonce_increment_correctness(&signer_ids, &nonces_for_nonce_check, state_after);
let (next_block_id, next_timestamp) = replay_context;