mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-03-26 12:13:08 +00:00
initialize branch
This commit is contained in:
parent
767b5afd38
commit
d58df166e7
@ -2,6 +2,15 @@ use std::io;
|
|||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! ensure {
|
||||||
|
($cond:expr, $err:expr) => {
|
||||||
|
if !$cond {
|
||||||
|
return Err($err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum NssaError {
|
pub enum NssaError {
|
||||||
#[error("Invalid input: {0}")]
|
#[error("Invalid input: {0}")]
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use nssa_core::{
|
|||||||
use sha2::{Digest, digest::FixedOutput};
|
use sha2::{Digest, digest::FixedOutput};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
V02State,
|
V02State, ensure,
|
||||||
error::NssaError,
|
error::NssaError,
|
||||||
public_transaction::{Message, WitnessSet},
|
public_transaction::{Message, WitnessSet},
|
||||||
state::MAX_NUMBER_CHAINED_CALLS,
|
state::MAX_NUMBER_CHAINED_CALLS,
|
||||||
@ -60,33 +60,33 @@ impl PublicTransaction {
|
|||||||
let witness_set = self.witness_set();
|
let witness_set = self.witness_set();
|
||||||
|
|
||||||
// All account_ids must be different
|
// All account_ids must be different
|
||||||
if message.account_ids.iter().collect::<HashSet<_>>().len() != message.account_ids.len() {
|
ensure!(
|
||||||
return Err(NssaError::InvalidInput(
|
message.account_ids.iter().collect::<HashSet<_>>().len() == message.account_ids.len(),
|
||||||
"Duplicate account_ids found in message".into(),
|
NssaError::InvalidInput("Duplicate account_ids found in message".into(),)
|
||||||
));
|
);
|
||||||
}
|
|
||||||
|
|
||||||
// Check exactly one nonce is provided for each signature
|
// Check exactly one nonce is provided for each signature
|
||||||
if message.nonces.len() != witness_set.signatures_and_public_keys.len() {
|
ensure!(
|
||||||
return Err(NssaError::InvalidInput(
|
message.nonces.len() == witness_set.signatures_and_public_keys.len(),
|
||||||
|
NssaError::InvalidInput(
|
||||||
"Mismatch between number of nonces and signatures/public keys".into(),
|
"Mismatch between number of nonces and signatures/public keys".into(),
|
||||||
));
|
)
|
||||||
}
|
);
|
||||||
|
|
||||||
// Check the signatures are valid
|
// Check the signatures are valid
|
||||||
if !witness_set.is_valid_for(message) {
|
ensure!(
|
||||||
return Err(NssaError::InvalidInput(
|
witness_set.is_valid_for(message),
|
||||||
"Invalid signature for given message and public key".into(),
|
NssaError::InvalidInput("Invalid signature for given message and public key".into())
|
||||||
));
|
);
|
||||||
}
|
|
||||||
|
|
||||||
let signer_account_ids = self.signer_account_ids();
|
let signer_account_ids = self.signer_account_ids();
|
||||||
// Check nonces corresponds to the current nonces on the public state.
|
// Check nonces corresponds to the current nonces on the public state.
|
||||||
for (account_id, nonce) in signer_account_ids.iter().zip(&message.nonces) {
|
for (account_id, nonce) in signer_account_ids.iter().zip(&message.nonces) {
|
||||||
let current_nonce = state.get_account_by_id(*account_id).nonce;
|
let current_nonce = state.get_account_by_id(*account_id).nonce;
|
||||||
if current_nonce != *nonce {
|
ensure!(
|
||||||
return Err(NssaError::InvalidInput("Nonce mismatch".into()));
|
current_nonce == *nonce,
|
||||||
}
|
NssaError::InvalidInput("Nonce mismatch".into())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build pre_states for execution
|
// Build pre_states for execution
|
||||||
@ -115,9 +115,10 @@ impl PublicTransaction {
|
|||||||
let mut chain_calls_counter = 0;
|
let mut chain_calls_counter = 0;
|
||||||
|
|
||||||
while let Some((chained_call, caller_program_id)) = chained_calls.pop_front() {
|
while let Some((chained_call, caller_program_id)) = chained_calls.pop_front() {
|
||||||
if chain_calls_counter > MAX_NUMBER_CHAINED_CALLS {
|
ensure!(
|
||||||
return Err(NssaError::MaxChainedCallsDepthExceeded);
|
chain_calls_counter <= MAX_NUMBER_CHAINED_CALLS,
|
||||||
}
|
NssaError::MaxChainedCallsDepthExceeded
|
||||||
|
);
|
||||||
|
|
||||||
// Check that the `program_id` corresponds to a deployed program
|
// Check that the `program_id` corresponds to a deployed program
|
||||||
let Some(program) = state.programs().get(&chained_call.program_id) else {
|
let Some(program) = state.programs().get(&chained_call.program_id) else {
|
||||||
@ -148,28 +149,31 @@ impl PublicTransaction {
|
|||||||
.get(&account_id)
|
.get(&account_id)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_else(|| state.get_account_by_id(account_id));
|
.unwrap_or_else(|| state.get_account_by_id(account_id));
|
||||||
if pre.account != expected_pre {
|
ensure!(
|
||||||
return Err(NssaError::InvalidProgramBehavior);
|
pre.account == expected_pre,
|
||||||
}
|
NssaError::InvalidProgramBehavior
|
||||||
|
);
|
||||||
|
|
||||||
// Check that authorization flags are consistent with the provided ones or
|
// Check that authorization flags are consistent with the provided ones or
|
||||||
// authorized by program through the PDA mechanism
|
// authorized by program through the PDA mechanism
|
||||||
let is_authorized = signer_account_ids.contains(&account_id)
|
let is_authorized = signer_account_ids.contains(&account_id)
|
||||||
|| authorized_pdas.contains(&account_id);
|
|| authorized_pdas.contains(&account_id);
|
||||||
if pre.is_authorized != is_authorized {
|
ensure!(
|
||||||
return Err(NssaError::InvalidProgramBehavior);
|
pre.is_authorized == is_authorized,
|
||||||
}
|
NssaError::InvalidProgramBehavior
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify execution corresponds to a well-behaved program.
|
// Verify execution corresponds to a well-behaved program.
|
||||||
// See the # Programs section for the definition of the `validate_execution` method.
|
// See the # Programs section for the definition of the `validate_execution` method.
|
||||||
if !validate_execution(
|
ensure!(
|
||||||
&program_output.pre_states,
|
validate_execution(
|
||||||
&program_output.post_states,
|
&program_output.pre_states,
|
||||||
chained_call.program_id,
|
&program_output.post_states,
|
||||||
) {
|
chained_call.program_id,
|
||||||
return Err(NssaError::InvalidProgramBehavior);
|
),
|
||||||
}
|
NssaError::InvalidProgramBehavior
|
||||||
|
);
|
||||||
|
|
||||||
for post in program_output
|
for post in program_output
|
||||||
.post_states
|
.post_states
|
||||||
@ -211,9 +215,10 @@ impl PublicTransaction {
|
|||||||
}
|
}
|
||||||
Some(post)
|
Some(post)
|
||||||
}) {
|
}) {
|
||||||
if post.program_owner == DEFAULT_PROGRAM_ID {
|
ensure!(
|
||||||
return Err(NssaError::InvalidProgramBehavior);
|
post.program_owner != DEFAULT_PROGRAM_ID,
|
||||||
}
|
NssaError::InvalidProgramBehavior
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(state_diff)
|
Ok(state_diff)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user