Skip to content

Commit

Permalink
Merge pull request #2508 from eqlabs/chris/v3-txs-in-write-api-0.8
Browse files Browse the repository at this point in the history
feat(rpc): v.0.8 only allows v3 transactions in the write api
  • Loading branch information
CHr15F0x authored Jan 22, 2025
2 parents cb88dd2 + 8354376 commit f29a5ec
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 3 deletions.
116 changes: 116 additions & 0 deletions crates/rpc/src/method/add_declare_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,122 @@ pub struct Input {
token: Option<String>,
}

impl Input {
pub fn is_v3_transaction(&self) -> bool {
matches!(
self.declare_transaction,
Transaction::Declare(BroadcastedDeclareTransaction::V3(_))
)
}
}

#[cfg(test)]
impl Input {
pub(crate) fn for_test_with_v0_transaction() -> Self {
Self {
declare_transaction: Transaction::Declare(BroadcastedDeclareTransaction::V0(
crate::types::request::BroadcastedDeclareTransactionV0 {
max_fee: Default::default(),
version: pathfinder_common::TransactionVersion::ZERO,
signature: Default::default(),
contract_class: crate::types::CairoContractClass {
program: Default::default(),
entry_points_by_type: crate::types::ContractEntryPoints {
constructor: Default::default(),
external: Default::default(),
l1_handler: Default::default(),
},
abi: Default::default(),
},
sender_address: Default::default(),
},
)),
token: None,
}
}

pub(crate) fn for_test_with_v1_transaction() -> Self {
Self {
declare_transaction: Transaction::Declare(BroadcastedDeclareTransaction::V1(
crate::types::request::BroadcastedDeclareTransactionV1 {
max_fee: Default::default(),
version: pathfinder_common::TransactionVersion::ONE,
signature: Default::default(),
nonce: Default::default(),
contract_class: crate::types::CairoContractClass {
program: Default::default(),
entry_points_by_type: crate::types::ContractEntryPoints {
constructor: Default::default(),
external: Default::default(),
l1_handler: Default::default(),
},
abi: Default::default(),
},
sender_address: Default::default(),
},
)),
token: None,
}
}

pub(crate) fn for_test_with_v2_transaction() -> Self {
Self {
declare_transaction: Transaction::Declare(BroadcastedDeclareTransaction::V2(
crate::types::request::BroadcastedDeclareTransactionV2 {
max_fee: Default::default(),
version: pathfinder_common::TransactionVersion::TWO,
signature: Default::default(),
nonce: Default::default(),
compiled_class_hash: Default::default(),
contract_class: crate::types::SierraContractClass {
sierra_program: Default::default(),
contract_class_version: Default::default(),
entry_points_by_type: crate::types::SierraEntryPoints {
constructor: Default::default(),
external: Default::default(),
l1_handler: Default::default(),
},
abi: Default::default(),
},
sender_address: Default::default(),
},
)),
token: None,
}
}

pub(crate) fn for_test_with_v3_transaction() -> Self {
Self {
declare_transaction: Transaction::Declare(BroadcastedDeclareTransaction::V3(
crate::types::request::BroadcastedDeclareTransactionV3 {
version: pathfinder_common::TransactionVersion::THREE,
signature: Default::default(),
nonce: Default::default(),
resource_bounds: Default::default(),
tip: Default::default(),
paymaster_data: Default::default(),
account_deployment_data: Default::default(),
nonce_data_availability_mode: Default::default(),
fee_data_availability_mode: Default::default(),
compiled_class_hash: Default::default(),
contract_class: crate::types::SierraContractClass {
sierra_program: Default::default(),
contract_class_version: Default::default(),
entry_points_by_type: crate::types::SierraEntryPoints {
constructor: Default::default(),
external: Default::default(),
l1_handler: Default::default(),
},
abi: Default::default(),
},
sender_address: Default::default(),
},
)),
token: None,
}
}
}

