Skip to content
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
4 changes: 3 additions & 1 deletion crates/apollo_gateway_types/src/gateway_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use starknet_api::transaction::TransactionHash;
use crate::errors::GatewayError;

const TRANSACTION_RECEIVED: &str = "TRANSACTION_RECEIVED";
pub const SUPPORTED_TRANSACTION_VERSIONS: [u64; 1] = [3];
// Version 4 is deploy_account only; the per-type gate is the serde of the transaction enums, so
// this list only shapes the deprecated endpoint's fallback version error.
pub const SUPPORTED_TRANSACTION_VERSIONS: [u64; 2] = [3, 4];

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct GatewayInput {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"version": "0x4",
"signature": [
"0x6"
],
"nonce": "0x0",
"nonce_data_availability_mode": 0,
"fee_data_availability_mode": 0,
"resource_bounds": {
"L1_GAS": {
"max_amount": "0x10000000000",
"max_price_per_unit": "0x10000000000"
},
"L1_DATA_GAS": {
"max_amount": "0x10000000000",
"max_price_per_unit": "0x10000000000"
},
"L2_GAS": {
"max_amount": "0x10000000000",
"max_price_per_unit": "0x10000000000"
}
},
"tip": "0x0",
"paymaster_data": [],
"class_hash": "0xaa17",
"contract_address_salt": "0x14d",
"constructor_calldata": [
"0x7",
"0x8"
],
"type": "DEPLOY_ACCOUNT"
}
67 changes: 63 additions & 4 deletions crates/apollo_http_server/src/deprecated_gateway_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use starknet_api::rpc_transaction::{
RpcDeclareTransactionV3,
RpcDeployAccountTransaction,
RpcDeployAccountTransactionV3,
RpcDeployAccountTransactionV4,
RpcInvokeTransaction,
RpcInvokeTransactionV3,
RpcTransaction,
Expand Down Expand Up @@ -63,6 +64,11 @@ impl DeprecatedGatewayTransactionV3 {
) => RpcTransaction::DeployAccount(RpcDeployAccountTransaction::V3(
deprecated_deploy_account_tx.into(),
)),
DeprecatedGatewayTransactionV3::DeployAccount(
DeprecatedGatewayDeployAccountTransaction::V4(deprecated_deploy_account_tx),
) => RpcTransaction::DeployAccount(RpcDeployAccountTransaction::V4(
deprecated_deploy_account_tx.into(),
)),
DeprecatedGatewayTransactionV3::Invoke(DeprecatedGatewayInvokeTransaction::V3(
deprecated_invoke_tx,
)) => RpcTransaction::Invoke(RpcInvokeTransaction::V3(deprecated_invoke_tx.into())),
Expand All @@ -84,10 +90,10 @@ impl From<RpcTransaction> for DeprecatedGatewayTransactionV3 {
DeprecatedGatewayDeployAccountTransaction::V3(deploy_account_tx.into()),
)
}
// TODO(Ron): add a V4 variant to the deprecated gateway dialect when v4 ingestion is
// enabled.
RpcTransaction::DeployAccount(RpcDeployAccountTransaction::V4(_)) => {
panic!("Deploy account v4 is not supported by the deprecated gateway dialect.")
RpcTransaction::DeployAccount(RpcDeployAccountTransaction::V4(deploy_account_tx)) => {
DeprecatedGatewayTransactionV3::DeployAccount(
DeprecatedGatewayDeployAccountTransaction::V4(deploy_account_tx.into()),
)
}
RpcTransaction::Invoke(RpcInvokeTransaction::V3(invoke_tx)) => {
DeprecatedGatewayTransactionV3::Invoke(DeprecatedGatewayInvokeTransaction::V3(
Expand Down Expand Up @@ -167,6 +173,8 @@ impl From<RpcInvokeTransactionV3> for DeprecatedGatewayInvokeTransactionV3 {
pub enum DeprecatedGatewayDeployAccountTransaction {
#[serde(rename = "0x3")]
V3(DeprecatedGatewayDeployAccountTransactionV3),
#[serde(rename = "0x4")]
V4(DeprecatedGatewayDeployAccountTransactionV4),
}

#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
Expand Down Expand Up @@ -218,6 +226,57 @@ impl From<RpcDeployAccountTransactionV3> for DeprecatedGatewayDeployAccountTrans
}
}

/// A v4 deploy account transaction in the legacy gateway dialect: the fields of v3, with the
/// contract address derived using Blake2 instead of Pedersen.
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct DeprecatedGatewayDeployAccountTransactionV4 {
pub signature: TransactionSignature,
pub nonce: Nonce,
pub class_hash: ClassHash,
pub contract_address_salt: ContractAddressSalt,
pub constructor_calldata: Calldata,
pub resource_bounds: DeprecatedGatewayAllResourceBounds,
pub tip: Tip,
pub paymaster_data: PaymasterData,
pub nonce_data_availability_mode: DataAvailabilityMode,
pub fee_data_availability_mode: DataAvailabilityMode,
}

impl From<DeprecatedGatewayDeployAccountTransactionV4> for RpcDeployAccountTransactionV4 {
fn from(deprecated_deploy_account_tx: DeprecatedGatewayDeployAccountTransactionV4) -> Self {
RpcDeployAccountTransactionV4 {
signature: deprecated_deploy_account_tx.signature,
nonce: deprecated_deploy_account_tx.nonce,
class_hash: deprecated_deploy_account_tx.class_hash,
contract_address_salt: deprecated_deploy_account_tx.contract_address_salt,
constructor_calldata: deprecated_deploy_account_tx.constructor_calldata,
resource_bounds: deprecated_deploy_account_tx.resource_bounds.into(),
tip: deprecated_deploy_account_tx.tip,
paymaster_data: deprecated_deploy_account_tx.paymaster_data,
nonce_data_availability_mode: deprecated_deploy_account_tx.nonce_data_availability_mode,
fee_data_availability_mode: deprecated_deploy_account_tx.fee_data_availability_mode,
}
}
}

#[cfg(any(feature = "testing", test))]
impl From<RpcDeployAccountTransactionV4> for DeprecatedGatewayDeployAccountTransactionV4 {
fn from(value: RpcDeployAccountTransactionV4) -> Self {
Self {
signature: value.signature,
nonce: value.nonce,
class_hash: value.class_hash,
contract_address_salt: value.contract_address_salt,
constructor_calldata: value.constructor_calldata,
resource_bounds: value.resource_bounds.into(),
tip: value.tip,
paymaster_data: value.paymaster_data,
nonce_data_availability_mode: value.nonce_data_availability_mode,
fee_data_availability_mode: value.fee_data_availability_mode,
}
}
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, Hash)]
#[serde(tag = "version")]
pub enum DeprecatedGatewayDeclareTransaction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const DEPRECATED_GATEWAY_INVOKE_TX_CLIENT_SIDE_PROVING_JSON_PATH: &str =
"deprecated_gateway/invoke_tx_client_side_proving.json";
const DEPRECATED_GATEWAY_DEPLOY_ACCOUNT_TX_JSON_PATH: &str =
"deprecated_gateway/deploy_account_tx.json";
const DEPRECATED_GATEWAY_DEPLOY_ACCOUNT_V4_TX_JSON_PATH: &str =
"deprecated_gateway/deploy_account_v4_tx.json";
const DEPRECATED_GATEWAY_DECLARE_TX_JSON_PATH: &str = "deprecated_gateway/declare_tx.json";

fn deprecated_gateway_declare_tx() -> DeprecatedGatewayDeclareTransaction {
Expand All @@ -37,8 +39,16 @@ fn deprecated_gateway_invoke_tx_deserialization(#[case] json_path: &str) {

#[test]
fn deprecated_gateway_deploy_account_tx_deserialization() {
let _: DeprecatedGatewayDeployAccountTransaction =
let deploy_account_tx: DeprecatedGatewayDeployAccountTransaction =
read_json_file(DEPRECATED_GATEWAY_DEPLOY_ACCOUNT_TX_JSON_PATH);
assert_matches!(deploy_account_tx, DeprecatedGatewayDeployAccountTransaction::V3(_));
}

#[test]
fn deprecated_gateway_deploy_account_v4_tx_deserialization() {
let deploy_account_tx: DeprecatedGatewayDeployAccountTransaction =
read_json_file(DEPRECATED_GATEWAY_DEPLOY_ACCOUNT_V4_TX_JSON_PATH);
assert_matches!(deploy_account_tx, DeprecatedGatewayDeployAccountTransaction::V4(_));
}

#[test]
Expand Down
6 changes: 3 additions & 3 deletions crates/apollo_http_server/src/http_server_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,17 @@ async fn test_response(#[case] index: u16, #[case] tx: impl GatewayTransaction)
code: StarknetErrorCode::KnownErrorCode(
KnownStarknetErrorCode::InvalidTransactionVersion,
),
message: "Transaction version 1 is not supported. Supported versions: [3].".to_string(),
message: "Transaction version 1 is not supported. Supported versions: [3, 4].".to_string(),
},
)]
#[case::newer_version(
unique_u16!(),
Some("0x4"),
Some("0x5"),
StarknetError {
code: StarknetErrorCode::KnownErrorCode(
KnownStarknetErrorCode::InvalidTransactionVersion,
),
message: "Transaction version 4 is not supported. Supported versions: [3].".to_string(),
message: "Transaction version 5 is not supported. Supported versions: [3, 4].".to_string(),
}
)]
#[tokio::test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@ use mempool_test_utils::starknet_api_test_utils::{
};
use mockall::predicate::eq;
use rstest::{fixture, rstest};
use starknet_api::compiled_class_hash;
use starknet_api::consensus_transaction::ConsensusTransaction;
use starknet_api::core::{is_pedersen_reachable_address, ContractAddress};
use starknet_api::executable_transaction::ValidateCompiledClassHashError;
use starknet_api::rpc_transaction::{RpcDeclareTransaction, RpcTransaction};
use starknet_api::rpc_transaction::{
InternalRpcTransactionWithoutTxHash,
RpcDeclareTransaction,
RpcTransaction,
};
use starknet_api::test_utils::deploy_account::rpc_deploy_account_tx;
use starknet_api::test_utils::{path_in_resources, read_json_file, CHAIN_ID_FOR_TESTS};
use starknet_api::transaction::fields::{Proof, ProofFacts};
use starknet_api::transaction::fields::{Calldata, ContractAddressSalt, Proof, ProofFacts};
use starknet_api::transaction::TransactionVersion;
use starknet_api::{class_hash, compiled_class_hash, deploy_account_tx_args};
use starknet_types_core::felt::Felt;

