diff --git a/CHANGELOG.md b/CHANGELOG.md index b68f6bcaf2..7f9cf8f74b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Next release +- refacto: substrate/starknet names in rpc library +- feat(rpc): Added starknet_getTransactionStatus and removed + starknet_pendingTransactions - feat(rpc): add starknet_specVersion rpc + added test for future support - docs: Added v0.6.0-rc5 documentation above the rpc method functions - dev(deps): bump starknet rs, use Eq for EmmitedEvents comparaison diff --git a/Cargo.lock b/Cargo.lock index fee509d4a8..780534fdc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -243,30 +243,30 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "a3a318f1f38d2418400f8209655bfd825785afd25aa30bb7ba6cc792e4596748" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2043,9 +2043,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.10" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" dependencies = [ "clap_builder", "clap_derive", @@ -2053,9 +2053,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.9" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" dependencies = [ "anstream", "anstyle", @@ -3998,7 +3998,7 @@ dependencies = [ "Inflector", "array-bytes 6.2.0", "chrono", - "clap 4.4.10", + "clap 4.4.11", "comfy-table", "frame-benchmarking", "frame-support", @@ -6385,7 +6385,7 @@ version = "0.5.0" dependencies = [ "async-trait", "blockifier", - "clap 4.4.10", + "clap 4.4.11", "frame-benchmarking", "frame-benchmarking-cli", "frame-system", @@ -6571,7 +6571,7 @@ dependencies = [ "avail-subxt", "celestia-rpc", "celestia-types", - "clap 4.4.10", + "clap 4.4.11", "ethers", "futures", "jsonrpsee 0.20.3", @@ -6690,6 +6690,7 @@ dependencies = [ "jsonrpsee 0.16.3", "mp-block", "mp-digest-log", + "mp-transactions", "num-bigint", "serde", "serde_json", @@ -7644,9 +7645,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.60" +version = "0.10.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" +checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -7676,9 +7677,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.96" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" +checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" dependencies = [ "cc", "libc", @@ -9598,7 +9599,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot dependencies = [ "array-bytes 6.2.0", "chrono", - "clap 4.4.10", + "clap 4.4.11", "fdlimit", "futures", "libp2p-identity 0.1.3", @@ -11160,9 +11161,9 @@ dependencies = [ [[package]] name = "snap" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "snow" @@ -13603,7 +13604,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.3.0#401f8a3e9448db854f5605b679fa085b8f445039" dependencies = [ "async-trait", - "clap 4.4.10", + "clap 4.4.11", "frame-remote-externalities", "frame-try-runtime", "hex", @@ -14815,9 +14816,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.19" +version = "0.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +checksum = "0383266b19108dfc6314a56047aa545a1b4d1be60e799b4dbdd407b56402704b" dependencies = [ "memchr", ] diff --git a/crates/client/rpc-core/Cargo.toml b/crates/client/rpc-core/Cargo.toml index ec4186b724..758cc578c2 100644 --- a/crates/client/rpc-core/Cargo.toml +++ b/crates/client/rpc-core/Cargo.toml @@ -32,6 +32,7 @@ jsonrpsee = { workspace = true, features = [ ], default-features = true } mp-block = { workspace = true } mp-digest-log = { workspace = true } +mp-transactions = { workspace = true, features = ["serde"] } num-bigint = { workspace = true } serde = { workspace = true, default-features = true } serde_json = { workspace = true } diff --git a/crates/client/rpc-core/src/lib.rs b/crates/client/rpc-core/src/lib.rs index 28cf13cc2f..230351d5c1 100644 --- a/crates/client/rpc-core/src/lib.rs +++ b/crates/client/rpc-core/src/lib.rs @@ -14,6 +14,7 @@ use serde_with::serde_as; pub mod utils; +use mp_transactions::TransactionStatus; use starknet_core::serde::unsigned_field_element::UfeHex; use starknet_core::types::{ BlockHashAndNumber, BlockId, BroadcastedDeclareTransaction, BroadcastedDeployAccountTransaction, @@ -71,6 +72,10 @@ pub trait StarknetReadRpcApi { #[method(name = "getBlockTransactionCount")] fn get_block_transaction_count(&self, block_id: BlockId) -> RpcResult; + /// Gets the Transaction Status, Including Mempool Status and Execution Details + #[method(name = "getTransactionStatus")] + fn get_transaction_status(&self, transaction_hash: FieldElement) -> RpcResult; + /// Get the value of the storage at the given address and key, at the given block id #[method(name = "getStorageAt")] fn get_storage_at(&self, contract_address: FieldElement, key: FieldElement, block_id: BlockId) -> RpcResult; @@ -128,10 +133,6 @@ pub trait StarknetReadRpcApi { #[method(name = "getStateUpdate")] fn get_state_update(&self, block_id: BlockId) -> RpcResult; - /// Returns the transactions in the transaction pool, recognized by this sequencer - #[method(name = "pendingTransactions")] - async fn pending_transactions(&self) -> RpcResult>; - /// Returns all events matching the given filter #[method(name = "getEvents")] async fn get_events(&self, filter: EventFilterWithPage) -> RpcResult; diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index 83c8575321..0eedf4c469 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -23,14 +23,14 @@ use mp_felt::{Felt252Wrapper, Felt252WrapperError}; use mp_hashers::HasherT; use mp_transactions::compute_hash::ComputeTransactionHash; use mp_transactions::to_starknet_core_transaction::to_starknet_core_tx; -use mp_transactions::UserTransaction; +use mp_transactions::{TransactionStatus, UserTransaction}; use pallet_starknet_runtime_api::{ConvertTransactionRuntimeApi, StarknetRuntimeApi}; use sc_client_api::backend::{Backend, StorageProvider}; use sc_client_api::BlockBackend; use sc_network_sync::SyncingService; use sc_transaction_pool::{ChainApi, Pool}; use sc_transaction_pool_api::error::{Error as PoolError, IntoPoolError}; -use sc_transaction_pool_api::{InPoolTransaction, TransactionPool, TransactionSource}; +use sc_transaction_pool_api::{TransactionPool, TransactionSource}; use sp_api::{ApiError, ProvideRuntimeApi}; use sp_arithmetic::traits::UniqueSaturatedInto; use sp_blockchain::HeaderBackend; @@ -46,7 +46,7 @@ use starknet_core::types::{ DeployAccountTransactionResult, EventFilterWithPage, EventsPage, ExecutionResult, FeeEstimate, FieldElement, FunctionCall, InvokeTransactionReceipt, InvokeTransactionResult, L1HandlerTransactionReceipt, MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, MaybePendingTransactionReceipt, StateDiff, StateUpdate, - SyncStatus, SyncStatusType, Transaction, TransactionFinalityStatus, TransactionReceipt, + SyncStatus, SyncStatusType, Transaction, TransactionExecutionStatus, TransactionFinalityStatus, TransactionReceipt, }; use crate::constants::{MAX_EVENTS_CHUNK_SIZE, MAX_EVENTS_KEYS}; @@ -58,6 +58,7 @@ pub struct Starknet { backend: Arc>, overrides: Arc>, pool: Arc

, + #[allow(dead_code)] graph: Arc>, sync_service: Arc>, starting_block: <::Header as HeaderT>::Number, @@ -119,9 +120,9 @@ where pub fn current_block_hash(&self) -> Result { let substrate_block_hash = self.client.info().best_hash; - let block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); - Ok(block.header().hash::().into()) + Ok(starknet_block.header().hash::().into()) } /// Returns the substrate block hash corresponding to the given Starknet block id @@ -159,10 +160,10 @@ where let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id)?; - let block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash) + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash) .ok_or("Failed to retrieve the substrate block number".to_string())?; - Ok(block.header().block_number) + Ok(starknet_block.header().block_number) } /// Returns a list of all transaction hashes in the given block. @@ -395,9 +396,81 @@ where StarknetRpcApiError::BlockNotFound })?; - let block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); - Ok(block.header().transaction_count) + Ok(starknet_block.header().transaction_count) + } + + /// Gets the Transaction Status, Including Mempool Status and Execution Details + /// + /// This method retrieves the status of a specified transaction. It provides information on + /// whether the transaction is still in the mempool, has been executed, or dropped from the + /// mempool. The status includes both finality status and execution status of the + /// transaction. + /// + /// ### Arguments + /// + /// * `transaction_hash` - The hash of the transaction for which the status is requested. + /// + /// ### Returns + /// + /// * `transaction_status` - An object containing the transaction status details: + /// - `finality_status`: The finality status of the transaction, indicating whether it is + /// confirmed, pending, or rejected. + /// - `execution_status`: The execution status of the transaction, providing details on the + /// execution outcome if the transaction has been processed. + fn get_transaction_status(&self, transaction_hash: FieldElement) -> RpcResult { + let substrate_block_hash = self + .backend + .mapping() + .block_hash_from_transaction_hash(H256::from(transaction_hash.to_bytes_be())) + .map_err(|e| { + error!("Failed to get transaction's substrate block hash from mapping_db: {e}"); + StarknetRpcApiError::TxnHashNotFound + })? + .ok_or(StarknetRpcApiError::TxnHashNotFound)?; + + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash) + .ok_or(StarknetRpcApiError::BlockNotFound)?; + + let chain_id = self.chain_id()?.0.into(); + + let starknet_tx = + if let Some(tx_hashes) = self.get_cached_transaction_hashes(starknet_block.header().hash::().into()) { + tx_hashes + .into_iter() + .zip(starknet_block.transactions()) + .find(|(tx_hash, _)| *tx_hash == Felt252Wrapper(transaction_hash).into()) + .map(|(_, tx)| to_starknet_core_tx(tx.clone(), transaction_hash)) + } else { + starknet_block + .transactions() + .iter() + .find(|tx| tx.compute_hash::(chain_id, false).0 == transaction_hash) + .map(|tx| to_starknet_core_tx(tx.clone(), transaction_hash)) + }; + + let execution_status = { + let revert_error = self + .client + .runtime_api() + .get_tx_execution_outcome(substrate_block_hash, Felt252Wrapper(transaction_hash).into()) + .map_err(|e| { + error!( + "Failed to get transaction execution outcome. Substrate block hash: {substrate_block_hash}, \ + transaction hash: {transaction_hash}, error: {e}" + ); + StarknetRpcApiError::InternalServerError + })?; + + if revert_error.is_none() { + TransactionExecutionStatus::Succeeded + } else { + TransactionExecutionStatus::Reverted + } + }; + + Ok(TransactionStatus { finality_status: TransactionFinalityStatus::AcceptedOnL2, execution_status }) } /// Get the value of the storage at the given address and key. @@ -695,9 +768,9 @@ where StarknetRpcApiError::BlockNotFound })?; - let block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); let chain_id = self.chain_id()?; - let block_hash = block.header().hash::(); + let block_hash = starknet_block.header().hash::(); let transaction_hashes = if let Some(tx_hashes) = self.get_cached_transaction_hashes(block_hash.into()) { let mut v = Vec::with_capacity(tx_hashes.len()); @@ -711,20 +784,20 @@ where } v } else { - block.transactions_hashes::(chain_id.0.into()).map(FieldElement::from).collect() + starknet_block.transactions_hashes::(chain_id.0.into()).map(FieldElement::from).collect() }; - let parent_blockhash = block.header().parent_block_hash; + let parent_blockhash = starknet_block.header().parent_block_hash; let block_with_tx_hashes = BlockWithTxHashes { transactions: transaction_hashes, // TODO: Status hardcoded, get status from block status: BlockStatus::AcceptedOnL2, block_hash: block_hash.into(), parent_hash: parent_blockhash.into(), - block_number: block.header().block_number, - new_root: block.header().global_state_root.into(), - timestamp: block.header().block_timestamp, - sequencer_address: Felt252Wrapper::from(block.header().sequencer_address).into(), + block_number: starknet_block.header().block_number, + new_root: starknet_block.header().global_state_root.into(), + timestamp: starknet_block.header().block_timestamp, + sequencer_address: Felt252Wrapper::from(starknet_block.header().sequencer_address).into(), }; Ok(MaybePendingBlockWithTxHashes::Block(block_with_tx_hashes)) @@ -881,12 +954,14 @@ where StarknetRpcApiError::BlockNotFound })?; - let block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); - let transaction = block.transactions().get(index as usize).ok_or(StarknetRpcApiError::InvalidTxnIndex)?; + let transaction = + starknet_block.transactions().get(index as usize).ok_or(StarknetRpcApiError::InvalidTxnIndex)?; let chain_id = self.chain_id()?; - let opt_cached_transaction_hashes = self.get_cached_transaction_hashes(block.header().hash::().into()); + let opt_cached_transaction_hashes = + self.get_cached_transaction_hashes(starknet_block.header().hash::().into()); let transaction_hash = if let Some(cached_tx_hashes) = opt_cached_transaction_hashes { cached_tx_hashes @@ -934,15 +1009,16 @@ where StarknetRpcApiError::BlockNotFound })?; - let block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); - let block_hash = block.header().hash::(); + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); + let block_hash = starknet_block.header().hash::(); let chain_id = self.chain_id()?; let chain_id = Felt252Wrapper(chain_id.0); - let opt_cached_transaction_hashes = self.get_cached_transaction_hashes(block.header().hash::().into()); - let mut transactions = Vec::with_capacity(block.transactions().len()); - for (index, tx) in block.transactions().iter().enumerate() { + let opt_cached_transaction_hashes = + self.get_cached_transaction_hashes(starknet_block.header().hash::().into()); + let mut transactions = Vec::with_capacity(starknet_block.transactions().len()); + for (index, tx) in starknet_block.transactions().iter().enumerate() { let tx_hash = if let Some(cached_tx_hashes) = opt_cached_transaction_hashes.as_ref() { cached_tx_hashes .get(index) @@ -968,11 +1044,11 @@ where // TODO: Get status from block status: BlockStatus::AcceptedOnL2, block_hash: block_hash.into(), - parent_hash: block.header().parent_block_hash.into(), - block_number: block.header().block_number, - new_root: block.header().global_state_root.into(), - timestamp: block.header().block_timestamp, - sequencer_address: Felt252Wrapper::from(block.header().sequencer_address).into(), + parent_hash: starknet_block.header().parent_block_hash.into(), + block_number: starknet_block.header().block_number, + new_root: starknet_block.header().global_state_root.into(), + timestamp: starknet_block.header().block_timestamp, + sequencer_address: Felt252Wrapper::from(starknet_block.header().sequencer_address).into(), transactions, }; @@ -1003,10 +1079,11 @@ where StarknetRpcApiError::BlockNotFound })?; - let block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); - let old_root = if block.header().block_number > 0 { - let parent_block_hash = (TryInto::::try_into(block.header().parent_block_hash)).unwrap(); + let old_root = if starknet_block.header().block_number > 0 { + let parent_block_hash = + (TryInto::::try_into(starknet_block.header().parent_block_hash)).unwrap(); let substrate_parent_block_hash = self.substrate_block_hash_from_starknet_block(BlockId::Hash(parent_block_hash)).map_err(|e| { error!("'{e}'"); @@ -1021,8 +1098,8 @@ where }; Ok(StateUpdate { - block_hash: block.header().hash::().into(), - new_root: block.header().global_state_root.into(), + block_hash: starknet_block.header().hash::().into(), + new_root: starknet_block.header().global_state_root.into(), old_root, state_diff: StateDiff { storage_diffs: Vec::new(), @@ -1035,44 +1112,6 @@ where }) } - /// TODO: Transaction Status API: Added starknet_getTransactionStatus and removed - /// starknet_pendingTransactions. - async fn pending_transactions(&self) -> RpcResult> { - let substrate_block_hash = self.client.info().best_hash; - - let mut transactions = vec![]; - - let mut transactions_ready: Vec<::Extrinsic> = - self.graph.validated_pool().ready().map(|tx| tx.data().clone()).collect(); - - let mut transactions_future: Vec<::Extrinsic> = - self.graph.validated_pool().futures().into_iter().map(|(_hash, extrinsic)| extrinsic).collect(); - - transactions.append(&mut transactions_ready); - transactions.append(&mut transactions_future); - - let api = self.client.runtime_api(); - - let transactions = api.extrinsic_filter(substrate_block_hash, transactions).map_err(|e| { - error!("Failed to filter extrinsics. Substrate block hash: {substrate_block_hash}, error: {e}"); - StarknetRpcApiError::InternalServerError - })?; - - let chain_id = self.chain_id().map_err(|e| { - error!("Failed to retrieve chain ID. Error: {e}"); - StarknetRpcApiError::InternalServerError - })?; - - let transactions = transactions - .into_iter() - .map(|tx| { - let hash = tx.compute_hash::(chain_id.0.into(), false).into(); - to_starknet_core_tx(tx, hash) - }) - .collect(); - Ok(transactions) - } - /// Returns all events matching the given filter. /// /// This function retrieves all event objects that match the conditions specified in the @@ -1172,7 +1211,7 @@ where /// - `TOO_MANY_KEYS_IN_FILTER` if there are too many keys in the filter, which may exceed the /// system's capacity. fn get_transaction_by_hash(&self, transaction_hash: FieldElement) -> RpcResult { - let block_hash_from_db = self + let substrate_block_hash_from_db = self .backend .mapping() .block_hash_from_transaction_hash(H256::from(transaction_hash.to_bytes_be())) @@ -1181,27 +1220,28 @@ where StarknetRpcApiError::TxnHashNotFound })?; - let substrate_block_hash = match block_hash_from_db { + let substrate_block_hash = match substrate_block_hash_from_db { Some(block_hash) => block_hash, None => return Err(StarknetRpcApiError::TxnHashNotFound.into()), }; - let block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); + let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); let chain_id = self.chain_id()?.0.into(); - let find_tx = if let Some(tx_hashes) = self.get_cached_transaction_hashes(block.header().hash::().into()) { - tx_hashes - .into_iter() - .zip(block.transactions()) - .find(|(tx_hash, _)| *tx_hash == Felt252Wrapper(transaction_hash).into()) - .map(|(_, tx)| to_starknet_core_tx(tx.clone(), transaction_hash)) - } else { - block - .transactions() - .iter() - .find(|tx| tx.compute_hash::(chain_id, false).0 == transaction_hash) - .map(|tx| to_starknet_core_tx(tx.clone(), transaction_hash)) - }; + let find_tx = + if let Some(tx_hashes) = self.get_cached_transaction_hashes(starknet_block.header().hash::().into()) { + tx_hashes + .into_iter() + .zip(starknet_block.transactions()) + .find(|(tx_hash, _)| *tx_hash == Felt252Wrapper(transaction_hash).into()) + .map(|(_, tx)| to_starknet_core_tx(tx.clone(), transaction_hash)) + } else { + starknet_block + .transactions() + .iter() + .find(|tx| tx.compute_hash::(chain_id, false).0 == transaction_hash) + .map(|tx| to_starknet_core_tx(tx.clone(), transaction_hash)) + }; find_tx.ok_or(StarknetRpcApiError::TxnHashNotFound.into()) } @@ -1239,7 +1279,7 @@ where let substrate_block_hash; loop { - let block_hash_from_db = madara_backend + let substrate_block_hash_from_db = madara_backend .mapping() .block_hash_from_transaction_hash(H256::from(transaction_hash.to_bytes_be())) .map_err(|e| { @@ -1247,7 +1287,7 @@ where StarknetRpcApiError::InternalServerError })?; - match block_hash_from_db { + match substrate_block_hash_from_db { Some(block_hash) => { substrate_block_hash = block_hash; break; @@ -1276,9 +1316,9 @@ where Ok(res) => res, }?; - let block: mp_block::Block = + let starknet_block: mp_block::Block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); - let block_header = block.header(); + let block_header = starknet_block.header(); let block_hash = block_header.hash::().into(); let block_number = block_header.block_number; diff --git a/crates/primitives/transactions/src/lib.rs b/crates/primitives/transactions/src/lib.rs index a5c079939c..64c8290b95 100644 --- a/crates/primitives/transactions/src/lib.rs +++ b/crates/primitives/transactions/src/lib.rs @@ -19,6 +19,7 @@ use blockifier::execution::contract_class::ContractClass; use blockifier::transaction::transaction_types::TransactionType; use derive_more::From; use starknet_api::transaction::Fee; +use starknet_core::types::{TransactionExecutionStatus, TransactionFinalityStatus}; use starknet_ff::FieldElement; const SIMULATE_TX_VERSION_OFFSET: FieldElement = @@ -28,6 +29,14 @@ const SIMULATE_TX_VERSION_OFFSET: FieldElement = // pub mod utils; use mp_felt::Felt252Wrapper; +// TODO(antiyro): remove this when released: https://github.com/xJonathanLEI/starknet-rs/blame/fec81d126c58ff3dff6cbfd4b9e714913298e54e/starknet-core/src/types/serde_impls.rs#L175 +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct TransactionStatus { + pub finality_status: TransactionFinalityStatus, + pub execution_status: TransactionExecutionStatus, +} + /// Wrapper type for transaction execution error. /// Different tx types. /// See `https://docs.starknet.io/documentation/architecture_and_concepts/Blocks/transactions/` for more details. diff --git a/docs/content/articles/en/madara-beast-article.md b/docs/content/articles/en/madara-beast-article.md index 1a2b983035..4e18e6346a 100644 --- a/docs/content/articles/en/madara-beast-article.md +++ b/docs/content/articles/en/madara-beast-article.md @@ -28,11 +28,10 @@ Future of Blockchain Infrastructure_ Imagine having the power to tailor-make a blockchain specifically for your application’s unique requirements – that’s exactly what appchains offer. Appchains are application-specific blockchains that offer developers the -flexibility to fine-tune aspects of the chains to suit their applications -needs, like choosing a different hash function or customizing the consensus -algorithm. The best part? Appchains inherit the security of the robust L1 or L2 -blockchains on which they are built, providing developers with the best of both -worlds. +flexibility to fine-tune aspects of the chains to suit their applications needs, +like choosing a different hash function or customizing the consensus algorithm. +The best part? Appchains inherit the security of the robust L1 or L2 blockchains +on which they are built, providing developers with the best of both worlds. Introducing Madara, a game-changing sequencer that combines flexibility and lightning-fast performance. Sequencers are entities responsible for executing diff --git a/docs/contributor-starter-pack.md b/docs/contributor-starter-pack.md index 3662f4ee27..83f54eb29c 100644 --- a/docs/contributor-starter-pack.md +++ b/docs/contributor-starter-pack.md @@ -295,8 +295,8 @@ How to contribute? 3. Work on your fork, in a branch dedicated to the issue you are working on. 4. Push your changes to your fork, and submit a pull request (PR) on Madara official repository. -5. If change is non trivial and requires some time to complete we suggest opening - a Draft PR. In case you need any help you can ask in [madara's +5. If change is non trivial and requires some time to complete we suggest + opening a Draft PR. In case you need any help you can ask in [madara's telegram](https://t.me/MadaraStarknet) channel and link to the relevant code path. @@ -317,7 +317,8 @@ servers browser) Starkware, which is the company at the root of Starknet innovation, is rewarding the contributors via [OnlyDust](https://www.onlydust.xyz/). This is an amazing -initiative and opportunity that rewards early builders of the Starknet ecosystem. +initiative and opportunity that rewards early builders of the Starknet +ecosystem. How it works? Simple: diff --git a/starknet-rpc-test/Cargo.toml b/starknet-rpc-test/Cargo.toml index 24aaca9d6e..61589a2e76 100644 --- a/starknet-rpc-test/Cargo.toml +++ b/starknet-rpc-test/Cargo.toml @@ -93,10 +93,6 @@ path = "add_declare_transaction.rs" name = "starknet_add_deploy_account_transaction" path = "add_deploy_account_transaction.rs" -[[test]] -name = "starknet_pending_transactions" -path = "pending_transactions.rs" - [[test]] name = "starknet_get_transaction_by_hash" path = "get_transaction_by_hash.rs" diff --git a/starknet-rpc-test/pending_transactions.rs b/starknet-rpc-test/pending_transactions.rs deleted file mode 100644 index a767e4fb1f..0000000000 --- a/starknet-rpc-test/pending_transactions.rs +++ /dev/null @@ -1,83 +0,0 @@ -extern crate starknet_rpc_test; - -use rstest::rstest; -use starknet_accounts::Account; -use starknet_core::types::{BlockId, BlockTag}; -use starknet_ff::FieldElement; -use starknet_providers::Provider; -use starknet_rpc_test::constants::{ARGENT_CONTRACT_ADDRESS, SIGNER_PRIVATE}; -use starknet_rpc_test::fixtures::{madara, ThreadSafeMadaraClient}; -use starknet_rpc_test::utils::{build_single_owner_account, AccountActions}; - -#[rstest] -#[tokio::test] -async fn works_with_one_pending_transaction(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { - let rpc = madara.get_starknet_client().await; - - let account = build_single_owner_account(&rpc, SIGNER_PRIVATE, ARGENT_CONTRACT_ADDRESS, true); - - let mut madara_write_lock = madara.write().await; - account.transfer_tokens(FieldElement::from_hex_be("0x123").unwrap(), FieldElement::ONE, None).send().await?; - - let pending_txs = rpc.pending_transactions().await?; - - // Seal block - madara_write_lock.create_empty_block().await?; - - // not validating the fields inside the transaction as - // that is covered in get_block_with_txs - assert_eq!(pending_txs.len(), 1); - - Ok(()) -} - -#[rstest] -#[tokio::test] -async fn works_with_50_pending_transactions(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { - let rpc = madara.get_starknet_client().await; - - let mut madara_write_lock = madara.write().await; - let account = build_single_owner_account(&rpc, SIGNER_PRIVATE, ARGENT_CONTRACT_ADDRESS, true); - let nonce = rpc.get_nonce(BlockId::Tag(BlockTag::Latest), account.address()).await?; - let nonce = nonce.to_bytes_be(); - let nonce: u64 = nonce[31] as u64; - - // loop from 0 to 50 - for nonce_idx in 0..50 { - let _ = account - .transfer_tokens( - FieldElement::from_hex_be("0x123").unwrap(), - FieldElement::ONE, - Some(nonce + nonce_idx as u64), - ) - .send() - .await; - } - - let pending_txs = rpc.pending_transactions().await?; - // Seal block - madara_write_lock.create_empty_block().await?; - - // not validating the fields inside the transaction as - // that is covered in get_block_with_txs - assert_eq!(pending_txs.len(), 50); - - Ok(()) -} - -#[rstest] -#[tokio::test] -async fn works_without_pending_transactions(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { - let rpc = madara.get_starknet_client().await; - - let pending_txs = { - let _madara_write_lock = madara.write(); - rpc.pending_transactions().await? - }; - - // not validating the fields inside the transaction as - // that is covered in get_block_with_txs - assert_eq!(pending_txs.len(), 0); - - Ok(()) -}