error handling for encoding

This commit is contained in:
Sergio Chouhy 2025-08-12 22:35:07 -03:00
parent 0dcdb2188a
commit 2d9896f6ed
7 changed files with 46 additions and 47 deletions

View File

@ -78,7 +78,7 @@ impl HashableBlockData {
let mut transactions = Vec::with_capacity(num_transactions); let mut transactions = Vec::with_capacity(num_transactions);
for _ in 0..num_transactions { for _ in 0..num_transactions {
let tx = nssa::PublicTransaction::from_cursor(&mut cursor); let tx = nssa::PublicTransaction::from_cursor(&mut cursor).unwrap();
transactions.push(tx); transactions.push(tx);
} }

View File

@ -1,3 +1,5 @@
use std::io;
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -16,4 +18,7 @@ pub enum NssaError {
#[error("Invalid private key")] #[error("Invalid private key")]
InvalidPrivateKey, InvalidPrivateKey,
#[error("IO error: {0}")]
Io(#[from] io::Error),
} }

View File

@ -4,6 +4,7 @@ use nssa_core::program::ProgramId;
use crate::{ use crate::{
Address, PublicKey, PublicTransaction, Signature, Address, PublicKey, PublicTransaction, Signature,
error::NssaError,
public_transaction::{Message, WitnessSet}, public_transaction::{Message, WitnessSet},
}; };
@ -45,46 +46,46 @@ impl Message {
bytes bytes
} }
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self { pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
let prefix = { let prefix = {
let mut this = [0u8; MESSAGE_ENCODING_PREFIX_LEN]; let mut this = [0u8; MESSAGE_ENCODING_PREFIX_LEN];
cursor.read_exact(&mut this).unwrap(); cursor.read_exact(&mut this)?;
this this
}; };
assert_eq!(&prefix, MESSAGE_ENCODING_PREFIX); assert_eq!(&prefix, MESSAGE_ENCODING_PREFIX);
let program_id: ProgramId = { let program_id: ProgramId = {
let mut this = [0u32; 8]; let mut this = [0u32; 8];
for i in 0..8 { for i in 0..8 {
this[i] = u32_from_cursor(cursor); this[i] = u32_from_cursor(cursor)?;
} }
this this
}; };
let addresses_len = u32_from_cursor(cursor); let addresses_len = u32_from_cursor(cursor)?;
let mut addresses = Vec::with_capacity(addresses_len as usize); let mut addresses = Vec::with_capacity(addresses_len as usize);
for _ in 0..addresses_len { for _ in 0..addresses_len {
let mut value = [0u8; 32]; let mut value = [0u8; 32];
cursor.read_exact(&mut value).unwrap(); cursor.read_exact(&mut value)?;
addresses.push(Address::new(value)) addresses.push(Address::new(value))
} }
let nonces_len = u32_from_cursor(cursor); let nonces_len = u32_from_cursor(cursor)?;
let mut nonces = Vec::with_capacity(nonces_len as usize); let mut nonces = Vec::with_capacity(nonces_len as usize);
for _ in 0..nonces_len { for _ in 0..nonces_len {
let mut buf = [0u8; 16]; let mut buf = [0u8; 16];
cursor.read_exact(&mut buf).unwrap(); cursor.read_exact(&mut buf)?;
nonces.push(u128::from_le_bytes(buf)) nonces.push(u128::from_le_bytes(buf))
} }
let instruction_data_len = u32_from_cursor(cursor); let instruction_data_len = u32_from_cursor(cursor)?;
let mut instruction_data = Vec::with_capacity(instruction_data_len as usize); let mut instruction_data = Vec::with_capacity(instruction_data_len as usize);
for _ in 0..instruction_data_len { for _ in 0..instruction_data_len {
let word = u32_from_cursor(cursor); let word = u32_from_cursor(cursor)?;
instruction_data.push(word) instruction_data.push(word)
} }
Self { Ok(Self {
program_id, program_id,
addresses, addresses,
nonces, nonces,
instruction_data, instruction_data,
} })
} }
} }
@ -100,22 +101,21 @@ impl WitnessSet {
bytes bytes
} }
// TODO: remove unwraps and return Result pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self {
let num_signatures: u32 = { let num_signatures: u32 = {
let mut buf = [0u8; 4]; let mut buf = [0u8; 4];
cursor.read_exact(&mut buf).unwrap(); cursor.read_exact(&mut buf)?;
u32::from_le_bytes(buf) u32::from_le_bytes(buf)
}; };
let mut signatures_and_public_keys = Vec::with_capacity(num_signatures as usize); let mut signatures_and_public_keys = Vec::with_capacity(num_signatures as usize);
for _i in 0..num_signatures { for _i in 0..num_signatures {
let signature = Signature::from_cursor(cursor); let signature = Signature::from_cursor(cursor)?;
let public_key = PublicKey::from_cursor(cursor); let public_key = PublicKey::from_cursor(cursor)?;
signatures_and_public_keys.push((signature, public_key)) signatures_and_public_keys.push((signature, public_key))
} }
Self { Ok(Self {
signatures_and_public_keys, signatures_and_public_keys,
} })
} }
} }
@ -126,23 +126,23 @@ impl PublicTransaction {
bytes bytes
} }
pub fn from_bytes(bytes: &[u8]) -> Self { pub fn from_bytes(bytes: &[u8]) -> Result<Self, NssaError> {
let mut cursor = Cursor::new(bytes); let mut cursor = Cursor::new(bytes);
Self::from_cursor(&mut cursor) Ok(Self::from_cursor(&mut cursor)?)
} }
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self { pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
let message = Message::from_cursor(cursor); let message = Message::from_cursor(cursor)?;
let witness_set = WitnessSet::from_cursor(cursor); let witness_set = WitnessSet::from_cursor(cursor)?;
Self { Ok(Self {
message, message,
witness_set, witness_set,
} })
} }
} }
fn u32_from_cursor(cursor: &mut Cursor<&[u8]>) -> u32 { fn u32_from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<u32, NssaError> {
let mut word_buf = [0u8; 4]; let mut word_buf = [0u8; 4];
cursor.read_exact(&mut word_buf).unwrap(); cursor.read_exact(&mut word_buf)?;
u32::from_le_bytes(word_buf) Ok(u32::from_le_bytes(word_buf))
} }