use crate::transaction_converter::{
TransactionConverter,
Expand Down Expand Up @@ -270,3 +278,37 @@ async fn test_internal_rpc_to_rpc_in_echonet_mode_skips_proof_manager_lookup(
assert_eq!(round_tripped_tx.proof_facts, proof_facts);
assert!(round_tripped_tx.proof.is_empty(), "proof must remain empty in an echonet round-trip");
}

#[rstest]
#[tokio::test]
async fn test_convert_rpc_deploy_account_v4_to_internal() {
let transaction_converter = create_transaction_converter(MockProofManagerClient::new());

// Frozen vector: deployer = 0, salt = 771, class_hash = 0x4242,
// constructor_calldata = [42, 2^63, 1337], escaping after one increment.
let rpc_tx = rpc_deploy_account_tx(deploy_account_tx_args! {
version: TransactionVersion::FOUR,
class_hash: class_hash!("0x4242"),
contract_address_salt: ContractAddressSalt(Felt::from(771_u16)),
constructor_calldata: Calldata(Arc::new(vec![
Felt::from(42_u8),
Felt::from(1_u64 << 63),
Felt::from(1337_u16),
])),
});

let (internal_tx, _verification_handle) =
transaction_converter.convert_rpc_tx_to_internal_rpc_tx(rpc_tx).await.unwrap();
let InternalRpcTransactionWithoutTxHash::DeployAccount(internal_deploy_account) =
&internal_tx.tx
else {
panic!("Expected a deploy account transaction.");
};

let expected_address = ContractAddress::try_from(Felt::from_hex_unchecked(
"0x566c3e328f3fd5a311267250cadc3c1c4de799db54180fcf862fe90b622571d",
))
.unwrap();
assert_eq!(internal_deploy_account.contract_address, expected_address);
assert!(!is_pedersen_reachable_address(internal_deploy_account.contract_address.0.key()));
}
50 changes: 34 additions & 16 deletions crates/starknet_api/src/test_utils/deploy_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::rpc_transaction::{
InternalRpcTransactionWithoutTxHash,
RpcDeployAccountTransaction,
RpcDeployAccountTransactionV3,
RpcDeployAccountTransactionV4,
RpcTransaction,
};
use crate::transaction::fields::{
Expand Down Expand Up @@ -161,26 +162,43 @@ pub fn create_executable_deploy_account_tx_and_update_nonce(
}

pub fn rpc_deploy_account_tx(deploy_tx_args: DeployAccountTxArgs) -> RpcTransaction {
if deploy_tx_args.version != TransactionVersion::THREE {
panic!("Unsupported transaction version: {:?}.", deploy_tx_args.version);
}

let ValidResourceBounds::AllResources(resource_bounds) = deploy_tx_args.resource_bounds else {
panic!("Unsupported resource bounds type: {:?}.", deploy_tx_args.resource_bounds)
};

RpcTransaction::DeployAccount(RpcDeployAccountTransaction::V3(RpcDeployAccountTransactionV3 {
resource_bounds,
tip: deploy_tx_args.tip,
contract_address_salt: deploy_tx_args.contract_address_salt,
class_hash: deploy_tx_args.class_hash,
constructor_calldata: deploy_tx_args.constructor_calldata,
nonce: deploy_tx_args.nonce,
signature: deploy_tx_args.signature,
nonce_data_availability_mode: deploy_tx_args.nonce_data_availability_mode,
fee_data_availability_mode: deploy_tx_args.fee_data_availability_mode,
paymaster_data: deploy_tx_args.paymaster_data,
}))
if deploy_tx_args.version == TransactionVersion::THREE {
RpcTransaction::DeployAccount(RpcDeployAccountTransaction::V3(
RpcDeployAccountTransactionV3 {
resource_bounds,
tip: deploy_tx_args.tip,
contract_address_salt: deploy_tx_args.contract_address_salt,
class_hash: deploy_tx_args.class_hash,
constructor_calldata: deploy_tx_args.constructor_calldata,
nonce: deploy_tx_args.nonce,
signature: deploy_tx_args.signature,
nonce_data_availability_mode: deploy_tx_args.nonce_data_availability_mode,
fee_data_availability_mode: deploy_tx_args.fee_data_availability_mode,
paymaster_data: deploy_tx_args.paymaster_data,
},
))
} else if deploy_tx_args.version == TransactionVersion::FOUR {
RpcTransaction::DeployAccount(RpcDeployAccountTransaction::V4(
RpcDeployAccountTransactionV4 {
resource_bounds,
tip: deploy_tx_args.tip,
contract_address_salt: deploy_tx_args.contract_address_salt,
class_hash: deploy_tx_args.class_hash,
constructor_calldata: deploy_tx_args.constructor_calldata,
nonce: deploy_tx_args.nonce,
signature: deploy_tx_args.signature,
nonce_data_availability_mode: deploy_tx_args.nonce_data_availability_mode,
fee_data_availability_mode: deploy_tx_args.fee_data_availability_mode,
paymaster_data: deploy_tx_args.paymaster_data,
},
))
} else {
panic!("Unsupported transaction version: {:?}.", deploy_tx_args.version);
}
}

pub fn internal_deploy_account_tx(deploy_tx_args: DeployAccountTxArgs) -> InternalRpcTransaction {
Expand Down
Loading