mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-02 13:23:10 +00:00
add max depth reached error for chained calls
This commit is contained in:
parent
a94440fa1f
commit
c7b415b2f4
@ -54,4 +54,7 @@ pub enum NssaError {
|
||||
|
||||
#[error("Program already exists")]
|
||||
ProgramAlreadyExists,
|
||||
|
||||
#[error("Chain of calls too long")]
|
||||
MaxChainedCallsDepthExceeded,
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ use crate::{
|
||||
V02State,
|
||||
error::NssaError,
|
||||
public_transaction::{Message, WitnessSet},
|
||||
state::MAX_NUMBER_CHAINED_CALLS,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -18,7 +19,6 @@ pub struct PublicTransaction {
|
||||
message: Message,
|
||||
witness_set: WitnessSet,
|
||||
}
|
||||
const MAX_NUMBER_CHAINED_CALLS: usize = 10;
|
||||
|
||||
impl PublicTransaction {
|
||||
pub fn new(message: Message, witness_set: WitnessSet) -> Self {
|
||||
@ -183,7 +183,11 @@ impl PublicTransaction {
|
||||
};
|
||||
}
|
||||
|
||||
Ok(state_diff)
|
||||
if chained_calls.is_empty() {
|
||||
Ok(state_diff)
|
||||
} else {
|
||||
Err(NssaError::MaxChainedCallsDepthExceeded)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,8 @@ use nssa_core::{
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub const MAX_NUMBER_CHAINED_CALLS: usize = 10;
|
||||
|
||||
pub(crate) struct CommitmentSet {
|
||||
merkle_tree: MerkleTree,
|
||||
commitments: HashMap<Commitment, usize>,
|
||||
@ -251,6 +253,7 @@ pub mod tests {
|
||||
program::Program,
|
||||
public_transaction,
|
||||
signature::PrivateKey,
|
||||
state::MAX_NUMBER_CHAINED_CALLS,
|
||||
};
|
||||
|
||||
use nssa_core::{
|
||||
@ -2079,7 +2082,7 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chained_call() {
|
||||
fn test_chained_call_succeeds() {
|
||||
let program = Program::chain_caller();
|
||||
let key = PrivateKey::try_new([1; 32]).unwrap();
|
||||
let address = Address::from(&PublicKey::new_from_private_key(&key));
|
||||
@ -2091,8 +2094,8 @@ pub mod tests {
|
||||
let from_key = key;
|
||||
let to = Address::new([2; 32]);
|
||||
let amount: u128 = 37;
|
||||
let instruction: (u128, ProgramId) =
|
||||
(amount, Program::authenticated_transfer_program().id());
|
||||
let instruction: (u128, ProgramId, u32) =
|
||||
(amount, Program::authenticated_transfer_program().id(), 2);
|
||||
|
||||
let expected_to_post = Account {
|
||||
program_owner: Program::chain_caller().id(),
|
||||
@ -2118,4 +2121,40 @@ pub mod tests {
|
||||
assert_eq!(from_post.balance, initial_balance - 2 * amount);
|
||||
assert_eq!(to_post, expected_to_post);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execution_fails_if_chained_calls_exceeds_depth() {
|
||||
let program = Program::chain_caller();
|
||||
let key = PrivateKey::try_new([1; 32]).unwrap();
|
||||
let address = Address::from(&PublicKey::new_from_private_key(&key));
|
||||
let initial_balance = 100;
|
||||
let initial_data = [(address, initial_balance)];
|
||||
let mut state =
|
||||
V02State::new_with_genesis_accounts(&initial_data, &[]).with_test_programs();
|
||||
let from = address;
|
||||
let from_key = key;
|
||||
let to = Address::new([2; 32]);
|
||||
let amount: u128 = 0;
|
||||
let instruction: (u128, ProgramId, u32) = (
|
||||
amount,
|
||||
Program::authenticated_transfer_program().id(),
|
||||
MAX_NUMBER_CHAINED_CALLS as u32 + 1,
|
||||
);
|
||||
|
||||
let message = public_transaction::Message::try_new(
|
||||
program.id(),
|
||||
vec![to, from], //The chain_caller program permutes the account order in the chain call
|
||||
vec![0],
|
||||
instruction,
|
||||
)
|
||||
.unwrap();
|
||||
let witness_set = public_transaction::WitnessSet::for_message(&message, &[&from_key]);
|
||||
let tx = PublicTransaction::new(message, witness_set);
|
||||
|
||||
let result = state.transition_from_public_transaction(&tx);
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(NssaError::MaxChainedCallsDepthExceeded)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,14 +3,14 @@ use nssa_core::program::{
|
||||
};
|
||||
use risc0_zkvm::serde::to_vec;
|
||||
|
||||
type Instruction = (u128, ProgramId);
|
||||
type Instruction = (u128, ProgramId, u32);
|
||||
|
||||
/// A program that calls another program twice.
|
||||
/// A program that calls another program `num_chain_calls` times.
|
||||
/// It permutes the order of the input accounts on the subsequent call
|
||||
fn main() {
|
||||
let ProgramInput {
|
||||
pre_states,
|
||||
instruction: (balance, program_id),
|
||||
instruction: (balance, program_id, num_chain_calls),
|
||||
} = read_nssa_inputs::<Instruction>();
|
||||
|
||||
let [sender_pre, receiver_pre] = match pre_states.try_into() {
|
||||
@ -20,19 +20,21 @@ fn main() {
|
||||
|
||||
let instruction_data = to_vec(&balance).unwrap();
|
||||
|
||||
let chained_call = vec![
|
||||
let mut chained_call = vec![
|
||||
ChainedCall {
|
||||
program_id,
|
||||
instruction_data: instruction_data.clone(),
|
||||
account_indices: vec![0, 1],
|
||||
},
|
||||
ChainedCall {
|
||||
program_id,
|
||||
instruction_data,
|
||||
account_indices: vec![1, 0], // <- Account order permutation here
|
||||
},
|
||||
};
|
||||
num_chain_calls as usize - 1
|
||||
];
|
||||
|
||||
chained_call.push(ChainedCall {
|
||||
program_id,
|
||||
instruction_data,
|
||||
account_indices: vec![1, 0], // <- Account order permutation here
|
||||
});
|
||||
|
||||
write_nssa_outputs_with_chained_call(
|
||||
vec![sender_pre.clone(), receiver_pre.clone()],
|
||||
vec![sender_pre.account, receiver_pre.account],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user