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