278 lines
7.6 KiB
Rust
Raw Normal View History

2026-03-04 18:42:33 +03:00
#![expect(
clippy::multiple_inherent_impl,
reason = "We prefer to group methods by functionality rather than by type for encoding"
)]
2025-08-06 20:05:04 -03:00
pub use lee_core::{
GENESIS_BLOCK_ID, SharedSecretKey,
account::{Account, AccountId, Balance, Data},
2025-12-11 20:59:37 -03:00
encryption::EphemeralPublicKey,
program::ProgramId,
};
pub use privacy_preserving_circuit::{
PRIVACY_PRESERVING_CIRCUIT_ELF, PRIVACY_PRESERVING_CIRCUIT_ID,
};
2025-08-27 16:24:20 -03:00
pub use privacy_preserving_transaction::{
PrivacyPreservingTransaction, circuit::execute_and_prove,
};
pub use program_deployment_transaction::ProgramDeploymentTransaction;
2025-10-16 16:19:39 -03:00
pub use public_transaction::PublicTransaction;
2025-11-26 00:27:20 +03:00
pub use signature::{PrivateKey, PublicKey, Signature};
pub use state::V03State;
pub use validated_state_diff::ValidatedStateDiff;
2026-03-04 18:42:33 +03:00
pub mod encoding;
pub mod error;
mod merkle_tree;
pub mod privacy_preserving_transaction;
pub mod program;
pub mod program_deployment_transaction;
pub mod public_transaction;
mod signature;
mod state;
mod validated_state_diff;
2026-03-04 18:42:33 +03:00
mod privacy_preserving_circuit {
include!(concat!(
env!("OUT_DIR"),
"/lee/privacy_preserving_circuit/mod.rs"
));
}
#[cfg(test)]
mod test_methods {
use std::borrow::Cow;
use crate::program::Program;
#[must_use]
pub const fn simple_balance_transfer() -> Program {
Program::new_unchecked(
test_methods::SIMPLE_BALANCE_TRANSFER_ID,
Cow::Borrowed(test_methods::SIMPLE_BALANCE_TRANSFER_ELF),
)
}
#[must_use]
pub const fn nonce_changer() -> Program {
Program::new_unchecked(
test_methods::NONCE_CHANGER_ID,
Cow::Borrowed(test_methods::NONCE_CHANGER_ELF),
)
}
#[must_use]
pub const fn extra_output() -> Program {
Program::new_unchecked(
test_methods::EXTRA_OUTPUT_ID,
Cow::Borrowed(test_methods::EXTRA_OUTPUT_ELF),
)
}
#[must_use]
pub const fn missing_output() -> Program {
Program::new_unchecked(
test_methods::MISSING_OUTPUT_ID,
Cow::Borrowed(test_methods::MISSING_OUTPUT_ELF),
)
}
fix!(state_machine): reject public transactions that silently drop a d… (#625) * fix(state_machine): reject public transactions that silently drop a declared account ValidatedStateDiff::from_public_transaction never checked that the accounts touched in a program's output matched the caller-declared message.account_ids — it just folded whatever pairs the program returned into the diff. A program (or a macro-generated dispatcher wrapping one) that silently drops an account from both sides of its own output together stays internally consistent (pre_states.len() == post_states.len()) and passes validate_execution's existing checks, so the dropped account simply vanishes with no error. Add a check after the chained-call loop: every account_id in message.account_ids must appear in the final state_diff, or the transaction is rejected with the new DeclaredAccountMissingFromOutput error. Add a dropped_account test-guest program that reproduces the exact shape of the bug (two pre_states in, one consistent (pre, post) pair out) and a regression test proving the transaction is now rejected. Verified the test fails with Ok(()) when the check is removed, and passes once it's restored. * style: tighten comments and apply nightly rustfmt Condense the explanatory comments on the new account-accounting check and the dropped_account test guest, and fix imprecise wording (the account is dropped from both pre_state and post_states together, not just pre_state). Also applies cargo +nightly fmt's wrapping of the new error message. * chore: regenerate test fixture after rebase onto dev
2026-07-23 12:09:16 -04:00
#[must_use]
pub const fn dropped_account() -> Program {
Program::new_unchecked(
test_methods::DROPPED_ACCOUNT_ID,
Cow::Borrowed(test_methods::DROPPED_ACCOUNT_ELF),
)
}
#[must_use]
pub const fn program_owner_changer() -> Program {
Program::new_unchecked(
test_methods::PROGRAM_OWNER_CHANGER_ID,
Cow::Borrowed(test_methods::PROGRAM_OWNER_CHANGER_ELF),
)
}
#[must_use]
pub const fn data_changer() -> Program {
Program::new_unchecked(
test_methods::DATA_CHANGER_ID,
Cow::Borrowed(test_methods::DATA_CHANGER_ELF),
)
}
#[must_use]
pub const fn minter() -> Program {
Program::new_unchecked(
test_methods::MINTER_ID,
Cow::Borrowed(test_methods::MINTER_ELF),
)
}
#[must_use]
pub const fn burner() -> Program {
Program::new_unchecked(
test_methods::BURNER_ID,
Cow::Borrowed(test_methods::BURNER_ELF),
)
}
#[must_use]
pub const fn auth_asserting_noop() -> Program {
Program::new_unchecked(
test_methods::AUTH_ASSERTING_NOOP_ID,
Cow::Borrowed(test_methods::AUTH_ASSERTING_NOOP_ELF),
)
}
#[must_use]
pub const fn private_pda_delegator() -> Program {
Program::new_unchecked(
test_methods::PRIVATE_PDA_DELEGATOR_ID,
Cow::Borrowed(test_methods::PRIVATE_PDA_DELEGATOR_ELF),
)
}
#[must_use]
pub const fn pda_claimer() -> Program {
Program::new_unchecked(
test_methods::PDA_CLAIMER_ID,
Cow::Borrowed(test_methods::PDA_CLAIMER_ELF),
)
}
#[must_use]
pub const fn two_pda_claimer() -> Program {
Program::new_unchecked(
test_methods::TWO_PDA_CLAIMER_ID,
Cow::Borrowed(test_methods::TWO_PDA_CLAIMER_ELF),
)
}
#[must_use]
pub const fn noop() -> Program {
Program::new_unchecked(test_methods::NOOP_ID, Cow::Borrowed(test_methods::NOOP_ELF))
}
#[must_use]
pub const fn chain_caller() -> Program {
Program::new_unchecked(
test_methods::CHAIN_CALLER_ID,
Cow::Borrowed(test_methods::CHAIN_CALLER_ELF),
)
}
#[must_use]
pub const fn modified_transfer_program() -> Program {
Program::new_unchecked(
test_methods::MODIFIED_TRANSFER_ID,
Cow::Borrowed(test_methods::MODIFIED_TRANSFER_ELF),
)
}
#[must_use]
pub const fn malicious_authorization_changer() -> Program {
Program::new_unchecked(
test_methods::MALICIOUS_AUTHORIZATION_CHANGER_ID,
Cow::Borrowed(test_methods::MALICIOUS_AUTHORIZATION_CHANGER_ELF),
)
}
#[must_use]
pub const fn validity_window() -> Program {
Program::new_unchecked(
test_methods::VALIDITY_WINDOW_ID,
Cow::Borrowed(test_methods::VALIDITY_WINDOW_ELF),
)
}
#[must_use]
pub const fn flash_swap_initiator() -> Program {
Program::new_unchecked(
test_methods::FLASH_SWAP_INITIATOR_ID,
Cow::Borrowed(test_methods::FLASH_SWAP_INITIATOR_ELF),
)
}
#[must_use]
pub const fn flash_swap_callback() -> Program {
Program::new_unchecked(
test_methods::FLASH_SWAP_CALLBACK_ID,
Cow::Borrowed(test_methods::FLASH_SWAP_CALLBACK_ELF),
)
}
#[must_use]
pub const fn malicious_self_program_id() -> Program {
Program::new_unchecked(
test_methods::MALICIOUS_SELF_PROGRAM_ID_ID,
Cow::Borrowed(test_methods::MALICIOUS_SELF_PROGRAM_ID_ELF),
)
}
#[must_use]
pub const fn malicious_caller_program_id() -> Program {
Program::new_unchecked(
test_methods::MALICIOUS_CALLER_PROGRAM_ID_ID,
Cow::Borrowed(test_methods::MALICIOUS_CALLER_PROGRAM_ID_ELF),
)
}
#[must_use]
pub const fn pda_spend_proxy() -> Program {
Program::new_unchecked(
test_methods::PDA_SPEND_PROXY_ID,
Cow::Borrowed(test_methods::PDA_SPEND_PROXY_ELF),
)
}
#[must_use]
pub const fn claimer() -> Program {
Program::new_unchecked(
test_methods::CLAIMER_ID,
Cow::Borrowed(test_methods::CLAIMER_ELF),
)
}
#[must_use]
pub const fn changer_claimer() -> Program {
Program::new_unchecked(
test_methods::CHANGER_CLAIMER_ID,
Cow::Borrowed(test_methods::CHANGER_CLAIMER_ELF),
)
}
#[must_use]
pub const fn validity_window_chain_caller() -> Program {
Program::new_unchecked(
test_methods::VALIDITY_WINDOW_CHAIN_CALLER_ID,
Cow::Borrowed(test_methods::VALIDITY_WINDOW_CHAIN_CALLER_ELF),
)
}
#[must_use]
#[inline]
pub const fn simple_transfer_proxy() -> Program {
Program::new_unchecked(
test_methods::SIMPLE_TRANSFER_PROXY_ID,
Cow::Borrowed(test_methods::SIMPLE_TRANSFER_PROXY_ELF),
)
}
#[must_use]
pub const fn malicious_injector() -> Program {
Program::new_unchecked(
test_methods::MALICIOUS_INJECTOR_ID,
Cow::Borrowed(test_methods::MALICIOUS_INJECTOR_ELF),
)
}
#[must_use]
pub const fn malicious_launderer() -> Program {
Program::new_unchecked(
test_methods::MALICIOUS_LAUNDERER_ID,
Cow::Borrowed(test_methods::MALICIOUS_LAUNDERER_ELF),
)
}
2026-03-04 18:42:33 +03:00
}