View File

@ -128,7 +128,7 @@ mod tests {
}; };
#[test] #[test]
fn test_to_bytes() { fn test_public_transaction_encoding_bytes_roundtrip() {
let key1 = PrivateKey::try_new([1; 32]).unwrap(); let key1 = PrivateKey::try_new([1; 32]).unwrap();
let key2 = PrivateKey::try_new([2; 32]).unwrap(); let key2 = PrivateKey::try_new([2; 32]).unwrap();
let addr1 = Address::from_public_key(&PublicKey::new(&key1)); let addr1 = Address::from_public_key(&PublicKey::new(&key1));
@ -147,8 +147,7 @@ mod tests {
let tx = PublicTransaction::new(message, witness_set); let tx = PublicTransaction::new(message, witness_set);
let bytes = tx.to_bytes(); let bytes = tx.to_bytes();
let mut cursor: Cursor<&[u8]> = Cursor::new(&bytes); let tx_from_bytes = PublicTransaction::from_bytes(&bytes).unwrap();
let recov_tx = PublicTransaction::from_cursor(&mut cursor); assert_eq!(tx, tx_from_bytes);
assert_eq!(tx, recov_tx);
} }
} }

View File

@ -1,13 +1,12 @@
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};
use crate::{PublicKey, Signature}; use crate::{PublicKey, Signature, error::NssaError};
impl PublicKey { impl PublicKey {
// TODO: remove unwraps and return Result pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self {
let mut value = [0u8; 32]; let mut value = [0u8; 32];
cursor.read_exact(&mut value).unwrap(); cursor.read_exact(&mut value)?;
Self(value) Ok(Self(value))
} }
pub(crate) fn to_bytes(&self) -> &[u8] { pub(crate) fn to_bytes(&self) -> &[u8] {
@ -16,11 +15,10 @@ impl PublicKey {
} }
impl Signature { impl Signature {
// TODO: remove unwraps and return Result pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self {
let mut value = [0u8; 64]; let mut value = [0u8; 64];
cursor.read_exact(&mut value).unwrap(); cursor.read_exact(&mut value)?;
Self { value } Ok(Self { value })
} }
pub(crate) fn to_bytes(&self) -> &[u8] { pub(crate) fn to_bytes(&self) -> &[u8] {

View File

@ -102,13 +102,10 @@ impl SequencerCore {
.mempool .mempool
.pop_size(self.sequencer_config.max_num_tx_in_block); .pop_size(self.sequencer_config.max_num_tx_in_block);
println!("##");
println!("{:?}", transactions.len());
let valid_transactions: Vec<_> = transactions let valid_transactions: Vec<_> = transactions
.into_iter() .into_iter()
.filter_map(|tx| self.execute_check_transaction_on_state(tx).ok()) .filter_map(|tx| self.execute_check_transaction_on_state(tx).ok())
.collect(); .collect();
println!("{:?}", valid_transactions.len());
let prev_block_hash = self let prev_block_hash = self
.store .store

View File

@ -1,4 +1,3 @@
use actix_web::Error as HttpError; use actix_web::Error as HttpError;
use base64::{engine::general_purpose, Engine}; use base64::{engine::general_purpose, Engine};
use nssa; use nssa;
@ -71,7 +70,8 @@ impl JsonHandler {
async fn process_send_tx(&self, request: Request) -> Result<Value, RpcErr> { async fn process_send_tx(&self, request: Request) -> Result<Value, RpcErr> {
let send_tx_req = SendTxRequest::parse(Some(request.params))?; let send_tx_req = SendTxRequest::parse(Some(request.params))?;
let tx = nssa::PublicTransaction::from_bytes(&send_tx_req.transaction); let tx = nssa::PublicTransaction::from_bytes(&send_tx_req.transaction)
.map_err(|e| RpcError::serialization_error(&e.to_string()))?;
{ {
let mut state = self.sequencer_state.lock().await; let mut state = self.sequencer_state.lock().await;