mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-04-08 12:13:24 +00:00
fix: apply formatting and rebuild artifacts
This commit is contained in:
parent
88e3b368c3
commit
74e16db68f
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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.
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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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),
|
||||
},
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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),
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user