Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rpc): Move away from serde in RPC DTO's (in favor of our own [De]SerializeForVersion) #2392

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/executor/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ pub struct MsgToL1 {
pub from_address: Felt,
}

#[derive(Debug, Clone)]
#[derive(Default, Debug, Clone)]
pub struct InnerCallExecutionResources {
pub l1_gas: u128,
pub l2_gas: u128,
Expand Down
7 changes: 3 additions & 4 deletions crates/pathfinder/src/bin/pathfinder/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Examples:
default_value = "v07",
env = "PATHFINDER_RPC_ROOT_VERSION"
)]
rpc_root_version: RpcVersion,
rpc_root_version: RootRpcVersion,

#[arg(
long = "rpc.execution-concurrency",
Expand Down Expand Up @@ -334,8 +334,7 @@ impl Color {
}

#[derive(clap::ValueEnum, Debug, Clone, Copy, PartialEq)]
pub enum RpcVersion {
V06,
pub enum RootRpcVersion {
V07,
}

Expand Down Expand Up @@ -692,7 +691,7 @@ pub struct Config {
pub ethereum: Ethereum,
pub rpc_address: SocketAddr,
pub rpc_cors_domains: Option<AllowedOrigins>,
pub rpc_root_version: RpcVersion,
pub rpc_root_version: RootRpcVersion,
pub websocket: WebsocketConfig,
pub monitor_address: Option<SocketAddr>,
pub network: Option<NetworkConfig>,
Expand Down
3 changes: 1 addition & 2 deletions crates/pathfinder/src/bin/pathfinder/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,7 @@ Hint: This is usually caused by exceeding the file descriptor limit of your syst
};

let default_version = match config.rpc_root_version {
config::RpcVersion::V06 => pathfinder_rpc::RpcVersion::V06,
config::RpcVersion::V07 => pathfinder_rpc::RpcVersion::V07,
config::RootRpcVersion::V07 => pathfinder_rpc::RpcVersion::V07,
};

let rpc_server = pathfinder_rpc::RpcServer::new(config.rpc_address, context, default_version);
Expand Down
167 changes: 162 additions & 5 deletions crates/rpc/src/dto/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@ use pathfinder_common::{ContractAddress, ContractNonce};
use serde::ser::Error;

use super::serialize::SerializeStruct;
use super::FeeEstimate;
use crate::RpcVersion;

#[derive(Debug)]
pub struct TransactionTrace<'a> {
pub trace: &'a pathfinder_executor::types::TransactionTrace,
pub struct TransactionTrace {
pub trace: pathfinder_executor::types::TransactionTrace,
pub include_state_diff: bool,
}

impl crate::dto::serialize::SerializeForVersion for TransactionTrace<'_> {
impl crate::dto::serialize::SerializeForVersion for TransactionTrace {
fn serialize(
&self,
serializer: super::serialize::Serializer,
) -> Result<super::serialize::Ok, super::serialize::Error> {
let mut serializer = serializer.serialize_struct()?;
match self.trace {
match &self.trace {
pathfinder_executor::types::TransactionTrace::Declare(trace) => {
serializer.serialize_field("type", &"DECLARE")?;
if let Some(fee_transfer_invocation) = &trace.fee_transfer_invocation {
Expand Down Expand Up @@ -120,7 +121,7 @@ impl crate::dto::serialize::SerializeForVersion for TransactionTrace<'_> {
}

#[derive(Debug)]
struct FunctionInvocation<'a>(&'a pathfinder_executor::types::FunctionInvocation);
pub(crate) struct FunctionInvocation<'a>(&'a pathfinder_executor::types::FunctionInvocation);

impl crate::dto::serialize::SerializeForVersion for FunctionInvocation<'_> {
fn serialize(
Expand Down Expand Up @@ -519,3 +520,159 @@ impl crate::dto::serialize::SerializeForVersion for ExecuteInvocation<'_> {
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum CallType {
Call,
_LibraryCall,
Delegate,
}

impl From<pathfinder_executor::types::CallType> for CallType {
fn from(value: pathfinder_executor::types::CallType) -> Self {
use pathfinder_executor::types::CallType::*;
match value {
Call => Self::Call,
Delegate => Self::Delegate,
}
}
}

impl crate::dto::serialize::SerializeForVersion for CallType {
fn serialize(
&self,
serializer: super::serialize::Serializer,
) -> Result<super::serialize::Ok, super::serialize::Error> {
match self {
CallType::Call => serializer.serialize_str("CALL"),
CallType::_LibraryCall => serializer.serialize_str("LIBRARY_CALL"),
CallType::Delegate => serializer.serialize_str("DELEGATE"),
}
}
}

#[derive(Debug, Eq, PartialEq)]
pub struct SimulationFlags(pub Vec<SimulationFlag>);

#[derive(Debug, Eq, PartialEq)]
pub enum SimulationFlag {
SkipFeeCharge,
SkipValidate,
}

impl crate::dto::DeserializeForVersion for SimulationFlag {
fn deserialize(value: crate::dto::Value) -> Result<Self, serde_json::Error> {
let value: String = value.deserialize_serde()?;
match value.as_str() {
"SKIP_FEE_CHARGE" => Ok(Self::SkipFeeCharge),
"SKIP_VALIDATE" => Ok(Self::SkipValidate),
_ => Err(serde_json::Error::custom("Invalid simulation flag")),
}
}
}

impl crate::dto::DeserializeForVersion for SimulationFlags {
fn deserialize(value: crate::dto::Value) -> Result<Self, serde_json::Error> {
let array = value.deserialize_array(SimulationFlag::deserialize)?;
Ok(Self(array))
}
}

pub(crate) struct SimulatedTransaction(pub pathfinder_executor::types::TransactionSimulation);

impl crate::dto::serialize::SerializeForVersion for SimulatedTransaction {
fn serialize(
&self,
serializer: super::serialize::Serializer,
) -> Result<super::serialize::Ok, super::serialize::Error> {
let mut serializer = serializer.serialize_struct()?;
serializer.serialize_field("fee_estimation", &FeeEstimate(&self.0.fee_estimation))?;
serializer.serialize_field(
"transaction_trace",
&TransactionTrace {
trace: self.0.trace.clone(),
include_state_diff: false,
},
)?;
serializer.end()
}
}

#[cfg(test)]
mod tests {

use pathfinder_common::macro_prelude::*;
use pathfinder_common::{
felt,
BlockHeader,
BlockId,
CallParam,
ClassHash,
ContractAddress,
EntryPoint,
StarknetVersion,
StorageAddress,
StorageValue,
TransactionVersion,
};
use pathfinder_crypto::Felt;
use pathfinder_storage::Storage;
use starknet_gateway_test_fixtures::class_definitions::{
DUMMY_ACCOUNT_CLASS_HASH,
ERC20_CONTRACT_DEFINITION_CLASS_HASH,
};

use crate::context::RpcContext;
use crate::dto::serialize::{SerializeForVersion, Serializer};
use crate::dto::{
CallType,
ComputationResources,
ExecutionResources,
FeeEstimate,
FunctionInvocation,
SimulatedTransaction,
TransactionTrace,
};
use crate::method::call::FunctionCall;
use crate::method::get_state_update::types::{DeployedContract, Nonce, StateDiff};
use crate::method::simulate_transactions::tests::fixtures;
use crate::types::request::{
BroadcastedDeclareTransaction,
BroadcastedDeclareTransactionV1,
BroadcastedTransaction,
};
use crate::types::ContractClass;
use crate::RpcVersion;

pub(crate) async fn setup_storage_with_starknet_version(
version: StarknetVersion,
) -> (
Storage,
BlockHeader,
ContractAddress,
ContractAddress,
StorageValue,
) {
let test_storage_key = StorageAddress::from_name(b"my_storage_var");
let test_storage_value = storage_value!("0x09");

// set test storage variable
let (storage, last_block_header, account_contract_address, universal_deployer_address) =
crate::test_setup::test_storage(version, |state_update| {
state_update.with_storage_update(
fixtures::DEPLOYED_CONTRACT_ADDRESS,
test_storage_key,
test_storage_value,
)
})
.await;

(
storage,
last_block_header,
account_contract_address,
universal_deployer_address,
test_storage_value,
)
}
}
5 changes: 2 additions & 3 deletions crates/rpc/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,8 @@ impl ApplicationError {
pub fn message(&self, version: RpcVersion) -> String {
match self {
ApplicationError::InsufficientResourcesForValidate => match version {
RpcVersion::V06 | RpcVersion::V07 => "Max fee is smaller than the minimal \
transaction cost (validation plus fee \
transfer)"
RpcVersion::V07 => "Max fee is smaller than the minimal transaction cost \
(validation plus fee transfer)"
.to_string(),
_ => self.to_string(),
},
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/src/felt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl From<RpcFelt> for Felt {
/// This can be easily accomplished by marking a field with `#[serde_as(as =
/// "RpcFelt251")]`.
#[derive(serde::Serialize)]
pub struct RpcFelt251(RpcFelt);
pub struct RpcFelt251(pub RpcFelt);

mod serialization {
//! Blanket [serde::Serialize] and [serde_with::SerializeAs] implementations
Expand Down
19 changes: 0 additions & 19 deletions crates/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ mod pending;
#[cfg(test)]
mod test_setup;
pub mod types;
pub mod v06;
pub mod v07;
pub mod v08;

Expand Down Expand Up @@ -44,7 +43,6 @@ const DEFAULT_MAX_CONNECTIONS: usize = 1024;

#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub enum RpcVersion {
V06,
#[default]
V07,
V08,
Expand All @@ -54,7 +52,6 @@ pub enum RpcVersion {
impl RpcVersion {
fn to_str(self) -> &'static str {
match self {
RpcVersion::V06 => "v0.6",
RpcVersion::V07 => "v0.7",
RpcVersion::V08 => "v0.8",
RpcVersion::PathfinderV01 => "v0.1",
Expand Down Expand Up @@ -164,13 +161,11 @@ impl RpcServer {
}
}

let v06_routes = v06::register_routes().build(self.context.clone());
let v07_routes = v07::register_routes().build(self.context.clone());
let v08_routes = v08::register_routes().build(self.context.clone());
let pathfinder_routes = pathfinder::register_routes().build(self.context.clone());

let default_router = match self.default_version {
RpcVersion::V06 => v06_routes.clone(),
RpcVersion::V07 => v07_routes.clone(),
RpcVersion::V08 => v08_routes.clone(),
RpcVersion::PathfinderV01 => {
Expand All @@ -183,8 +178,6 @@ impl RpcServer {
// used by monitoring bots to check service health.
.route("/", get(empty_body).post(rpc_handler))
.with_state(default_router.clone())
.route("/rpc/v0_6", post(rpc_handler))
.with_state(v06_routes.clone())
.route("/rpc/v0_7", post(rpc_handler))
.with_state(v07_routes.clone())
// TODO Uncomment once RPC 0.8 is ready.
Expand All @@ -198,8 +191,6 @@ impl RpcServer {
router
.route("/ws", get(websocket_handler))
.with_state(default_router)
.route("/ws/rpc/v0_6", get(websocket_handler))
.with_state(v06_routes)
.route("/ws/rpc/v0_7", get(websocket_handler))
.with_state(v07_routes)
.route("/ws/rpc/pathfinder/v0_1", get(websocket_handler))
Expand Down Expand Up @@ -951,16 +942,6 @@ mod tests {
#[case::v0_7_pathfinder("/rpc/v0_7", "pathfinder_rpc_api.json", &["pathfinder_version", "pathfinder_getTransactionStatus"], Api::HttpOnly)]
#[case::v0_7_pathfinder_websocket("/ws/rpc/v0_7", "pathfinder_rpc_api.json", &["pathfinder_version", "pathfinder_getTransactionStatus"], Api::WebsocketOnly)]

#[case::v0_6_api("/rpc/v0_6", "v06/starknet_api_openrpc.json", &[], Api::HttpOnly)]
#[case::v0_6_api_websocket("/ws/rpc/v0_6", "v06/starknet_api_openrpc.json", &[], Api::WebsocketOnly)]
#[case::v0_6_trace("/rpc/v0_6", "v06/starknet_trace_api_openrpc.json", &[], Api::HttpOnly)]
#[case::v0_6_trace_websocket("/ws/rpc/v0_6", "v06/starknet_trace_api_openrpc.json", &[], Api::WebsocketOnly)]
#[case::v0_6_write("/rpc/v0_6", "v06/starknet_write_api.json", &[], Api::HttpOnly)]
#[case::v0_6_write_websocket("/ws/rpc/v0_6", "v06/starknet_write_api.json", &[], Api::WebsocketOnly)]
// get_transaction_status is now part of the official spec, so we are phasing it out.
#[case::v0_6_pathfinder("/rpc/v0_6", "pathfinder_rpc_api.json", &["pathfinder_version", "pathfinder_getTransactionStatus"], Api::HttpOnly)]
#[case::v0_6_pathfinder_websocket("/ws/rpc/v0_6", "pathfinder_rpc_api.json", &["pathfinder_version", "pathfinder_getTransactionStatus"], Api::WebsocketOnly)]

#[case::pathfinder("/rpc/pathfinder/v0.1", "pathfinder_rpc_api.json", &[], Api::HttpOnly)]
#[case::pathfinder("/ws/rpc/pathfinder/v0_1", "pathfinder_rpc_api.json", &[], Api::WebsocketOnly)]

Expand Down
Loading
Loading