impl crate::dto::DeserializeForVersion for Input {
fn deserialize(value: crate::dto::Value) -> Result<Self, serde_json::Error> {
value.deserialize_map(|value| {
Expand Down
49 changes: 49 additions & 0 deletions crates/rpc/src/method/add_deploy_account_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,55 @@ pub struct Input {
deploy_account_transaction: Transaction,
}

impl Input {
pub fn is_v3_transaction(&self) -> bool {
matches!(
self.deploy_account_transaction,
Transaction::DeployAccount(BroadcastedDeployAccountTransaction::V3(_))
)
}
}
#[cfg(test)]
impl Input {
pub(crate) fn for_test_with_v1_transaction() -> Self {
Self {
deploy_account_transaction: Transaction::DeployAccount(
BroadcastedDeployAccountTransaction::V1(BroadcastedDeployAccountTransactionV1 {
version: pathfinder_common::TransactionVersion::ONE,
max_fee: Default::default(),
signature: Default::default(),
nonce: Default::default(),
class_hash: Default::default(),
contract_address_salt: Default::default(),
constructor_calldata: Default::default(),
}),
),
}
}

pub(crate) fn for_test_with_v3_transaction() -> Self {
Self {
deploy_account_transaction: Transaction::DeployAccount(
BroadcastedDeployAccountTransaction::V3(
crate::types::request::BroadcastedDeployAccountTransactionV3 {
version: pathfinder_common::TransactionVersion::THREE,
signature: Default::default(),
nonce: Default::default(),
resource_bounds: Default::default(),
tip: Default::default(),
paymaster_data: Default::default(),
nonce_data_availability_mode: Default::default(),
fee_data_availability_mode: Default::default(),
contract_address_salt: Default::default(),
constructor_calldata: Default::default(),
class_hash: Default::default(),
},
),
),
}
}
}

impl crate::dto::DeserializeForVersion for Input {
fn deserialize(value: crate::dto::Value) -> Result<Self, serde_json::Error> {
value.deserialize_map(|value| {
Expand Down
62 changes: 62 additions & 0 deletions crates/rpc/src/method/add_invoke_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,68 @@ pub struct Input {
invoke_transaction: Transaction,
}

impl Input {
pub fn is_v3_transaction(&self) -> bool {
matches!(
self.invoke_transaction,
Transaction::Invoke(BroadcastedInvokeTransaction::V3(_))
)
}
}

#[cfg(test)]
impl Input {
pub(crate) fn for_test_with_v0_transaction() -> Self {
Self {
invoke_transaction: Transaction::Invoke(BroadcastedInvokeTransaction::V0(
crate::types::request::BroadcastedInvokeTransactionV0 {
version: pathfinder_common::TransactionVersion::ZERO,
max_fee: Default::default(),
signature: Default::default(),
contract_address: Default::default(),
entry_point_selector: Default::default(),
calldata: Default::default(),
},
)),
}
}

pub(crate) fn for_test_with_v1_transaction() -> Self {
Self {
invoke_transaction: Transaction::Invoke(BroadcastedInvokeTransaction::V1(
crate::types::request::BroadcastedInvokeTransactionV1 {
version: pathfinder_common::TransactionVersion::ONE,
max_fee: Default::default(),
signature: Default::default(),
nonce: Default::default(),
sender_address: Default::default(),
calldata: Default::default(),
},
)),
}
}

pub(crate) fn for_test_with_v3_transaction() -> Self {
Self {
invoke_transaction: Transaction::Invoke(BroadcastedInvokeTransaction::V3(
crate::types::request::BroadcastedInvokeTransactionV3 {
version: pathfinder_common::TransactionVersion::THREE,
signature: Default::default(),
nonce: Default::default(),
resource_bounds: Default::default(),
tip: Default::default(),
paymaster_data: Default::default(),
account_deployment_data: Default::default(),
nonce_data_availability_mode: Default::default(),
fee_data_availability_mode: Default::default(),
sender_address: Default::default(),
calldata: Default::default(),
},
)),
}
}
}

impl crate::dto::DeserializeForVersion for Input {
fn deserialize(value: crate::dto::Value) -> Result<Self, serde_json::Error> {
value.deserialize_map(|value| {
Expand Down
10 changes: 7 additions & 3 deletions crates/rpc/src/v08.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
mod method;

use method as v08_method;

use crate::jsonrpc::{RpcRouter, RpcRouterBuilder};
use crate::method::subscribe_events::SubscribeEvents;
use crate::method::subscribe_new_heads::SubscribeNewHeads;
Expand All @@ -7,9 +11,9 @@ use crate::method::subscribe_transaction_status::SubscribeTransactionStatus;
#[rustfmt::skip]
pub fn register_routes() -> RpcRouterBuilder {
RpcRouter::builder(crate::RpcVersion::V08)
.register("starknet_addDeclareTransaction", crate::method::add_declare_transaction)
.register("starknet_addDeployAccountTransaction", crate::method::add_deploy_account_transaction)
.register("starknet_addInvokeTransaction", crate::method::add_invoke_transaction)
.register("starknet_addDeclareTransaction", v08_method::add_declare_transaction)
.register("starknet_addDeployAccountTransaction", v08_method::add_deploy_account_transaction)
.register("starknet_addInvokeTransaction", v08_method::add_invoke_transaction)
.register("starknet_blockHashAndNumber", crate::method::block_hash_and_number)
.register("starknet_blockNumber", crate::method::block_number)
.register("starknet_call", crate::method::call)
Expand Down
7 changes: 7 additions & 0 deletions crates/rpc/src/v08/method.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod add_declare_transaction;
mod add_deploy_account_transaction;
mod add_invoke_transaction;

pub use add_declare_transaction::add_declare_transaction;
pub use add_deploy_account_transaction::add_deploy_account_transaction;
pub use add_invoke_transaction::add_invoke_transaction;
37 changes: 37 additions & 0 deletions crates/rpc/src/v08/method/add_declare_transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use crate::context::RpcContext;
use crate::method::add_declare_transaction::{AddDeclareTransactionError, Input, Output};

pub async fn add_declare_transaction(
context: RpcContext,
input: Input,
) -> Result<Output, AddDeclareTransactionError> {
if !input.is_v3_transaction() {
return Err(AddDeclareTransactionError::UnsupportedTransactionVersion);
}

crate::method::add_declare_transaction::add_declare_transaction(context, input).await
}

#[cfg(test)]
mod tests {
use super::*;
use crate::context::RpcContext;

#[rstest::rstest]
#[case::v0_is_unsupported(Input::for_test_with_v0_transaction(), false)]
#[case::v1_is_unsupported(Input::for_test_with_v1_transaction(), false)]
#[case::v2_is_unsupported(Input::for_test_with_v2_transaction(), false)]
#[case::v3_is_supported(Input::for_test_with_v3_transaction(), true)]
#[tokio::test]
async fn only_v3_transactions_are_accepted(#[case] input: Input, #[case] is_supported: bool) {
let context = RpcContext::for_tests();
let result = add_declare_transaction(context, input).await;
assert_eq!(
!is_supported,
matches!(
result,
Err(AddDeclareTransactionError::UnsupportedTransactionVersion)
)
);
}
}
40 changes: 40 additions & 0 deletions crates/rpc/src/v08/method/add_deploy_account_transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::context::RpcContext;
use crate::method::add_deploy_account_transaction::{
AddDeployAccountTransactionError,
Input,
Output,
};

pub async fn add_deploy_account_transaction(
context: RpcContext,
input: Input,
) -> Result<Output, AddDeployAccountTransactionError> {
if !input.is_v3_transaction() {
return Err(AddDeployAccountTransactionError::UnsupportedTransactionVersion);
}

crate::method::add_deploy_account_transaction::add_deploy_account_transaction(context, input)
.await
}

#[cfg(test)]
mod tests {
use super::*;
use crate::context::RpcContext;

#[rstest::rstest]
#[case::v1_is_unsupported(Input::for_test_with_v1_transaction(), false)]
#[case::v3_is_supported(Input::for_test_with_v3_transaction(), true)]
#[tokio::test]
async fn only_v3_transactions_are_accepted(#[case] input: Input, #[case] is_supported: bool) {
let context = RpcContext::for_tests();
let result = add_deploy_account_transaction(context, input).await;
assert_eq!(
!is_supported,
matches!(
result,
Err(AddDeployAccountTransactionError::UnsupportedTransactionVersion)
)
);
}
}
36 changes: 36 additions & 0 deletions crates/rpc/src/v08/method/add_invoke_transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::context::RpcContext;
use crate::method::add_invoke_transaction::{AddInvokeTransactionError, Input, Output};

pub async fn add_invoke_transaction(
context: RpcContext,
input: Input,
) -> Result<Output, AddInvokeTransactionError> {
if !input.is_v3_transaction() {
return Err(AddInvokeTransactionError::UnsupportedTransactionVersion);
}

crate::method::add_invoke_transaction::add_invoke_transaction(context, input).await
}

#[cfg(test)]
mod tests {
use super::*;
use crate::context::RpcContext;

#[rstest::rstest]
#[case::v0_is_unsupported(Input::for_test_with_v0_transaction(), false)]
#[case::v1_is_unsupported(Input::for_test_with_v1_transaction(), false)]
#[case::v3_is_supported(Input::for_test_with_v3_transaction(), true)]
#[tokio::test]
async fn only_v3_transactions_are_accepted(#[case] input: Input, #[case] is_supported: bool) {
let context = RpcContext::for_tests();
let result = add_invoke_transaction(context, input).await;
assert_eq!(
!is_supported,
matches!(
result,
Err(AddInvokeTransactionError::UnsupportedTransactionVersion)
)
);
}
}

0 comments on commit f29a5ec

Please sign in to comment.