fix: refactor of sequencer to return errors immediately

This commit is contained in:
Oleksandr Pravdyvyi 2025-01-22 12:26:19 +02:00
parent b240f8e2fe
commit 02bdfe4ce0
9 changed files with 88 additions and 25 deletions

1
Cargo.lock generated
View File

@ -2683,6 +2683,7 @@ dependencies = [
"rand 0.8.5", "rand 0.8.5",
"reqwest 0.11.27", "reqwest 0.11.27",
"risc0-zkvm", "risc0-zkvm",
"rpc_primitives",
"secp256k1-zkp", "secp256k1-zkp",
"serde", "serde",
"serde_json", "serde_json",

View File

@ -35,6 +35,9 @@ path = "../utxo"
[dependencies.zkvm] [dependencies.zkvm]
path = "../zkvm" path = "../zkvm"
[dependencies.rpc_primitives]
path = "../rpc_primitives"
[dependencies.secp256k1-zkp] [dependencies.secp256k1-zkp]
workspace = true workspace = true
features = ["std", "rand-std", "rand", "serde", "global-context"] features = ["std", "rand-std", "rand", "serde", "global-context"]

View File

@ -1,3 +1,4 @@
use rpc_primitives::errors::RpcError;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use storage::{block::Block, transaction::Transaction}; use storage::{block::Block, transaction::Transaction};
@ -74,3 +75,10 @@ pub struct SequencerRpcResponse {
pub result: serde_json::Value, pub result: serde_json::Value,
pub id: u64, pub id: u64,
} }
#[derive(Debug, Clone, Deserialize)]
pub struct SequencerRpcError {
pub jsonrpc: String,
pub error: RpcError,
pub id: u64,
}

View File

