fix: apply formatting and rebuild artifacts

This commit is contained in:
Moudy
2026-04-03 01:17:42 +02:00
parent 88e3b368c3
commit 74e16db68f
54 changed files with 319 additions and 91 deletions
Generated
+1
View File
@@ -7833,6 +7833,7 @@ version = "0.1.0"
dependencies = [
"nssa_core",
"risc0-zkvm",
"serde",
]
[[package]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -18,7 +18,9 @@ type Instruction = Vec<u8>;
fn main() {
// Read inputs
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: greeting,
},
@@ -50,5 +52,11 @@ fn main() {
// with the NSSA program rules.
// WARNING: constructing a `ProgramOutput` has no effect on its own. `.write()` must be
// called to commit the output.
ProgramOutput::new(self_program_id, instruction_data, vec![pre_state], vec![post_state]).write();
ProgramOutput::new(
self_program_id,
instruction_data,
vec![pre_state],
vec![post_state],
)
.write();
}
@@ -18,7 +18,9 @@ type Instruction = Vec<u8>;
fn main() {
// Read inputs
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: greeting,
},
@@ -57,5 +59,11 @@ fn main() {
// with the NSSA program rules.
// WARNING: constructing a `ProgramOutput` has no effect on its own. `.write()` must be
// called to commit the output.
ProgramOutput::new(self_program_id, instruction_data, vec![pre_state], vec![post_state]).write();
ProgramOutput::new(
self_program_id,
instruction_data,
vec![pre_state],
vec![post_state],
)
.write();
}
@@ -65,7 +65,9 @@ fn move_data(from_pre: AccountWithMetadata, to_pre: AccountWithMetadata) -> Vec<
fn main() {
// Read input accounts.
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (function_id, data),
},
@@ -26,7 +26,9 @@ fn hello_world_program_id() -> ProgramId {
fn main() {
// Read inputs
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (),
},
@@ -55,7 +57,12 @@ fn main() {
// Write the outputs.
// WARNING: constructing a `ProgramOutput` has no effect on its own. `.write()` must be
// called to commit the output.
ProgramOutput::new(self_program_id, instruction_data, vec![pre_state], vec![post_state])
.with_chained_calls(vec![chained_call])
.write();
ProgramOutput::new(
self_program_id,
instruction_data,
vec![pre_state],
vec![post_state],
)
.with_chained_calls(vec![chained_call])
.write();
}
@@ -32,7 +32,9 @@ fn hello_world_program_id() -> ProgramId {
fn main() {
// Read inputs
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (),
},
@@ -68,7 +70,12 @@ fn main() {
// Write the outputs.
// WARNING: constructing a `ProgramOutput` has no effect on its own. `.write()` must be
// called to commit the output.
ProgramOutput::new(self_program_id, instruction_data, vec![pre_state], vec![post_state])
.with_chained_calls(vec![chained_call])
.write();
ProgramOutput::new(
self_program_id,
instruction_data,
vec![pre_state],
vec![post_state],
)
.with_chained_calls(vec![chained_call])
.write();
}
@@ -160,7 +160,13 @@ fn execute_and_prove_program(
) -> Result<Receipt, NssaError> {
// Write inputs to the program
let mut env_builder = ExecutorEnv::builder();
Program::write_inputs(program.id(), caller_program_id, pre_states, instruction_data, &mut env_builder)?;
Program::write_inputs(
program.id(),
caller_program_id,
pre_states,
instruction_data,
&mut env_builder,
)?;
let env = env_builder.build().unwrap();
// Prove the program
+7 -1
View File
@@ -59,7 +59,13 @@ impl Program {
// Write inputs to the program
let mut env_builder = ExecutorEnv::builder();
env_builder.session_limit(Some(MAX_NUM_CYCLES_PUBLIC_EXECUTION));
Self::write_inputs(self.id, caller_program_id, pre_states, instruction_data, &mut env_builder)?;
Self::write_inputs(
self.id,
caller_program_id,
pre_states,
instruction_data,
&mut env_builder,
)?;
let env = env_builder.build().unwrap();
// Execute the program (without proving)
+5 -2
View File
@@ -147,8 +147,11 @@ impl PublicTransaction {
"Program {:?} pre_states: {:?}, instruction_data: {:?}",
chained_call.program_id, chained_call.pre_states, chained_call.instruction_data
);
let mut program_output =
program.execute(caller_program_id, &chained_call.pre_states, &chained_call.instruction_data)?;
let mut program_output = program.execute(
caller_program_id,
&chained_call.pre_states,
&chained_call.instruction_data,
)?;
debug!(
"Program {:?} output: {:?}",
chained_call.program_id, program_output
+100 -29
View File
@@ -3523,7 +3523,7 @@ pub mod tests {
let message = public_transaction::Message::try_new(
initiator.id(),
vec![vault_id, receiver_id],
vec![], // no signers — vault is PDA-authorised
vec![], // no signers — vault is PDA-authorised
instruction,
)
.unwrap();
@@ -3561,18 +3561,33 @@ pub mod tests {
// Pre-simulated intermediate states:
// After transfer (vault→receiver, amount_out):
let vault_after_transfer = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: initial_balance - amount_out, ..Account::default() },
false, vault_id,
Account {
program_owner: token.id(),
balance: initial_balance - amount_out,
..Account::default()
},
false,
vault_id,
);
let receiver_after_transfer = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: amount_out, ..Account::default() },
false, receiver_id,
Account {
program_owner: token.id(),
balance: amount_out,
..Account::default()
},
false,
receiver_id,
);
// After callback returns funds (receiver→vault, amount_out):
let vault_after_callback = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: initial_balance, ..Account::default() },
false, vault_id,
Account {
program_owner: token.id(),
balance: initial_balance,
..Account::default()
},
false,
vault_id,
);
// Callback instruction: return funds
@@ -3581,12 +3596,22 @@ pub mod tests {
token_program_id: token.id(),
amount: amount_out,
vault_after_return: Some(AccountWithMetadata::new(
Account { program_owner: token.id(), balance: initial_balance, ..Account::default() },
false, vault_id,
Account {
program_owner: token.id(),
balance: initial_balance,
..Account::default()
},
false,
vault_id,
)),
receiver_after_return: Some(AccountWithMetadata::new(
Account { program_owner: token.id(), balance: 0, ..Account::default() },
false, receiver_id,
Account {
program_owner: token.id(),
balance: 0,
..Account::default()
},
false,
receiver_id,
)),
};
let cb_data = Program::serialize_instruction(cb_instruction).unwrap();
@@ -3639,18 +3664,33 @@ pub mod tests {
// Pre-simulated intermediate states (same as successful case for steps 1-2):
let vault_after_transfer = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: initial_balance - amount_out, ..Account::default() },
false, vault_id,
Account {
program_owner: token.id(),
balance: initial_balance - amount_out,
..Account::default()
},
false,
vault_id,
);
let receiver_after_transfer = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: amount_out, ..Account::default() },
false, receiver_id,
Account {
program_owner: token.id(),
balance: amount_out,
..Account::default()
},
false,
receiver_id,
);
// After callback that does NOT return funds — vault stays drained:
let vault_after_callback = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: initial_balance - amount_out, ..Account::default() },
false, vault_id,
Account {
program_owner: token.id(),
balance: initial_balance - amount_out,
..Account::default()
},
false,
vault_id,
);
// Callback instruction: do NOT return funds
@@ -3677,7 +3717,10 @@ pub mod tests {
let result = state.transition_from_public_transaction(&tx, 1, 0);
// Invariant check fails → entire tx rolls back
assert!(result.is_err(), "flash swap should fail when callback keeps funds");
assert!(
result.is_err(),
"flash swap should fail when callback keeps funds"
);
// State unchanged (rollback)
assert_eq!(state.get_account_by_id(vault_id).balance, initial_balance);
@@ -3714,17 +3757,32 @@ pub mod tests {
// Zero-amount transfer: states remain unchanged after transfer
let vault_after_transfer = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: initial_balance, ..Account::default() },
false, vault_id,
Account {
program_owner: token.id(),
balance: initial_balance,
..Account::default()
},
false,
vault_id,
);
let receiver_after_transfer = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: 0, ..Account::default() },
false, receiver_id,
Account {
program_owner: token.id(),
balance: 0,
..Account::default()
},
false,
receiver_id,
);
// Callback with zero amount, return_funds=true (no-op effectively)
let vault_after_callback = AccountWithMetadata::new(
Account { program_owner: token.id(), balance: initial_balance, ..Account::default() },
false, vault_id,
Account {
program_owner: token.id(),
balance: initial_balance,
..Account::default()
},
false,
vault_id,
);
let cb_instruction = CallbackInstruction {
@@ -3732,12 +3790,22 @@ pub mod tests {
token_program_id: token.id(),
amount: 0,
vault_after_return: Some(AccountWithMetadata::new(
Account { program_owner: token.id(), balance: initial_balance, ..Account::default() },
false, vault_id,
Account {
program_owner: token.id(),
balance: initial_balance,
..Account::default()
},
false,
vault_id,
)),
receiver_after_return: Some(AccountWithMetadata::new(
Account { program_owner: token.id(), balance: 0, ..Account::default() },
false, receiver_id,
Account {
program_owner: token.id(),
balance: 0,
..Account::default()
},
false,
receiver_id,
)),
};
let cb_data = Program::serialize_instruction(cb_instruction).unwrap();
@@ -3754,7 +3822,10 @@ pub mod tests {
let tx = build_flash_swap_tx(&initiator, vault_id, receiver_id, instruction);
let result = state.transition_from_public_transaction(&tx, 1, 0);
assert!(result.is_ok(), "zero-amount flash swap should succeed: {result:?}");
assert!(
result.is_ok(),
"zero-amount flash swap should succeed: {result:?}"
);
}
#[test]
+11 -4
View File
@@ -13,7 +13,9 @@ use nssa_core::program::{ProgramInput, ProgramOutput, read_nssa_inputs};
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction,
},
@@ -152,7 +154,12 @@ fn main() {
}
};
ProgramOutput::new(self_program_id, instruction_words, pre_states_clone, post_states)
.with_chained_calls(chained_calls)
.write();
ProgramOutput::new(
self_program_id,
instruction_words,
pre_states_clone,
post_states,
)
.with_chained_calls(chained_calls)
.write();
}
@@ -3,7 +3,9 @@ use nssa_core::program::{ProgramInput, ProgramOutput, read_nssa_inputs};
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction,
},
@@ -56,7 +58,12 @@ fn main() {
}
};
ProgramOutput::new(self_program_id, instruction_words, pre_states_clone, post_states)
.with_chained_calls(chained_calls)
.write();
ProgramOutput::new(
self_program_id,
instruction_words,
pre_states_clone,
post_states,
)
.with_chained_calls(chained_calls)
.write();
}
@@ -66,7 +66,9 @@ fn transfer(
fn main() {
// Read input accounts.
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: balance_to_move,
},
+3 -1
View File
@@ -45,7 +45,9 @@ fn main() {
// Read input accounts.
// It is expected to receive only two accounts: [pinata_account, winner_account]
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: solution,
},
@@ -51,7 +51,9 @@ fn main() {
// It is expected to receive three accounts: [pinata_definition, pinata_token_holding,
// winner_token_holding]
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: solution,
},
+10 -2
View File
@@ -11,7 +11,9 @@ use token_program::core::Instruction;
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction,
},
@@ -81,5 +83,11 @@ fn main() {
}
};
ProgramOutput::new(self_program_id, instruction_words, pre_states_clone, post_states).write();
ProgramOutput::new(
self_program_id,
instruction_words,
pre_states_clone,
post_states,
)
.write();
}
+3 -1
View File
@@ -4,7 +4,9 @@ type Instruction = u128;
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: balance_to_burn,
},
@@ -12,7 +12,9 @@ type Instruction = (u128, ProgramId, u32, Option<PdaSeed>);
/// program.
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (balance, auth_transfer_id, num_chain_calls, pda_seed),
},
@@ -5,7 +5,9 @@ type Instruction = (Option<Vec<u8>>, bool);
/// A program that optionally modifies the account data and optionally claims it.
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (data_opt, should_claim),
},
@@ -33,5 +35,11 @@ fn main() {
AccountPostState::new(account_post)
};
ProgramOutput::new(self_program_id, instruction_words, vec![pre], vec![post_state]).write();
ProgramOutput::new(
self_program_id,
instruction_words,
vec![pre],
vec![post_state],
)
.write();
}
+10 -2
View File
@@ -4,7 +4,9 @@ type Instruction = ();
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (),
},
@@ -17,5 +19,11 @@ fn main() {
let account_post = AccountPostState::new_claimed(pre.account.clone(), Claim::Authorized);
ProgramOutput::new(self_program_id, instruction_words, vec![pre], vec![account_post]).write();
ProgramOutput::new(
self_program_id,
instruction_words,
vec![pre],
vec![account_post],
)
.write();
}
@@ -5,7 +5,9 @@ type Instruction = Vec<u8>;
/// A program that modifies the account data by setting bytes sent in instruction.
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: data,
},
@@ -6,7 +6,15 @@ use nssa_core::{
type Instruction = ();
fn main() {
let (ProgramInput { self_program_id, caller_program_id: _, pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let (
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
..
},
instruction_words,
) = read_nssa_inputs::<Instruction>();
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
@@ -10,12 +10,12 @@
//! In a real flash swap, this would contain the user's arbitrage or other logic.
//! In this test program, it is controlled by `return_funds`:
//!
//! - `return_funds = true`: emits a token transfer (receiver → vault) to return the funds.
//! The invariant check will pass and the transaction will succeed.
//! - `return_funds = true`: emits a token transfer (receiver → vault) to return the funds. The
//! invariant check will pass and the transaction will succeed.
//!
//! - `return_funds = false`: emits no transfers. Funds stay with the receiver.
//! The invariant check will fail (vault balance < initial), causing full atomic rollback.
//! This simulates a malicious or buggy callback that does not repay the flash loan.
//! - `return_funds = false`: emits no transfers. Funds stay with the receiver. The invariant check
//! will fail (vault balance < initial), causing full atomic rollback. This simulates a malicious
//! or buggy callback that does not repay the flash loan.
//!
//! # Note on caller_program_id
//!
@@ -16,18 +16,18 @@
//! 2. User callback (arbitrary logic, e.g. arbitrage)
//! 3. Self-call to `InvariantCheck` (using `self_program_id` to reference itself)
//!
//! - `InvariantCheck` (internal): enforces that the vault balance was restored after
//! the callback. Uses `caller_program_id == Some(self_program_id)` to prevent standalone
//! calls (this is the visibility enforcement mechanism).
//! - `InvariantCheck` (internal): enforces that the vault balance was restored after the callback.
//! Uses `caller_program_id == Some(self_program_id)` to prevent standalone calls (this is the
//! visibility enforcement mechanism).
//!
//! # What this demonstrates
//!
//! - `self_program_id`: enables a program to chain back to itself (step 3 above)
//! - `caller_program_id`: enables a program to restrict which callers can invoke an instruction
//! - Pre-simulated intermediate states: the initiator must compute expected intermediate
//! account states and embed them in the instruction. The node validates them deterministically.
//! - Atomic rollback: if the callback doesn't return funds, the invariant check fails,
//! and all state changes from steps 1 and 2 are rolled back automatically.
//! - Pre-simulated intermediate states: the initiator must compute expected intermediate account
//! states and embed them in the instruction. The node validates them deterministically.
//! - Atomic rollback: if the callback doesn't return funds, the invariant check fails, and all
//! state changes from steps 1 and 2 are rolled back automatically.
//!
//! # Tests
//!
@@ -132,8 +132,9 @@ fn main() {
// Chained call 3: Self-call to enforce the invariant.
// Uses `self_program_id` to reference this program, the key feature that enables
// the "prep → callback → assert" pattern without a separate checker program.
// If the callback did not return funds, vault_after_callback.balance < min_vault_balance
// and this call will panic, rolling back the entire transaction.
// If the callback did not return funds, vault_after_callback.balance <
// min_vault_balance and this call will panic, rolling back the entire
// transaction.
let invariant_instruction =
risc0_zkvm::serde::to_vec(&FlashSwapInstruction::InvariantCheck {
min_vault_balance,
@@ -13,7 +13,9 @@ type Instruction = (u128, ProgramId);
/// but sets the `is_authorized` field of the first account to true.
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (balance, transfer_program_id),
},
+9 -1
View File
@@ -3,7 +3,15 @@ use nssa_core::program::{AccountPostState, ProgramInput, ProgramOutput, read_nss
type Instruction = ();
fn main() {
let (ProgramInput { self_program_id, caller_program_id: _, pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let (
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
..
},
instruction_words,
) = read_nssa_inputs::<Instruction>();
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
@@ -3,7 +3,15 @@ use nssa_core::program::{AccountPostState, ProgramInput, ProgramOutput, read_nss
type Instruction = ();
fn main() {
let (ProgramInput { self_program_id, caller_program_id: _, pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let (
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
..
},
instruction_words,
) = read_nssa_inputs::<Instruction>();
let Ok([pre1, pre2]) = <[_; 2]>::try_from(pre_states) else {
return;
@@ -63,7 +63,9 @@ fn transfer(
fn main() {
// Read input accounts.
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: balance_to_move,
},
@@ -3,7 +3,15 @@ use nssa_core::program::{AccountPostState, ProgramInput, ProgramOutput, read_nss
type Instruction = ();
fn main() {
let (ProgramInput { self_program_id, caller_program_id: _, pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let (
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
..
},
instruction_words,
) = read_nssa_inputs::<Instruction>();
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
+9 -1
View File
@@ -3,7 +3,15 @@ use nssa_core::program::{AccountPostState, ProgramInput, ProgramOutput, read_nss
type Instruction = ();
fn main() {
let (ProgramInput { self_program_id, caller_program_id: _, pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let (
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
..
},
instruction_words,
) = read_nssa_inputs::<Instruction>();
let post_states = pre_states
.iter()
@@ -3,7 +3,15 @@ use nssa_core::program::{AccountPostState, ProgramInput, ProgramOutput, read_nss
type Instruction = ();
fn main() {
let (ProgramInput { self_program_id, caller_program_id: _, pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let (
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
..
},
instruction_words,
) = read_nssa_inputs::<Instruction>();
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
@@ -4,7 +4,9 @@ type Instruction = u128;
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: balance,
},
@@ -7,7 +7,9 @@ type Instruction = (BlockValidityWindow, TimestampValidityWindow);
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (block_validity_window, timestamp_validity_window),
},
@@ -15,7 +15,9 @@ type Instruction = (BlockValidityWindow, ProgramId, BlockValidityWindow);
fn main() {
let (
ProgramInput { self_program_id, caller_program_id: _,
ProgramInput {
self_program_id,
caller_program_id: _,
pre_states,
instruction: (block_validity_window, chained_program_id, chained_block_validity_window),
},