diff --git a/crates/blockifier/src/abi/constants.rs b/crates/blockifier/src/abi/constants.rs index ba8ed1e896..7de227f7de 100644 --- a/crates/blockifier/src/abi/constants.rs +++ b/crates/blockifier/src/abi/constants.rs @@ -1,9 +1,3 @@ -use starknet_api::transaction::TransactionVersion; -use starknet_types_core::felt::Felt; - -// The version is considered 0 for L1-Handler transaction hash calculation purposes. -pub const L1_HANDLER_VERSION: TransactionVersion = TransactionVersion(Felt::ZERO); - // OS-related constants. pub const L1_TO_L2_MSG_HEADER_SIZE: usize = 5; pub const L2_TO_L1_MSG_HEADER_SIZE: usize = 3; diff --git a/crates/native_blockifier/src/py_l1_handler.rs b/crates/native_blockifier/src/py_l1_handler.rs index df90b9642e..ede488bc01 100644 --- a/crates/native_blockifier/src/py_l1_handler.rs +++ b/crates/native_blockifier/src/py_l1_handler.rs @@ -1,6 +1,5 @@ use std::sync::Arc; -use blockifier::abi::constants; use pyo3::prelude::*; use starknet_api::core::{ContractAddress, EntryPointSelector, Nonce}; use starknet_api::executable_transaction::L1HandlerTransaction; @@ -21,13 +20,12 @@ struct PyL1HandlerTransaction { impl TryFrom for starknet_api::transaction::L1HandlerTransaction { type Error = NativeBlockifierInputError; fn try_from(tx: PyL1HandlerTransaction) -> Result { - Ok(Self { - version: constants::L1_HANDLER_VERSION, - nonce: Nonce(tx.nonce.0), - contract_address: ContractAddress::try_from(tx.contract_address.0)?, - entry_point_selector: EntryPointSelector(tx.entry_point_selector.0), - calldata: Calldata(Arc::from(from_py_felts(tx.calldata))), - }) + Ok(Self::new( + Nonce(tx.nonce.0), + ContractAddress::try_from(tx.contract_address.0)?, + EntryPointSelector(tx.entry_point_selector.0), + Calldata(Arc::from(from_py_felts(tx.calldata))), + )) } } diff --git a/crates/papyrus_protobuf/src/converters/transaction.rs b/crates/papyrus_protobuf/src/converters/transaction.rs index 2e43b8ccf6..a376bfc349 100644 --- a/crates/papyrus_protobuf/src/converters/transaction.rs +++ b/crates/papyrus_protobuf/src/converters/transaction.rs @@ -1253,8 +1253,6 @@ impl From for protobuf::transaction::Deploy { impl TryFrom for L1HandlerTransaction { type Error = ProtobufConversionError; fn try_from(value: protobuf::transaction::L1HandlerV0) -> Result { - let version = TransactionVersion(Felt::ZERO); - let nonce = Nonce( value .nonce @@ -1283,7 +1281,7 @@ impl TryFrom for L1HandlerTransaction { let calldata = Calldata(calldata.into()); - Ok(Self { version, nonce, contract_address, entry_point_selector, calldata }) + Ok(Self::new(nonce, contract_address, entry_point_selector, calldata)) } } diff --git a/crates/papyrus_rpc/src/v0_8/execution_test.rs b/crates/papyrus_rpc/src/v0_8/execution_test.rs index 732525a62f..a1ac28d153 100644 --- a/crates/papyrus_rpc/src/v0_8/execution_test.rs +++ b/crates/papyrus_rpc/src/v0_8/execution_test.rs @@ -70,6 +70,7 @@ use starknet_api::transaction::{ TransactionHash, TransactionOffsetInBlock, TransactionVersion, + L1_HANDLER_VERSION, }; use starknet_api::{calldata, class_hash, contract_address, felt, nonce, tx_hash}; use starknet_client::reader::objects::pending_data::{ @@ -1204,7 +1205,7 @@ async fn pending_trace_block_transactions_and_trace_transaction_execution_contex #[test] fn message_from_l1_to_l1_handler_tx() { let l1_handler_tx = L1HandlerTransaction::from(MESSAGE_FROM_L1.clone()); - assert_eq!(l1_handler_tx.version, TransactionVersion::ONE); + assert_eq!(l1_handler_tx.version, L1_HANDLER_VERSION); assert_eq!(l1_handler_tx.contract_address, *CONTRACT_ADDRESS); assert_eq!(l1_handler_tx.entry_point_selector, selector_from_name("l1_handle")); // The first item of calldata is the from_address. diff --git a/crates/papyrus_rpc/src/v0_8/transaction.rs b/crates/papyrus_rpc/src/v0_8/transaction.rs index da7dc9c41e..33bfaf6a0c 100644 --- a/crates/papyrus_rpc/src/v0_8/transaction.rs +++ b/crates/papyrus_rpc/src/v0_8/transaction.rs @@ -1280,14 +1280,7 @@ impl From for L1HandlerTransaction { let mut calldata = vec![sender_as_felt]; calldata.extend_from_slice(&message.payload.0); let calldata = Calldata(Arc::new(calldata)); - Self { - // TODO: This should be of transaction version 0. - version: TransactionVersion::ONE, - contract_address: message.to_address, - entry_point_selector: message.entry_point_selector, - calldata, - ..Default::default() - } + Self::new(Nonce::default(), message.to_address, message.entry_point_selector, calldata) } } diff --git a/crates/papyrus_rpc/src/v0_8/transaction_test.rs b/crates/papyrus_rpc/src/v0_8/transaction_test.rs index 965656b6f8..4b61923f14 100644 --- a/crates/papyrus_rpc/src/v0_8/transaction_test.rs +++ b/crates/papyrus_rpc/src/v0_8/transaction_test.rs @@ -16,7 +16,7 @@ use starknet_api::transaction::fields::{ Tip, TransactionSignature, }; -use starknet_api::transaction::{L1HandlerTransaction, Transaction, TransactionVersion}; +use starknet_api::transaction::{L1HandlerTransaction, Transaction}; use starknet_api::{calldata, contract_address, felt, nonce}; use starknet_client::writer::objects::transaction as client_transaction; @@ -37,16 +37,15 @@ use super::{ lazy_static::lazy_static! { // A transaction from MAINNET with tx hash 0x439e12f67962c353182d72b4af12c3f11eaba4b36e552aebcdcd6db66971bdb. - static ref L1_HANDLER_TX: L1HandlerTransaction = L1HandlerTransaction { - version: TransactionVersion::ZERO, - nonce: nonce!(0x18e94d), - contract_address: contract_address!( + static ref L1_HANDLER_TX: L1HandlerTransaction = L1HandlerTransaction::new( + nonce!(0x18e94d), + contract_address!( "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82" ), - entry_point_selector: EntryPointSelector(felt!( + EntryPointSelector(felt!( "0x1b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19" )), - calldata: calldata![ + calldata![ felt!("0xae0ee0a63a2ce6baeeffe56e7714fb4efe48d419"), felt!("0x455448"), felt!("0xc27947400e26e534e677afc2e9b2ec1bab14fc89"), @@ -54,7 +53,7 @@ lazy_static::lazy_static! { felt!("0x9184e72a000"), felt!("0x0") ], - }; + ); } // The msg hash of the L1Handler transaction. diff --git a/crates/starknet_api/src/test_utils/l1_handler.rs b/crates/starknet_api/src/test_utils/l1_handler.rs index bc848a6b01..beb669e979 100644 --- a/crates/starknet_api/src/test_utils/l1_handler.rs +++ b/crates/starknet_api/src/test_utils/l1_handler.rs @@ -1,7 +1,7 @@ use crate::core::{ContractAddress, EntryPointSelector, Nonce}; use crate::executable_transaction::L1HandlerTransaction as ExecutableL1HandlerTransaction; use crate::transaction::fields::{Calldata, Fee}; -use crate::transaction::{L1HandlerTransaction, TransactionHash, TransactionVersion}; +use crate::transaction::{L1HandlerTransaction, TransactionHash}; #[derive(Clone, Default)] pub struct L1HandlerTxArgs { @@ -34,13 +34,12 @@ pub fn executable_l1_handler_tx( l1_handler_tx_args: L1HandlerTxArgs, ) -> ExecutableL1HandlerTransaction { ExecutableL1HandlerTransaction { - tx: L1HandlerTransaction { - version: TransactionVersion::ZERO, // The transaction version of L1 handler is always 0. - nonce: l1_handler_tx_args.nonce, - contract_address: l1_handler_tx_args.contract_address, - entry_point_selector: l1_handler_tx_args.entry_point_selector, - calldata: l1_handler_tx_args.calldata, - }, + tx: L1HandlerTransaction::new( + l1_handler_tx_args.nonce, + l1_handler_tx_args.contract_address, + l1_handler_tx_args.entry_point_selector, + l1_handler_tx_args.calldata, + ), tx_hash: l1_handler_tx_args.tx_hash, paid_fee_on_l1: l1_handler_tx_args.paid_fee_on_l1, } diff --git a/crates/starknet_api/src/transaction.rs b/crates/starknet_api/src/transaction.rs index b2af549672..e0341838fd 100644 --- a/crates/starknet_api/src/transaction.rs +++ b/crates/starknet_api/src/transaction.rs @@ -54,6 +54,9 @@ pub static QUERY_VERSION_BASE: LazyLock = LazyLock::new(|| { Felt::TWO.pow(QUERY_VERSION_BASE_BIT) }); +// The version is considered 0 for L1-Handler transaction hash calculation purposes. +pub const L1_HANDLER_VERSION: TransactionVersion = TransactionVersion(Felt::ZERO); + pub trait TransactionHasher { fn calculate_transaction_hash( &self, @@ -682,6 +685,25 @@ pub struct L1HandlerTransaction { pub calldata: Calldata, } +impl L1HandlerTransaction { + /// A new method is implemented for this struct even though all fields are public because for a + /// properly formatted transaction, the transaction version is always 0. + pub fn new( + nonce: Nonce, + contract_address: ContractAddress, + entry_point_selector: EntryPointSelector, + calldata: Calldata, + ) -> Self { + Self { + version: L1_HANDLER_VERSION, + nonce, + contract_address, + entry_point_selector, + calldata, + } + } +} + impl TransactionHasher for L1HandlerTransaction { fn calculate_transaction_hash( &self, diff --git a/crates/starknet_client/src/reader/objects/transaction.rs b/crates/starknet_client/src/reader/objects/transaction.rs index e341c2ea20..4aa8e4f44a 100644 --- a/crates/starknet_client/src/reader/objects/transaction.rs +++ b/crates/starknet_client/src/reader/objects/transaction.rs @@ -141,6 +141,7 @@ impl Transaction { #[serde(deny_unknown_fields)] pub struct L1HandlerTransaction { pub transaction_hash: TransactionHash, + // TODO: The version field should always be set to 0. pub version: TransactionVersion, #[serde(default)] pub nonce: Nonce, @@ -151,6 +152,16 @@ pub struct L1HandlerTransaction { impl From for starknet_api::transaction::L1HandlerTransaction { fn from(l1_handler_tx: L1HandlerTransaction) -> Self { + if l1_handler_tx.version != starknet_api::transaction::L1_HANDLER_VERSION { + error!("L1HandlerTransaction version is not supported: {:?}", l1_handler_tx.version); + } + // starknet_api::transaction::L1HandlerTransaction::new( + // l1_handler_tx.nonce, + // l1_handler_tx.contract_address, + // l1_handler_tx.entry_point_selector, + // l1_handler_tx.calldata, + // ) + starknet_api::transaction::L1HandlerTransaction { version: l1_handler_tx.version, nonce: l1_handler_tx.nonce,