This commit is contained in:
Sergio Chouhy 2026-03-28 03:54:57 -03:00
parent 5634cc3654
commit 6f380f1e74
9 changed files with 69 additions and 49 deletions

View File

@ -1,9 +1,8 @@
use borsh::{BorshDeserialize, BorshSerialize};
use nssa_core::{BlockId, Timestamp};
use serde::{Deserialize, Serialize};
use sha2::{Digest as _, Sha256, digest::FixedOutput as _};
use nssa_core::{BlockId, Timestamp};
use crate::{HashType, transaction::NSSATransaction};
pub type MantleMsgId = [u8; 32];

View File

@ -73,9 +73,7 @@ impl NSSATransaction {
timestamp: Timestamp,
) -> Result<Self, nssa::error::NssaError> {
match &self {
Self::Public(tx) => {
state.transition_from_public_transaction(tx, block_id, timestamp)
}
Self::Public(tx) => state.transition_from_public_transaction(tx, block_id, timestamp),
Self::PrivacyPreserving(tx) => {
state.transition_from_privacy_preserving_transaction(tx, block_id, timestamp)
}

View File

@ -6,8 +6,8 @@ use common::{
block::{BedrockStatus, Block},
transaction::NSSATransaction,
};
use nssa_core::BlockId;
use nssa::{Account, AccountId, V03State};
use nssa_core::BlockId;
use storage::indexer::RocksDBIO;
use tokio::sync::RwLock;

View File

@ -183,8 +183,7 @@ impl<T: Copy + PartialOrd> ValidityWindow<T> {
/// Valid for values in the range [from, to), where `from` is included and `to` is excluded.
#[must_use]
pub fn is_valid_for(&self, value: T) -> bool {
self.from.is_none_or(|start| value >= start)
&& self.to.is_none_or(|end| value < end)
self.from.is_none_or(|start| value >= start) && self.to.is_none_or(|end| value < end)
}
/// Returns `Err(InvalidWindow)` if both bounds are set and `from >= to`.
@ -310,7 +309,9 @@ impl ProgramOutput {
/// Sets the block ID validity window from a fallible range conversion (`1..5`).
/// Returns `Err` if the range is empty.
pub fn try_with_block_validity_window<W: TryInto<BlockValidityWindow, Error = InvalidWindow>>(
pub fn try_with_block_validity_window<
W: TryInto<BlockValidityWindow, Error = InvalidWindow>,
>(
mut self,
window: W,
) -> Result<Self, InvalidWindow> {
@ -319,14 +320,19 @@ impl ProgramOutput {
}
/// Sets the timestamp validity window from an infallible range conversion.
pub fn with_timestamp_validity_window<W: Into<TimestampValidityWindow>>(mut self, window: W) -> Self {
pub fn with_timestamp_validity_window<W: Into<TimestampValidityWindow>>(
mut self,
window: W,
) -> Self {
self.timestamp_validity_window = window.into();
self
}
/// Sets the timestamp validity window from a fallible range conversion.
/// Returns `Err` if the range is empty.
pub fn try_with_timestamp_validity_window<W: TryInto<TimestampValidityWindow, Error = InvalidWindow>>(
pub fn try_with_timestamp_validity_window<
W: TryInto<TimestampValidityWindow, Error = InvalidWindow>,
>(
mut self,
window: W,
) -> Result<Self, InvalidWindow> {

View File

@ -196,7 +196,9 @@ impl PublicTransaction {
// Verify validity window
ensure!(
program_output.block_validity_window.is_valid_for(block_id)
&& program_output.timestamp_validity_window.is_valid_for(timestamp),
&& program_output
.timestamp_validity_window
.is_valid_for(timestamp),
NssaError::OutOfValidityWindow
);

View File

@ -3032,7 +3032,10 @@ pub mod tests {
let account_ids = vec![pre.account_id];
let nonces = vec![];
let program_id = validity_window_program.id();
let instruction = (block_validity_window, TimestampValidityWindow::new_unbounded());
let instruction = (
block_validity_window,
TimestampValidityWindow::new_unbounded(),
);
let message =
public_transaction::Message::try_new(program_id, account_ids, nonces, instruction)
.unwrap();
@ -3040,12 +3043,13 @@ pub mod tests {
PublicTransaction::new(message, witness_set)
};
let result = state.transition_from_public_transaction(&tx, block_id, 0);
let is_inside_validity_window = match (block_validity_window.start(), block_validity_window.end()) {
(Some(s), Some(e)) => s <= block_id && block_id < e,
(Some(s), None) => s <= block_id,
(None, Some(e)) => block_id < e,
(None, None) => true,
};
let is_inside_validity_window =
match (block_validity_window.start(), block_validity_window.end()) {
(Some(s), Some(e)) => s <= block_id && block_id < e,
(Some(s), None) => s <= block_id,
(None, Some(e)) => block_id < e,
(None, None) => true,
};
if is_inside_validity_window {
assert!(result.is_ok());
} else {
@ -3080,8 +3084,10 @@ pub mod tests {
let account_ids = vec![pre.account_id];
let nonces = vec![];
let program_id = validity_window_program.id();
let instruction =
(BlockValidityWindow::new_unbounded(), timestamp_validity_window);
let instruction = (
BlockValidityWindow::new_unbounded(),
timestamp_validity_window,
);
let message =
public_transaction::Message::try_new(program_id, account_ids, nonces, instruction)
.unwrap();
@ -3089,13 +3095,15 @@ pub mod tests {
PublicTransaction::new(message, witness_set)
};
let result = state.transition_from_public_transaction(&tx, 1, timestamp);
let is_inside_validity_window =
match (timestamp_validity_window.start(), timestamp_validity_window.end()) {
(Some(s), Some(e)) => s <= timestamp && timestamp < e,
(Some(s), None) => s <= timestamp,
(None, Some(e)) => timestamp < e,
(None, None) => true,
};
let is_inside_validity_window = match (
timestamp_validity_window.start(),
timestamp_validity_window.end(),
) {
(Some(s), Some(e)) => s <= timestamp && timestamp < e,
(Some(s), None) => s <= timestamp,
(None, Some(e)) => timestamp < e,
(None, None) => true,
};
if is_inside_validity_window {
assert!(result.is_ok());
} else {
@ -3130,7 +3138,10 @@ pub mod tests {
let shared_secret = SharedSecretKey::new(&esk, &account_keys.vpk());
let epk = EphemeralPublicKey::from_scalar(esk);
let instruction = (block_validity_window, TimestampValidityWindow::new_unbounded());
let instruction = (
block_validity_window,
TimestampValidityWindow::new_unbounded(),
);
let (output, proof) = circuit::execute_and_prove(
vec![pre],
Program::serialize_instruction(instruction).unwrap(),
@ -3196,8 +3207,10 @@ pub mod tests {
let shared_secret = SharedSecretKey::new(&esk, &account_keys.vpk());
let epk = EphemeralPublicKey::from_scalar(esk);
let instruction =
(BlockValidityWindow::new_unbounded(), timestamp_validity_window);
let instruction = (
BlockValidityWindow::new_unbounded(),
timestamp_validity_window,
);
let (output, proof) = circuit::execute_and_prove(
vec![pre],
Program::serialize_instruction(instruction).unwrap(),
@ -3221,13 +3234,15 @@ pub mod tests {
PrivacyPreservingTransaction::new(message, witness_set)
};
let result = state.transition_from_privacy_preserving_transaction(&tx, 1, timestamp);
let is_inside_validity_window =
match (timestamp_validity_window.start(), timestamp_validity_window.end()) {
(Some(s), Some(e)) => s <= timestamp && timestamp < e,
(Some(s), None) => s <= timestamp,
(None, Some(e)) => timestamp < e,
(None, None) => true,
};
let is_inside_validity_window = match (
timestamp_validity_window.start(),
timestamp_validity_window.end(),
) {
(Some(s), Some(e)) => s <= timestamp && timestamp < e,
(Some(s), None) => s <= timestamp,
(None, Some(e)) => timestamp < e,
(None, None) => true,
};
if is_inside_validity_window {
assert!(result.is_ok());
} else {

View File

@ -170,10 +170,9 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
timestamp: Timestamp,
) -> Result<NSSATransaction, nssa::error::NssaError> {
match &tx {
NSSATransaction::Public(tx) => {
self.state
.transition_from_public_transaction(tx, block_id, timestamp)
}
NSSATransaction::Public(tx) => self
.state
.transition_from_public_transaction(tx, block_id, timestamp),
NSSATransaction::PrivacyPreserving(tx) => self
.state
.transition_from_privacy_preserving_transaction(tx, block_id, timestamp),
@ -253,7 +252,8 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
break;
}
match self.execute_check_transaction_on_state(tx, new_block_height, new_block_timestamp) {
match self.execute_check_transaction_on_state(tx, new_block_height, new_block_timestamp)
{
Ok(valid_tx) => {
valid_transactions.push(valid_tx);

View File

@ -1,9 +1,5 @@
//! Reexports of types used by sequencer rpc specification.
pub use common::{
HashType,
block::Block,
transaction::NSSATransaction,
};
pub use common::{HashType, block::Block, transaction::NSSATransaction};
pub use nssa::{Account, AccountId, ProgramId};
pub use nssa_core::{BlockId, Commitment, MembershipProof, account::Nonce};

View File

@ -188,7 +188,11 @@ impl RocksDBIO {
"transaction pre check failed with err {err:?}"
))
})?
.execute_check_on_state(&mut breakpoint, block.header.block_id, block.header.timestamp)
.execute_check_on_state(
&mut breakpoint,
block.header.block_id,
block.header.timestamp,
)
.map_err(|err| {
DbError::db_interaction_error(format!(
"transaction execution failed with err {err:?}"