@ -3,7 +3,7 @@ use anyhow::Result;
use json::{ use json::{
GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse, GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse,
RegisterAccountRequest, RegisterAccountResponse, SendTxRequest, SendTxResponse, RegisterAccountRequest, RegisterAccountResponse, SendTxRequest, SendTxResponse,
SequencerRpcRequest, SequencerRpcResponse, SequencerRpcError, SequencerRpcRequest, SequencerRpcResponse,
}; };
use k256::elliptic_curve::group::GroupEncoding; use k256::elliptic_curve::group::GroupEncoding;
use reqwest::Client; use reqwest::Client;
@ -26,6 +26,8 @@ pub enum SequencerClientError {
HTTPError(reqwest::Error), HTTPError(reqwest::Error),
#[error("Serde error")] #[error("Serde error")]
SerdeError(serde_json::Error), SerdeError(serde_json::Error),
#[error("Internal error")]
InternalError(SequencerRpcError),
} }
impl From<reqwest::Error> for SequencerClientError { impl From<reqwest::Error> for SequencerClientError {
@ -40,6 +42,12 @@ impl From<serde_json::Error> for SequencerClientError {
} }
} }
impl From<SequencerRpcError> for SequencerClientError {
fn from(value: SequencerRpcError) -> Self {
SequencerClientError::InternalError(value)
}
}
impl SequencerClient { impl SequencerClient {
pub fn new(config: NodeConfig) -> Result<Self> { pub fn new(config: NodeConfig) -> Result<Self> {
Ok(Self { Ok(Self {
@ -62,9 +70,16 @@ impl SequencerClient {
let call_res = call_builder.json(&request).send().await?; let call_res = call_builder.json(&request).send().await?;
let response = call_res.json::<SequencerRpcResponse>().await?; let response_vall = call_res.json::<Value>().await?;
Ok(response.result) if let Ok(response) = serde_json::from_value::<SequencerRpcResponse>(response_vall.clone())
{
Ok(response.result)
} else {
let err_resp = serde_json::from_value::<SequencerRpcError>(response_vall)?;
Err(err_resp.into())
}
} }
pub async fn get_block( pub async fn get_block(

View File

@ -43,8 +43,7 @@ impl JsonHandler {
let message_inner = self let message_inner = self
.process_request_internal(request) .process_request_internal(request)
.await .await
.map_err(|e| e.0) .map_err(|e| e.0);
.map_err(rpc_error_responce_inverter);
Ok(Message::response(id, message_inner)) Ok(Message::response(id, message_inner))
} else { } else {
Ok(Message::error(RpcError::parse_error( Ok(Message::error(RpcError::parse_error(

View File

@ -53,5 +53,9 @@ pub fn cast_seq_client_error_into_rpc_error(seq_cli_err: SequencerClientError) -
match seq_cli_err { match seq_cli_err {
SequencerClientError::SerdeError(_) => RpcError::serialization_error(&error_string), SequencerClientError::SerdeError(_) => RpcError::serialization_error(&error_string),
SequencerClientError::HTTPError(_) => RpcError::new_internal_error(None, &error_string), SequencerClientError::HTTPError(_) => RpcError::new_internal_error(None, &error_string),
SequencerClientError::InternalError(err) => RpcError::new_internal_error(
err.error.data,
&serde_json::to_string(&err.error.error_struct).unwrap_or(String::default()),
),
} }
} }

View File

@ -57,9 +57,9 @@ impl SequencerCore {
} }
} }
fn execute_check_transaction_on_state( pub fn transaction_pre_check(
&mut self, &mut self,
tx: TransactionMempool, tx: &Transaction,
) -> Result<(), TransactionMalformationErrorKind> { ) -> Result<(), TransactionMalformationErrorKind> {
let Transaction { let Transaction {
hash, hash,
@ -69,7 +69,7 @@ impl SequencerCore {
ref utxo_commitments_created_hashes, ref utxo_commitments_created_hashes,
ref nullifier_created_hashes, ref nullifier_created_hashes,
.. ..
} = tx.tx; } = tx;
//Sanity check //Sanity check
match tx_kind { match tx_kind {
@ -80,7 +80,7 @@ impl SequencerCore {
//Public transactions can not make private operations. //Public transactions can not make private operations.
return Err( return Err(
TransactionMalformationErrorKind::PublicTransactionChangedPrivateData { TransactionMalformationErrorKind::PublicTransactionChangedPrivateData {
tx: hash, tx: *hash,
}, },
); );
} }
@ -92,7 +92,7 @@ impl SequencerCore {
//between public and private state. //between public and private state.
return Err( return Err(
TransactionMalformationErrorKind::PrivateTransactionChangedPublicData { TransactionMalformationErrorKind::PrivateTransactionChangedPublicData {
tx: hash, tx: *hash,
}, },
); );
} }
@ -101,7 +101,7 @@ impl SequencerCore {
}; };
//Tree checks //Tree checks
let tx_tree_check = self.store.pub_tx_store.get_tx(hash).is_some(); let tx_tree_check = self.store.pub_tx_store.get_tx(*hash).is_some();
let nullifier_tree_check = nullifier_created_hashes let nullifier_tree_check = nullifier_created_hashes
.iter() .iter()
.map(|nullifier_hash| { .map(|nullifier_hash| {
@ -122,21 +122,46 @@ impl SequencerCore {
.any(|check| check); .any(|check| check);
if tx_tree_check { if tx_tree_check {
return Err(TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: hash }); return Err(TransactionMalformationErrorKind::TxHashAlreadyPresentInTree { tx: *hash });
} }
if nullifier_tree_check { if nullifier_tree_check {
return Err( return Err(
TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: hash }, TransactionMalformationErrorKind::NullifierAlreadyPresentInTree { tx: *hash },
); );
} }
if utxo_commitments_check { if utxo_commitments_check {
return Err( return Err(
TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree { tx: hash }, TransactionMalformationErrorKind::UTXOCommitmentAlreadyPresentInTree { tx: *hash },
); );
} }
Ok(())
}
pub fn push_tx_into_mempool_pre_check(
&mut self,
item: TransactionMempool,
) -> Result<(), TransactionMalformationErrorKind> {
self.transaction_pre_check(&item.tx)?;
self.mempool.push_item(item);
Ok(())
}
fn execute_check_transaction_on_state(
&mut self,
tx: TransactionMempool,
) -> Result<(), TransactionMalformationErrorKind> {
let Transaction {
hash,
ref utxo_commitments_created_hashes,
ref nullifier_created_hashes,
..
} = tx.tx;
for utxo_comm in utxo_commitments_created_hashes { for utxo_comm in utxo_commitments_created_hashes {
self.store self.store
.utxo_commitments_store .utxo_commitments_store

View File

@ -1,5 +1,7 @@
use actix_web::Error as HttpError; use actix_web::Error as HttpError;
use sequencer_core::sequecer_store::accounts_store::AccountPublicData; use sequencer_core::{
sequecer_store::accounts_store::AccountPublicData, TransactionMalformationErrorKind,
};
use serde_json::Value; use serde_json::Value;
use rpc_primitives::{ use rpc_primitives::{
@ -8,13 +10,10 @@ use rpc_primitives::{
parser::RpcRequest, parser::RpcRequest,
}; };
use crate::{ use crate::types::rpc_structs::{
rpc_error_responce_inverter, GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse,
types::rpc_structs::{ GetLastBlockRequest, GetLastBlockResponse, HelloRequest, HelloResponse, RegisterAccountRequest,
GetBlockDataRequest, GetBlockDataResponse, GetGenesisIdRequest, GetGenesisIdResponse, RegisterAccountResponse, SendTxRequest, SendTxResponse,
GetLastBlockRequest, GetLastBlockResponse, HelloRequest, HelloResponse,
RegisterAccountRequest, RegisterAccountResponse, SendTxRequest, SendTxResponse,
},
}; };
use super::{respond, types::err_rpc::RpcErr, JsonHandler}; use super::{respond, types::err_rpc::RpcErr, JsonHandler};
@ -26,8 +25,7 @@ impl JsonHandler {
let message_inner = self let message_inner = self
.process_request_internal(request) .process_request_internal(request)
.await .await
.map_err(|e| e.0) .map_err(|e| e.0);
.map_err(rpc_error_responce_inverter);
Ok(Message::response(id, message_inner)) Ok(Message::response(id, message_inner))
} else { } else {
Ok(Message::error(RpcError::parse_error( Ok(Message::error(RpcError::parse_error(
@ -74,7 +72,7 @@ impl JsonHandler {
{ {
let mut state = self.sequencer_state.lock().await; let mut state = self.sequencer_state.lock().await;
state.mempool.push_item(send_tx_req.transaction); state.push_tx_into_mempool_pre_check(send_tx_req.transaction)?;
} }
let helperstruct = SendTxResponse { let helperstruct = SendTxResponse {

View File

@ -1,6 +1,7 @@
use log::debug; use log::debug;
use rpc_primitives::errors::{RpcError, RpcParseError}; use rpc_primitives::errors::{RpcError, RpcParseError};
use sequencer_core::TransactionMalformationErrorKind;
pub struct RpcErr(pub RpcError); pub struct RpcErr(pub RpcError);
@ -40,6 +41,15 @@ impl RpcErrKind for RpcErrInternal {
} }
} }
impl RpcErrKind for TransactionMalformationErrorKind {
fn into_rpc_err(self) -> RpcError {
RpcError::new_internal_error(
Some(serde_json::to_value(self).unwrap()),
"transaction not accepted",
)
}
}
#[allow(clippy::needless_pass_by_value)] #[allow(clippy::needless_pass_by_value)]
pub fn from_rpc_err_into_anyhow_err(rpc_err: RpcError) -> anyhow::Error { pub fn from_rpc_err_into_anyhow_err(rpc_err: RpcError) -> anyhow::Error {
debug!("Rpc error cast to anyhow error : err {rpc_err:?}"); debug!("Rpc error cast to anyhow error : err {rpc_err:?}");