From bb75f1bd922f457ad1b74d75e2598c90f03affb0 Mon Sep 17 00:00:00 2001 From: antiyro Date: Mon, 4 Dec 2023 12:48:39 +0100 Subject: [PATCH 01/18] added documentation for rpc lib function based on v0.6.0-rc5 --- .vscode/settings.json | 9 +- .../src/accounts/argent/ArgentAccount.cairo | 2 +- cairo-contracts/src/counter.cairo | 2 +- crates/client/data-availability/src/lib.rs | 2 +- crates/client/rpc-core/starknet_openRPC.json | 22 +- crates/client/rpc/src/lib.rs | 251 ++++++++++++++++-- .../pallets/starknet/runtime_api/src/lib.rs | 2 +- crates/pallets/starknet/src/lib.rs | 2 +- crates/primitives/block/src/lib.rs | 2 +- crates/primitives/storage/src/lib.rs | 2 +- crates/runtime/src/lib.rs | 2 +- crates/runtime/src/opaque.rs | 2 +- crates/runtime/src/pallets.rs | 2 +- docs/starknet_features_compatibility.md | 2 +- 14 files changed, 255 insertions(+), 49 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2fc1a1b5fe..aaf2deaef4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,10 @@ { - "eslint.workingDirectories": ["tests"] + "eslint.workingDirectories": [ + "tests" + ], + "workbench.colorCustomizations": { + "activityBar.background": "#271C7A", + "titleBar.activeBackground": "#3628AB", + "titleBar.activeForeground": "#FBFBFE" + } } diff --git a/cairo-contracts/src/accounts/argent/ArgentAccount.cairo b/cairo-contracts/src/accounts/argent/ArgentAccount.cairo index 4718f26dc0..5548e6bf04 100644 --- a/cairo-contracts/src/accounts/argent/ArgentAccount.cairo +++ b/cairo-contracts/src/accounts/argent/ArgentAccount.cairo @@ -19,7 +19,7 @@ from src.accounts.argent.library import ( // // @title ArgentAccount // @author Argent Labs -// @notice Main account for Argent on StarkNet +// @notice Main account for Argent on Starknet // // /////////////////// diff --git a/cairo-contracts/src/counter.cairo b/cairo-contracts/src/counter.cairo index 35a087c225..ad2db442d5 100644 --- a/cairo-contracts/src/counter.cairo +++ b/cairo-contracts/src/counter.cairo @@ -1,4 +1,4 @@ -// Declare this file as a StarkNet contract. +// Declare this file as a Starknet contract. %lang starknet from starkware.cairo.common.cairo_builtins import HashBuiltin diff --git a/crates/client/data-availability/src/lib.rs b/crates/client/data-availability/src/lib.rs index 32aa062168..33c92be893 100644 --- a/crates/client/data-availability/src/lib.rs +++ b/crates/client/data-availability/src/lib.rs @@ -123,7 +123,7 @@ where match da_mode { DaMode::Validity => { - // Submit the StarkNet OS PIE + // Submit the Starknet OS PIE // TODO: Validity Impl // run the Starknet OS with the Cairo VM // extract the PIE from the Cairo VM run diff --git a/crates/client/rpc-core/starknet_openRPC.json b/crates/client/rpc-core/starknet_openRPC.json index b7ed095556..d002f99d06 100644 --- a/crates/client/rpc-core/starknet_openRPC.json +++ b/crates/client/rpc-core/starknet_openRPC.json @@ -2,7 +2,7 @@ "openrpc": "1.0.0-rc1", "info": { "version": "0.50.0", - "title": "StarkNet Node API", + "title": "Starknet Node API", "license": {} }, "servers": [], @@ -400,7 +400,7 @@ }, { "name": "starknet_call", - "summary": "call a starknet function without creating a StarkNet transaction", + "summary": "call a starknet function without creating a Starknet transaction", "description": "Calls a function in a contract and returns the return value. Using this call will not create a transaction; hence, will not change the state", "params": [ { @@ -445,7 +445,7 @@ }, { "name": "starknet_estimateFee", - "summary": "estimate the fee for of StarkNet transactions", + "summary": "estimate the fee for of Starknet transactions", "description": "estimates the resources required by transactions when applied on a given state", "params": [ { @@ -536,7 +536,7 @@ }, { "name": "starknet_chainId", - "summary": "Return the currently configured StarkNet chain id", + "summary": "Return the currently configured Starknet chain id", "params": [], "result": { "name": "result", @@ -727,7 +727,7 @@ ] }, "EVENT": { - "title": "A StarkNet event", + "title": "A Starknet event", "allOf": [ { "type": "object", @@ -870,7 +870,7 @@ }, "CHAIN_ID": { "title": "chainId", - "description": "StarkNet chain id, given in hex representation.", + "description": "Starknet chain id, given in hex representation.", "type": "string", "pattern": "^0x[a-fA-F0-9]+$" }, @@ -1009,7 +1009,7 @@ }, "TXN_HASH": { "$ref": "#/components/schemas/FELT", - "description": "The transaction hash, as assigned in StarkNet", + "description": "The transaction hash, as assigned in Starknet", "title": "A transaction's hash" }, "FELT": { @@ -1077,7 +1077,7 @@ "minimum": 0 }, "sequencer_address": { - "description": "The StarkNet identity of the sequencer submitting this block", + "description": "The Starknet identity of the sequencer submitting this block", "$ref": "#/components/schemas/FELT" } }, @@ -1145,7 +1145,7 @@ "minimum": 0 }, "sequencer_address": { - "description": "The StarkNet identity of the sequencer submitting this block", + "description": "The Starknet identity of the sequencer submitting this block", "$ref": "#/components/schemas/FELT" }, "parent_hash": { @@ -1171,7 +1171,7 @@ "minimum": 0 }, "sequencer_address": { - "description": "The StarkNet identity of the sequencer submitting this block", + "description": "The Starknet identity of the sequencer submitting this block", "$ref": "#/components/schemas/FELT" }, "parent_hash": { @@ -1964,7 +1964,7 @@ ] }, "DEPRECATED_CONTRACT_CLASS": { - "title": "The definition of a StarkNet contract class", + "title": "The definition of a Starknet contract class", "type": "object", "properties": { "program": { diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index 0567a1c624..ab460869f4 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -311,10 +311,33 @@ where C::Api: StarknetRuntimeApi + ConvertTransactionRuntimeApi, H: HasherT + Send + Sync + 'static, { + + /// Get the Most Recent Accepted Block Number + /// + /// ### Arguments + /// + /// This function does not take any arguments. + /// + /// ### Returns + /// + /// * `block_number` - The latest block number in the Starknet blockchain. + /// fn block_number(&self) -> RpcResult { self.current_block_number() } + /// Get the Most Recent Accepted Block Hash and Number + /// + /// ### Arguments + /// + /// This function does not take any arguments. + /// + /// ### Returns + /// + /// * `block_hash_and_number` - A tuple containing the latest block hash and number in the Starknet blockchain. + /// - `block_hash`: The hash of the latest block. + /// - `block_number`: The number of the latest block. + /// fn block_hash_and_number(&self) -> RpcResult { let block_number = self.current_block_number()?; let block_hash = self.current_block_hash().map_err(|e| { @@ -328,6 +351,21 @@ where }) } + /// Get the Number of Transactions in a Given Block + /// + /// ### Arguments + /// + /// * `block_id` - The identifier of the requested block. This can be the hash of the block, + /// the block's number (height), or a specific block tag. + /// + /// ### Returns + /// + /// * `transaction_count` - The number of transactions in the specified block. + /// + /// ### Errors + /// + /// This function may return a `BLOCK_NOT_FOUND` error if the specified block does not exist in the blockchain. + /// fn get_block_transaction_count(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -339,7 +377,19 @@ where Ok(block.header().transaction_count) } - /// get the storage at a given address and key and at a given block + /// Get the value of the storage at the given address and key. + /// + /// This function retrieves the value stored in a specified contract's storage, identified by a contract address and a storage key, within a specified block in the StarkNet network. + /// + /// ### Arguments + /// + /// * `contract_address` - The address of the contract to read from. This parameter identifies the contract whose storage is being queried. + /// * `key` - The key to the storage value for the given contract. This parameter specifies the particular storage slot to be queried. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter defines the state of the blockchain at which the storage value is to be read. + /// + /// ### Returns + /// + /// Returns the value at the given key for the given contract, represented as a `FieldElement`. If no value is found at the specified storage key, returns 0. In case of errors, such as `CONTRACT_NOT_FOUND` or `BLOCK_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the specific issue. fn get_storage_at(&self, contract_address: FieldElement, key: FieldElement, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -361,6 +411,26 @@ where Ok(Felt(Felt252Wrapper::from(value).into())) } + /// Call a Function in a Contract Without Creating a Starknet Transaction + /// + /// ### Arguments + /// + /// * `request` - The details of the function call to be made. This includes information such as the + /// contract address, function signature, and arguments. + /// * `block_id` - The identifier of the block used to reference the state or call the transaction on. + /// This can be the hash of the block, its number (height), or a specific block tag. + /// + /// ### Returns + /// + /// * `result` - The function's return value, as defined in the Cairo output. This is an array of field elements (`Felt`). + /// + /// ### Errors + /// + /// This method may return the following errors: + /// * `CONTRACT_NOT_FOUND` - If the specified contract address does not exist. + /// * `CONTRACT_ERROR` - If there is an error with the contract or the function call. + /// * `BLOCK_NOT_FOUND` - If the specified block does not exist in the blockchain. + /// fn call(&self, request: FunctionCall, block_id: BlockId) -> RpcResult> { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -388,7 +458,25 @@ where Ok(result.iter().map(|x| format!("{:#x}", x.0)).collect()) } - /// Get the contract class at a given contract address for a given block id + /// Get the Contract Class Definition at a Given Address in a Specific Block + /// + /// ### Arguments + /// + /// * `block_id` - The identifier of the block. This can be the hash of the block, its number (height), + /// or a specific block tag. + /// * `contract_address` - The address of the contract whose class definition will be returned. + /// + /// ### Returns + /// + /// * `contract_class` - The contract class definition. This may be either a standard contract class + /// or a deprecated contract class, depending on the contract's status and the blockchain's version. + /// + /// ### Errors + /// + /// This method may return the following errors: + /// * `BLOCK_NOT_FOUND` - If the specified block does not exist in the blockchain. + /// * `CONTRACT_NOT_FOUND` - If the specified contract address does not exist. + /// fn get_class_at(&self, block_id: BlockId, contract_address: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -414,13 +502,13 @@ where /// Get the contract class hash in the given block for the contract deployed at the given /// address /// - /// # Arguments + /// ### Arguments /// /// * `block_id` - The hash of the requested block, or number (height) of the requested block, /// or a block tag /// * `contract_address` - The address of the contract whose class hash will be returned /// - /// # Returns + /// ### Returns /// /// * `class_hash` - The class hash of the given contract fn get_class_hash_at(&self, block_id: BlockId, contract_address: FieldElement) -> RpcResult { @@ -442,11 +530,19 @@ where Ok(Felt(Felt252Wrapper::from(class_hash).into())) } - // Implementation of the `syncing` RPC Endpoint. - // It's an async function because it uses `sync_service.best_seen_block()`. - // - // # Returns - // * `Syncing` - An Enum that can be a `mc_rpc_core::SyncStatus` struct or a `Boolean`. + /// Returns an object about the sync status, or false if the node is not synching + /// + /// ### Arguments + /// + /// This function does not take any arguments. + /// + /// ### Returns + /// + /// * `Syncing` - An Enum that can either be a `mc_rpc_core::SyncStatus` struct representing the sync status, + /// or a `Boolean` (`false`) indicating that the node is not currently synchronizing. + /// + /// This is an asynchronous function due to its reliance on `sync_service.best_seen_block()`, + /// which potentially involves network communication and processing to determine the best block seen by the sync service. async fn syncing(&self) -> RpcResult { // obtain best seen (highest) block number match self.sync_service.best_seen_block().await { @@ -505,6 +601,15 @@ where } /// Get the contract class definition in the given block associated with the given hash. + /// + /// ### Arguments + /// + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. + /// * `class_hash` - The hash of the requested contract class. + /// + /// ### Returns + /// + /// Returns the contract class definition if found. In case of an error, returns a `StarknetRpcApiError` indicating either `BlockNotFound` or `ClassHashNotFound`. fn get_class(&self, block_id: BlockId, class_hash: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -528,7 +633,16 @@ where })?) } - /// Returns the specified block with transaction hashes. + /// Get block information with transaction hashes given the block id. + /// + /// ### Arguments + /// + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. + /// + /// ### Returns + /// + /// Returns block information with transaction hashes. This includes either a confirmed block or a pending block with transaction hashes, depending on the state of the requested block. + /// In case the block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. fn get_block_with_tx_hashes(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -570,7 +684,17 @@ where Ok(MaybePendingBlockWithTxHashes::Block(block_with_tx_hashes)) } - /// Get the nonce associated with the given address at the given block + /// Get the nonce associated with the given address in the given block. + /// + /// ### Arguments + /// + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter specifies the block in which the nonce is to be checked. + /// * `contract_address` - The address of the contract whose nonce we're seeking. This is the unique identifier of the contract in the Starknet network. + /// + /// ### Returns + /// + /// Returns the contract's nonce at the requested state. The nonce is returned as a `FieldElement`, representing the current state of the contract in terms of transactions count or other contract-specific operations. + /// In case of errors, such as `BLOCK_NOT_FOUND` or `CONTRACT_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the specific issue. fn get_nonce(&self, block_id: BlockId, contract_address: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -591,7 +715,17 @@ where Ok(Felt(Felt252Wrapper::from(nonce).into())) } - /// Returns the chain id. + /// Return the currently configured chain id. + /// + /// This function provides the chain id for the network that the node is connected to. The chain id is a unique identifier that distinguishes between different networks, such as mainnet or testnet. + /// + /// ### Arguments + /// + /// This function does not take any arguments. + /// + /// ### Returns + /// + /// Returns the chain id this node is connected to. The chain id is returned as a specific type, defined by the Starknet protocol, indicating the particular network. fn chain_id(&self) -> RpcResult { let best_block_hash = self.client.info().best_hash; let chain_id = self.client.runtime_api().chain_id(best_block_hash).map_err(|e| { @@ -666,7 +800,18 @@ where Ok(estimates) } - // Returns the details of a transaction by a given block id and index + /// Get the details of a transaction by a given block id and index. + /// + /// This function fetches the details of a specific transaction in the StarkNet network by identifying it through its block and position (index) within that block. If no transaction is found at the specified index, null is returned. + /// + /// ### Arguments + /// + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter is used to specify the block in which the transaction is located. + /// * `index` - An integer representing the index in the block where the transaction is expected to be found. The index starts from 0 and increases sequentially for each transaction in the block. + /// + /// ### Returns + /// + /// Returns the details of the transaction if found, including the transaction hash. The transaction details are returned as a type conforming to the StarkNet protocol. In case of errors like `BLOCK_NOT_FOUND` or `INVALID_TXN_INDEX`, returns a `StarknetRpcApiError` indicating the specific issue. fn get_transaction_by_block_id_and_index(&self, block_id: BlockId, index: u64) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -702,7 +847,17 @@ where Ok(to_starknet_core_tx(transaction.clone(), transaction_hash)) } - /// Get block information with full transactions given the block id + /// Get block information with full transactions given the block id. + /// + /// This function retrieves detailed information about a specific block in the StarkNet network, including all transactions contained within that block. The block is identified using its unique block id, which can be the block's hash, its number (height), or a block tag. + /// + /// ### Arguments + /// + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter is used to specify the block from which to retrieve information and transactions. + /// + /// ### Returns + /// + /// Returns detailed block information along with full transactions. Depending on the state of the block, this can include either a confirmed block or a pending block with its transactions. In case the specified block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. fn get_block_with_txs(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("Block not found: '{e}'"); @@ -754,7 +909,17 @@ where Ok(MaybePendingBlockWithTxs::Block(block_with_txs)) } - /// Get the information about the result of executing the requested block + /// Get the information about the result of executing the requested block. + /// + /// This function fetches details about the state update resulting from executing a specific block in the StarkNet network. The block is identified using its unique block id, which can be the block's hash, its number (height), or a block tag. + /// + /// ### Arguments + /// + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter specifies the block for which the state update information is required. + /// + /// ### Returns + /// + /// Returns information about the state update of the requested block, including any changes to the state of the network as a result of the block's execution. This can include a confirmed state update or a pending state update. If the block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. fn get_state_update(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -793,7 +958,7 @@ where }) } - /// Returns the transactions in the transaction pool, recognized by this sequencer + /// 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; @@ -830,7 +995,18 @@ where Ok(transactions) } - /// Returns all events matching the given filter + /// Returns all events matching the given filter. + /// + /// This function retrieves all event objects that match the conditions specified in the provided event filter. The filter can include various criteria such as contract addresses, event types, and block ranges. The function supports pagination through the result page request schema. + /// + /// ### Arguments + /// + /// * `filter` - The conditions used to filter the returned events. The filter is a combination of an event filter and a result page request, allowing for precise control over which events are returned and in what quantity. + /// + /// ### Returns + /// + /// Returns a chunk of event objects that match the filter criteria, encapsulated in an `EventsChunk` type. The chunk includes details about the events, such as their data, the block in which they occurred, and the transaction that triggered them. + /// In case of errors, such as `PAGE_SIZE_TOO_BIG`, `INVALID_CONTINUATION_TOKEN`, `BLOCK_NOT_FOUND`, or `TOO_MANY_KEYS_IN_FILTER`, returns a `StarknetRpcApiError` indicating the specific issue. async fn get_events(&self, filter: EventFilterWithPage) -> RpcResult { let continuation_token = match filter.result_page_request.continuation_token { Some(token) => types::ContinuationToken::parse(token).map_err(|e| { @@ -882,15 +1058,26 @@ where self.filter_events(filter) } - /// Returns a transaction details from it's hash. + /// Get the details and status of a submitted transaction. /// - /// If the transaction is in the transactions pool, - /// it considers the transaction hash as not found. - /// Consider using `pending_transaction` for that purpose. + /// This function retrieves the detailed information and status of a transaction identified by its hash. The transaction hash uniquely identifies a specific transaction that has been submitted to the StarkNet network. /// - /// # Arguments + /// ### Arguments + /// + /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the transaction for which details and status are requested. + /// + /// ### Returns /// - /// * `transaction_hash` - Transaction hash corresponding to the transaction. + /// Returns information about the requested transaction, including its status, sender, recipient, and other transaction details. The information is encapsulated in a `Transaction` type, which is a combination of the `TXN` schema and additional properties, such as the `transaction_hash`. + /// In case the specified transaction hash is not found, returns a `StarknetRpcApiError` with `TXN_HASH_NOT_FOUND`. + /// + /// ### Errors + /// + /// The function may return one of the following errors if encountered: + /// - `PAGE_SIZE_TOO_BIG` if the requested page size exceeds the allowed limit. + /// - `INVALID_CONTINUATION_TOKEN` if the provided continuation token is invalid or expired. + /// - `BLOCK_NOT_FOUND` if the specified block is not found. + /// - `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 .backend @@ -926,11 +1113,23 @@ where find_tx.ok_or(StarknetRpcApiError::TxnHashNotFound.into()) } - /// Returns the receipt of a transaction by transaction hash. + /// Get the transaction receipt by the transaction hash. /// - /// # Arguments + /// This function retrieves the transaction receipt for a specific transaction identified by its hash. The transaction receipt includes information about the execution status of the transaction, events generated during its execution, and other relevant details. + /// + /// ### Arguments + /// + /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the transaction for which the receipt is requested. + /// + /// ### Returns + /// + /// Returns a transaction receipt, which can be one of two types: + /// - `TransactionReceipt` if the transaction has been processed and has a receipt. + /// - `PendingTransactionReceipt` if the transaction is pending and the receipt is not yet available. + /// + /// ### Errors /// - /// * `transaction_hash` - Transaction hash corresponding to the transaction. + /// The function may return a `TXN_HASH_NOT_FOUND` error if the specified transaction hash is not found. async fn get_transaction_receipt( &self, transaction_hash: FieldElement, diff --git a/crates/pallets/starknet/runtime_api/src/lib.rs b/crates/pallets/starknet/runtime_api/src/lib.rs index d14ce32d0f..e296dc6814 100644 --- a/crates/pallets/starknet/runtime_api/src/lib.rs +++ b/crates/pallets/starknet/runtime_api/src/lib.rs @@ -1,4 +1,4 @@ -//! Definition of the runtime API for the StarkNet pallet. +//! Definition of the runtime API for the Starknet pallet. #![cfg_attr(not(feature = "std"), no_std)] // Adding allow unused type parameters to avoid clippy errors diff --git a/crates/pallets/starknet/src/lib.rs b/crates/pallets/starknet/src/lib.rs index 6b699a81cf..668c17addb 100644 --- a/crates/pallets/starknet/src/lib.rs +++ b/crates/pallets/starknet/src/lib.rs @@ -575,7 +575,7 @@ pub mod pallet { Ok(()) } - /// Since StarkNet v0.10.1 the deploy_account transaction replaces the deploy transaction + /// Since Starknet v0.10.1 the deploy_account transaction replaces the deploy transaction /// for deploying account contracts. To use it, you should first pre-fund your /// would-be account address so that you could pay the transaction fee (see here for more /// details) . You can then send the deploy_account transaction. See `https://docs.starknet.io/documentation/architecture_and_concepts/Blocks/transactions/#deploy_account_transaction`. diff --git a/crates/primitives/block/src/lib.rs b/crates/primitives/block/src/lib.rs index 2131480cb6..403c3903e4 100644 --- a/crates/primitives/block/src/lib.rs +++ b/crates/primitives/block/src/lib.rs @@ -1,4 +1,4 @@ -//! StarkNet block primitives. +//! Starknet block primitives. #![cfg_attr(not(feature = "std"), no_std)] #[doc(hidden)] diff --git a/crates/primitives/storage/src/lib.rs b/crates/primitives/storage/src/lib.rs index cec5fb0be1..4ba17e4a31 100644 --- a/crates/primitives/storage/src/lib.rs +++ b/crates/primitives/storage/src/lib.rs @@ -1,4 +1,4 @@ -//! StarkNet storage primitives. +//! Starknet storage primitives. #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index b1466fb640..2dbe163616 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -31,7 +31,7 @@ use mp_felt::Felt252Wrapper; use mp_transactions::compute_hash::ComputeTransactionHash; use mp_transactions::{Transaction, UserTransaction}; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; -/// Import the StarkNet pallet. +/// Import the Starknet pallet. pub use pallet_starknet; use pallet_starknet::pallet::Error as PalletError; use pallet_starknet::Call::{consume_l1_message, declare, deploy_account, invoke}; diff --git a/crates/runtime/src/opaque.rs b/crates/runtime/src/opaque.rs index 35918bb9b3..bb79be9229 100644 --- a/crates/runtime/src/opaque.rs +++ b/crates/runtime/src/opaque.rs @@ -6,7 +6,7 @@ pub use frame_support::weights::constants::{ pub use frame_support::weights::{IdentityFee, Weight}; pub use frame_support::{construct_runtime, parameter_types, StorageValue}; pub use frame_system::Call as SystemCall; -/// Import the StarkNet pallet. +/// Import the Starknet pallet. pub use pallet_starknet; pub use pallet_timestamp::Call as TimestampCall; use sp_runtime::traits::BlakeTwo256; diff --git a/crates/runtime/src/pallets.rs b/crates/runtime/src/pallets.rs index 030f6403a2..ecb4c1dcc2 100644 --- a/crates/runtime/src/pallets.rs +++ b/crates/runtime/src/pallets.rs @@ -11,7 +11,7 @@ pub use frame_support::weights::{IdentityFee, Weight}; pub use frame_support::{construct_runtime, parameter_types, StorageValue}; pub use frame_system::Call as SystemCall; pub use mp_chain_id::SN_GOERLI_CHAIN_ID; -/// Import the StarkNet pallet. +/// Import the Starknet pallet. pub use pallet_starknet; pub use pallet_timestamp::Call as TimestampCall; use sp_consensus_aura::sr25519::AuthorityId as AuraId; diff --git a/docs/starknet_features_compatibility.md b/docs/starknet_features_compatibility.md index c214124d7e..d8499331f9 100644 --- a/docs/starknet_features_compatibility.md +++ b/docs/starknet_features_compatibility.md @@ -1,4 +1,4 @@ -# StarkNet Features Compatibility +# Starknet Features Compatibility ## Block From 48a2bafd2220a7742c6189eb16cd8a3d86942cc9 Mon Sep 17 00:00:00 2001 From: antiyro Date: Mon, 4 Dec 2023 14:11:25 +0100 Subject: [PATCH 02/18] runned cleans for CI --- .vscode/settings.json | 4 +--- CHANGELOG.md | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index aaf2deaef4..dd5f3e78bb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,5 @@ { - "eslint.workingDirectories": [ - "tests" - ], + "eslint.workingDirectories": ["tests"], "workbench.colorCustomizations": { "activityBar.background": "#271C7A", "titleBar.activeBackground": "#3628AB", diff --git a/CHANGELOG.md b/CHANGELOG.md index 86526a1189..7f0a1b005b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Next release +- docs: Added v0.6.0-rc5 documentation above the rpc method functions - test(rust-rpc-test): use undeclared contracts for declare transactions testing - build: update blockifier, fix divergent substrat block hash - chore: remove tests that run in wasm and native, only wasm from now From 3f3222191cbfb153ae3a72ebdcc334a3f4af350f Mon Sep 17 00:00:00 2001 From: antiyro Date: Mon, 4 Dec 2023 15:02:39 +0100 Subject: [PATCH 03/18] cleaned for CI + remove unrelevent settings --- .vscode/settings.json | 7 +- crates/client/rpc/src/lib.rs | 203 +++++++++++++++++--------- starknet-rpc-test/get_spec_version.rs | 27 ++++ 3 files changed, 166 insertions(+), 71 deletions(-) create mode 100644 starknet-rpc-test/get_spec_version.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index dd5f3e78bb..2fc1a1b5fe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,3 @@ { - "eslint.workingDirectories": ["tests"], - "workbench.colorCustomizations": { - "activityBar.background": "#271C7A", - "titleBar.activeBackground": "#3628AB", - "titleBar.activeForeground": "#FBFBFE" - } + "eslint.workingDirectories": ["tests"] } diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index ab460869f4..2ef849ee23 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -311,7 +311,6 @@ where C::Api: StarknetRuntimeApi + ConvertTransactionRuntimeApi, H: HasherT + Send + Sync + 'static, { - /// Get the Most Recent Accepted Block Number /// /// ### Arguments @@ -320,8 +319,7 @@ where /// /// ### Returns /// - /// * `block_number` - The latest block number in the Starknet blockchain. - /// + /// * `block_number` - The latest block number of the current network. fn block_number(&self) -> RpcResult { self.current_block_number() } @@ -334,10 +332,10 @@ where /// /// ### Returns /// - /// * `block_hash_and_number` - A tuple containing the latest block hash and number in the Starknet blockchain. + /// * `block_hash_and_number` - A tuple containing the latest block hash and number of the + /// current network. /// - `block_hash`: The hash of the latest block. /// - `block_number`: The number of the latest block. - /// fn block_hash_and_number(&self) -> RpcResult { let block_number = self.current_block_number()?; let block_hash = self.current_block_hash().map_err(|e| { @@ -355,8 +353,8 @@ where /// /// ### Arguments /// - /// * `block_id` - The identifier of the requested block. This can be the hash of the block, - /// the block's number (height), or a specific block tag. + /// * `block_id` - The identifier of the requested block. This can be the hash of the block, the + /// block's number (height), or a specific block tag. /// /// ### Returns /// @@ -364,8 +362,8 @@ where /// /// ### Errors /// - /// This function may return a `BLOCK_NOT_FOUND` error if the specified block does not exist in the blockchain. - /// + /// This function may return a `BLOCK_NOT_FOUND` error if the specified block does not exist in + /// the blockchain. fn get_block_transaction_count(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -379,17 +377,33 @@ where /// Get the value of the storage at the given address and key. /// - /// This function retrieves the value stored in a specified contract's storage, identified by a contract address and a storage key, within a specified block in the StarkNet network. + /// This function retrieves the value stored in a specified contract's storage, identified by a + /// contract address and a storage key, within a specified block in the current network. /// /// ### Arguments /// - /// * `contract_address` - The address of the contract to read from. This parameter identifies the contract whose storage is being queried. - /// * `key` - The key to the storage value for the given contract. This parameter specifies the particular storage slot to be queried. - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter defines the state of the blockchain at which the storage value is to be read. + /// * `contract_address` - The address of the contract to read from. This parameter identifies + /// the contract whose storage is being queried. + /// * `key` - The key to the storage value for the given contract. This parameter specifies the + /// particular storage slot to be queried. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter defines the state of the blockchain at which the storage + /// value is to be read. /// /// ### Returns /// - /// Returns the value at the given key for the given contract, represented as a `FieldElement`. If no value is found at the specified storage key, returns 0. In case of errors, such as `CONTRACT_NOT_FOUND` or `BLOCK_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the specific issue. + /// Returns the value at the given key for the given contract, represented as a `FieldElement`. + /// If no value is found at the specified storage key, returns 0. + /// + /// ### Errors + /// + /// This function may return errors in the following cases: + /// + /// * `BLOCK_NOT_FOUND` - If the specified block does not exist in the blockchain. + /// * `CONTRACT_NOT_FOUND` - If the specified contract does not exist or is not deployed at the + /// given `contract_address` in the specified block. + /// * `STORAGE_KEY_NOT_FOUND` - If the specified storage key does not exist within the given + /// contract. fn get_storage_at(&self, contract_address: FieldElement, key: FieldElement, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -411,18 +425,20 @@ where Ok(Felt(Felt252Wrapper::from(value).into())) } - /// Call a Function in a Contract Without Creating a Starknet Transaction + /// Call a Function in a Contract Without Creating a Transaction /// /// ### Arguments /// - /// * `request` - The details of the function call to be made. This includes information such as the - /// contract address, function signature, and arguments. - /// * `block_id` - The identifier of the block used to reference the state or call the transaction on. - /// This can be the hash of the block, its number (height), or a specific block tag. + /// * `request` - The details of the function call to be made. This includes information such as + /// the contract address, function signature, and arguments. + /// * `block_id` - The identifier of the block used to reference the state or call the + /// transaction on. This can be the hash of the block, its number (height), or a specific + /// block tag. /// /// ### Returns /// - /// * `result` - The function's return value, as defined in the Cairo output. This is an array of field elements (`Felt`). + /// * `result` - The function's return value, as defined in the Cairo output. This is an array + /// of field elements (`Felt`). /// /// ### Errors /// @@ -430,7 +446,6 @@ where /// * `CONTRACT_NOT_FOUND` - If the specified contract address does not exist. /// * `CONTRACT_ERROR` - If there is an error with the contract or the function call. /// * `BLOCK_NOT_FOUND` - If the specified block does not exist in the blockchain. - /// fn call(&self, request: FunctionCall, block_id: BlockId) -> RpcResult> { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -462,21 +477,21 @@ where /// /// ### Arguments /// - /// * `block_id` - The identifier of the block. This can be the hash of the block, its number (height), - /// or a specific block tag. + /// * `block_id` - The identifier of the block. This can be the hash of the block, its number + /// (height), or a specific block tag. /// * `contract_address` - The address of the contract whose class definition will be returned. /// /// ### Returns /// - /// * `contract_class` - The contract class definition. This may be either a standard contract class - /// or a deprecated contract class, depending on the contract's status and the blockchain's version. + /// * `contract_class` - The contract class definition. This may be either a standard contract + /// class or a deprecated contract class, depending on the contract's status and the + /// blockchain's version. /// /// ### Errors /// /// This method may return the following errors: /// * `BLOCK_NOT_FOUND` - If the specified block does not exist in the blockchain. /// * `CONTRACT_NOT_FOUND` - If the specified contract address does not exist. - /// fn get_class_at(&self, block_id: BlockId, contract_address: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -538,11 +553,13 @@ where /// /// ### Returns /// - /// * `Syncing` - An Enum that can either be a `mc_rpc_core::SyncStatus` struct representing the sync status, - /// or a `Boolean` (`false`) indicating that the node is not currently synchronizing. - /// - /// This is an asynchronous function due to its reliance on `sync_service.best_seen_block()`, - /// which potentially involves network communication and processing to determine the best block seen by the sync service. + /// * `Syncing` - An Enum that can either be a `mc_rpc_core::SyncStatus` struct representing the + /// sync status, or a `Boolean` (`false`) indicating that the node is not currently + /// synchronizing. + /// + /// This is an asynchronous function due to its reliance on `sync_service.best_seen_block()`, + /// which potentially involves network communication and processing to determine the best block + /// seen by the sync service. async fn syncing(&self) -> RpcResult { // obtain best seen (highest) block number match self.sync_service.best_seen_block().await { @@ -604,12 +621,14 @@ where /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. /// * `class_hash` - The hash of the requested contract class. /// /// ### Returns /// - /// Returns the contract class definition if found. In case of an error, returns a `StarknetRpcApiError` indicating either `BlockNotFound` or `ClassHashNotFound`. + /// Returns the contract class definition if found. In case of an error, returns a + /// `StarknetRpcApiError` indicating either `BlockNotFound` or `ClassHashNotFound`. fn get_class(&self, block_id: BlockId, class_hash: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -637,11 +656,13 @@ where /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. /// /// ### Returns /// - /// Returns block information with transaction hashes. This includes either a confirmed block or a pending block with transaction hashes, depending on the state of the requested block. + /// Returns block information with transaction hashes. This includes either a confirmed block or + /// a pending block with transaction hashes, depending on the state of the requested block. /// In case the block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. fn get_block_with_tx_hashes(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { @@ -688,13 +709,18 @@ where /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter specifies the block in which the nonce is to be checked. - /// * `contract_address` - The address of the contract whose nonce we're seeking. This is the unique identifier of the contract in the Starknet network. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter specifies the block in which the nonce is to be checked. + /// * `contract_address` - The address of the contract whose nonce we're seeking. This is the + /// unique identifier of the contract in the Starknet network. /// /// ### Returns /// - /// Returns the contract's nonce at the requested state. The nonce is returned as a `FieldElement`, representing the current state of the contract in terms of transactions count or other contract-specific operations. - /// In case of errors, such as `BLOCK_NOT_FOUND` or `CONTRACT_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the specific issue. + /// Returns the contract's nonce at the requested state. The nonce is returned as a + /// `FieldElement`, representing the current state of the contract in terms of transactions + /// count or other contract-specific operations. In case of errors, such as + /// `BLOCK_NOT_FOUND` or `CONTRACT_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the + /// specific issue. fn get_nonce(&self, block_id: BlockId, contract_address: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -717,7 +743,9 @@ where /// Return the currently configured chain id. /// - /// This function provides the chain id for the network that the node is connected to. The chain id is a unique identifier that distinguishes between different networks, such as mainnet or testnet. + /// This function provides the chain id for the network that the node is connected to. The chain + /// id is a unique identifier that distinguishes between different networks, such as mainnet or + /// testnet. /// /// ### Arguments /// @@ -725,7 +753,8 @@ where /// /// ### Returns /// - /// Returns the chain id this node is connected to. The chain id is returned as a specific type, defined by the Starknet protocol, indicating the particular network. + /// Returns the chain id this node is connected to. The chain id is returned as a specific type, + /// defined by the Starknet protocol, indicating the particular network. fn chain_id(&self) -> RpcResult { let best_block_hash = self.client.info().best_hash; let chain_id = self.client.runtime_api().chain_id(best_block_hash).map_err(|e| { @@ -802,16 +831,25 @@ where /// Get the details of a transaction by a given block id and index. /// - /// This function fetches the details of a specific transaction in the StarkNet network by identifying it through its block and position (index) within that block. If no transaction is found at the specified index, null is returned. + /// This function fetches the details of a specific transaction in the StarkNet network by + /// identifying it through its block and position (index) within that block. If no transaction + /// is found at the specified index, null is returned. /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter is used to specify the block in which the transaction is located. - /// * `index` - An integer representing the index in the block where the transaction is expected to be found. The index starts from 0 and increases sequentially for each transaction in the block. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter is used to specify the block in which the transaction is + /// located. + /// * `index` - An integer representing the index in the block where the transaction is expected + /// to be found. The index starts from 0 and increases sequentially for each transaction in + /// the block. /// /// ### Returns /// - /// Returns the details of the transaction if found, including the transaction hash. The transaction details are returned as a type conforming to the StarkNet protocol. In case of errors like `BLOCK_NOT_FOUND` or `INVALID_TXN_INDEX`, returns a `StarknetRpcApiError` indicating the specific issue. + /// Returns the details of the transaction if found, including the transaction hash. The + /// transaction details are returned as a type conforming to the StarkNet protocol. In case of + /// errors like `BLOCK_NOT_FOUND` or `INVALID_TXN_INDEX`, returns a `StarknetRpcApiError` + /// indicating the specific issue. fn get_transaction_by_block_id_and_index(&self, block_id: BlockId, index: u64) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -849,15 +887,22 @@ where /// Get block information with full transactions given the block id. /// - /// This function retrieves detailed information about a specific block in the StarkNet network, including all transactions contained within that block. The block is identified using its unique block id, which can be the block's hash, its number (height), or a block tag. + /// This function retrieves detailed information about a specific block in the StarkNet network, + /// including all transactions contained within that block. The block is identified using its + /// unique block id, which can be the block's hash, its number (height), or a block tag. /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter is used to specify the block from which to retrieve information and transactions. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter is used to specify the block from which to retrieve + /// information and transactions. /// /// ### Returns /// - /// Returns detailed block information along with full transactions. Depending on the state of the block, this can include either a confirmed block or a pending block with its transactions. In case the specified block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. + /// Returns detailed block information along with full transactions. Depending on the state of + /// the block, this can include either a confirmed block or a pending block with its + /// transactions. In case the specified block is not found, returns a `StarknetRpcApiError` with + /// `BlockNotFound`. fn get_block_with_txs(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("Block not found: '{e}'"); @@ -911,15 +956,22 @@ where /// Get the information about the result of executing the requested block. /// - /// This function fetches details about the state update resulting from executing a specific block in the StarkNet network. The block is identified using its unique block id, which can be the block's hash, its number (height), or a block tag. + /// This function fetches details about the state update resulting from executing a specific + /// block in the StarkNet network. The block is identified using its unique block id, which can + /// be the block's hash, its number (height), or a block tag. /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter specifies the block for which the state update information is required. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter specifies the block for which the state update information + /// is required. /// /// ### Returns /// - /// Returns information about the state update of the requested block, including any changes to the state of the network as a result of the block's execution. This can include a confirmed state update or a pending state update. If the block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. + /// Returns information about the state update of the requested block, including any changes to + /// the state of the network as a result of the block's execution. This can include a confirmed + /// state update or a pending state update. If the block is not found, returns a + /// `StarknetRpcApiError` with `BlockNotFound`. fn get_state_update(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -958,7 +1010,8 @@ where }) } - /// TODO: Transaction Status API: Added starknet_getTransactionStatus and removed starknet_pendingTransactions. + /// 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; @@ -997,16 +1050,24 @@ where /// Returns all events matching the given filter. /// - /// This function retrieves all event objects that match the conditions specified in the provided event filter. The filter can include various criteria such as contract addresses, event types, and block ranges. The function supports pagination through the result page request schema. + /// This function retrieves all event objects that match the conditions specified in the + /// provided event filter. The filter can include various criteria such as contract addresses, + /// event types, and block ranges. The function supports pagination through the result page + /// request schema. /// /// ### Arguments /// - /// * `filter` - The conditions used to filter the returned events. The filter is a combination of an event filter and a result page request, allowing for precise control over which events are returned and in what quantity. + /// * `filter` - The conditions used to filter the returned events. The filter is a combination + /// of an event filter and a result page request, allowing for precise control over which + /// events are returned and in what quantity. /// /// ### Returns /// - /// Returns a chunk of event objects that match the filter criteria, encapsulated in an `EventsChunk` type. The chunk includes details about the events, such as their data, the block in which they occurred, and the transaction that triggered them. - /// In case of errors, such as `PAGE_SIZE_TOO_BIG`, `INVALID_CONTINUATION_TOKEN`, `BLOCK_NOT_FOUND`, or `TOO_MANY_KEYS_IN_FILTER`, returns a `StarknetRpcApiError` indicating the specific issue. + /// Returns a chunk of event objects that match the filter criteria, encapsulated in an + /// `EventsChunk` type. The chunk includes details about the events, such as their data, the + /// block in which they occurred, and the transaction that triggered them. In case of + /// errors, such as `PAGE_SIZE_TOO_BIG`, `INVALID_CONTINUATION_TOKEN`, `BLOCK_NOT_FOUND`, or + /// `TOO_MANY_KEYS_IN_FILTER`, returns a `StarknetRpcApiError` indicating the specific issue. async fn get_events(&self, filter: EventFilterWithPage) -> RpcResult { let continuation_token = match filter.result_page_request.continuation_token { Some(token) => types::ContinuationToken::parse(token).map_err(|e| { @@ -1060,16 +1121,22 @@ where /// Get the details and status of a submitted transaction. /// - /// This function retrieves the detailed information and status of a transaction identified by its hash. The transaction hash uniquely identifies a specific transaction that has been submitted to the StarkNet network. + /// This function retrieves the detailed information and status of a transaction identified by + /// its hash. The transaction hash uniquely identifies a specific transaction that has been + /// submitted to the StarkNet network. /// /// ### Arguments /// - /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the transaction for which details and status are requested. + /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the + /// transaction for which details and status are requested. /// /// ### Returns /// - /// Returns information about the requested transaction, including its status, sender, recipient, and other transaction details. The information is encapsulated in a `Transaction` type, which is a combination of the `TXN` schema and additional properties, such as the `transaction_hash`. - /// In case the specified transaction hash is not found, returns a `StarknetRpcApiError` with `TXN_HASH_NOT_FOUND`. + /// Returns information about the requested transaction, including its status, sender, + /// recipient, and other transaction details. The information is encapsulated in a `Transaction` + /// type, which is a combination of the `TXN` schema and additional properties, such as the + /// `transaction_hash`. In case the specified transaction hash is not found, returns a + /// `StarknetRpcApiError` with `TXN_HASH_NOT_FOUND`. /// /// ### Errors /// @@ -1077,7 +1144,8 @@ where /// - `PAGE_SIZE_TOO_BIG` if the requested page size exceeds the allowed limit. /// - `INVALID_CONTINUATION_TOKEN` if the provided continuation token is invalid or expired. /// - `BLOCK_NOT_FOUND` if the specified block is not found. - /// - `TOO_MANY_KEYS_IN_FILTER` if there are too many keys in the filter, which may exceed the system's capacity. + /// - `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 .backend @@ -1115,21 +1183,26 @@ where /// Get the transaction receipt by the transaction hash. /// - /// This function retrieves the transaction receipt for a specific transaction identified by its hash. The transaction receipt includes information about the execution status of the transaction, events generated during its execution, and other relevant details. + /// This function retrieves the transaction receipt for a specific transaction identified by its + /// hash. The transaction receipt includes information about the execution status of the + /// transaction, events generated during its execution, and other relevant details. /// /// ### Arguments /// - /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the transaction for which the receipt is requested. + /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the + /// transaction for which the receipt is requested. /// /// ### Returns /// /// Returns a transaction receipt, which can be one of two types: /// - `TransactionReceipt` if the transaction has been processed and has a receipt. - /// - `PendingTransactionReceipt` if the transaction is pending and the receipt is not yet available. + /// - `PendingTransactionReceipt` if the transaction is pending and the receipt is not yet + /// available. /// /// ### Errors /// - /// The function may return a `TXN_HASH_NOT_FOUND` error if the specified transaction hash is not found. + /// The function may return a `TXN_HASH_NOT_FOUND` error if the specified transaction hash is + /// not found. async fn get_transaction_receipt( &self, transaction_hash: FieldElement, diff --git a/starknet-rpc-test/get_spec_version.rs b/starknet-rpc-test/get_spec_version.rs new file mode 100644 index 0000000000..0e5b392626 --- /dev/null +++ b/starknet-rpc-test/get_spec_version.rs @@ -0,0 +1,27 @@ +extern crate starknet_rpc_test; + +use rstest::rstest; +use starknet_providers::Provider; +use starknet_rpc_test::fixtures::{madara, ThreadSafeMadaraClient}; + +#[rstest] +#[tokio::test] +async fn work_ok_up_to_1000(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { + let rpc = madara.get_starknet_client().await; + + { + let mut madara_write_lock = madara.write().await; + let block_number = rpc.block_number().await?; + + madara_write_lock.create_empty_block().await?; + assert_eq!(rpc.block_number().await?, 1 + block_number); + + madara_write_lock.run_to_block(block_number + 20).await?; + assert_eq!(rpc.block_number().await?, 20 + block_number); + + madara_write_lock.create_n_blocks(4).await?; + assert_eq!(rpc.block_number().await?, 24 + block_number); + } + + Ok(()) +} From c5698661456fe70de62efa82fbdf0e8096198058 Mon Sep 17 00:00:00 2001 From: antiyro Date: Mon, 4 Dec 2023 16:33:24 +0100 Subject: [PATCH 04/18] feat(rpc): add starknet_specVersion rpc implemented in v0.5.1 --- .vscode/settings.json | 7 +- crates/client/rpc-core/src/lib.rs | 4 + crates/client/rpc/src/lib.rs | 216 ++++++++++++++++++++--------- starknet-rpc-test/Cargo.toml | 4 + starknet-rpc-test/spec_version.rs | 17 +++ starknet-rpc-test/src/constants.rs | 2 + 6 files changed, 182 insertions(+), 68 deletions(-) create mode 100644 starknet-rpc-test/spec_version.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index dd5f3e78bb..2fc1a1b5fe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,3 @@ { - "eslint.workingDirectories": ["tests"], - "workbench.colorCustomizations": { - "activityBar.background": "#271C7A", - "titleBar.activeBackground": "#3628AB", - "titleBar.activeForeground": "#FBFBFE" - } + "eslint.workingDirectories": ["tests"] } diff --git a/crates/client/rpc-core/src/lib.rs b/crates/client/rpc-core/src/lib.rs index 0e9d4a6759..28cf13cc2f 100644 --- a/crates/client/rpc-core/src/lib.rs +++ b/crates/client/rpc-core/src/lib.rs @@ -55,6 +55,10 @@ pub trait StarknetWriteRpcApi { /// Starknet rpc interface. #[rpc(server, namespace = "starknet")] pub trait StarknetReadRpcApi { + /// Get the Version of the StarkNet JSON-RPC Specification Being Used + #[method(name = "specVersion")] + fn spec_version(&self) -> RpcResult; + /// Get the most recent accepted block number #[method(name = "blockNumber")] fn block_number(&self) -> RpcResult; diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index ab460869f4..dd52ca8f01 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -100,6 +100,16 @@ where } } +impl Starknet +where + B: BlockT, + C: HeaderBackend + 'static, +{ + pub fn current_spec_version(&self) -> RpcResult { + Ok("0.4.0".to_string()) + } +} + impl Starknet where B: BlockT, @@ -311,6 +321,22 @@ where C::Api: StarknetRuntimeApi + ConvertTransactionRuntimeApi, H: HasherT + Send + Sync + 'static, { + /// Returns the Version of the StarkNet JSON-RPC Specification Being Used + /// + /// This method provides the version of the StarkNet JSON-RPC specification that the node is + /// currently using. The version is returned as a semantic versioning (SemVer) string. + /// + /// # Arguments + /// + /// This method does not take any arguments. + /// + /// # Returns + /// + /// * `spec_version` - A string representing the SemVer of the StarkNet JSON-RPC specification + /// being used. + fn spec_version(&self) -> RpcResult { + self.current_spec_version() + } /// Get the Most Recent Accepted Block Number /// @@ -321,7 +347,6 @@ where /// ### Returns /// /// * `block_number` - The latest block number in the Starknet blockchain. - /// fn block_number(&self) -> RpcResult { self.current_block_number() } @@ -334,10 +359,10 @@ where /// /// ### Returns /// - /// * `block_hash_and_number` - A tuple containing the latest block hash and number in the Starknet blockchain. + /// * `block_hash_and_number` - A tuple containing the latest block hash and number in the + /// Starknet blockchain. /// - `block_hash`: The hash of the latest block. /// - `block_number`: The number of the latest block. - /// fn block_hash_and_number(&self) -> RpcResult { let block_number = self.current_block_number()?; let block_hash = self.current_block_hash().map_err(|e| { @@ -355,8 +380,8 @@ where /// /// ### Arguments /// - /// * `block_id` - The identifier of the requested block. This can be the hash of the block, - /// the block's number (height), or a specific block tag. + /// * `block_id` - The identifier of the requested block. This can be the hash of the block, the + /// block's number (height), or a specific block tag. /// /// ### Returns /// @@ -364,8 +389,8 @@ where /// /// ### Errors /// - /// This function may return a `BLOCK_NOT_FOUND` error if the specified block does not exist in the blockchain. - /// + /// This function may return a `BLOCK_NOT_FOUND` error if the specified block does not exist in + /// the blockchain. fn get_block_transaction_count(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -379,17 +404,25 @@ where /// Get the value of the storage at the given address and key. /// - /// This function retrieves the value stored in a specified contract's storage, identified by a contract address and a storage key, within a specified block in the StarkNet network. + /// This function retrieves the value stored in a specified contract's storage, identified by a + /// contract address and a storage key, within a specified block in the StarkNet network. /// /// ### Arguments /// - /// * `contract_address` - The address of the contract to read from. This parameter identifies the contract whose storage is being queried. - /// * `key` - The key to the storage value for the given contract. This parameter specifies the particular storage slot to be queried. - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter defines the state of the blockchain at which the storage value is to be read. + /// * `contract_address` - The address of the contract to read from. This parameter identifies + /// the contract whose storage is being queried. + /// * `key` - The key to the storage value for the given contract. This parameter specifies the + /// particular storage slot to be queried. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter defines the state of the blockchain at which the storage + /// value is to be read. /// /// ### Returns /// - /// Returns the value at the given key for the given contract, represented as a `FieldElement`. If no value is found at the specified storage key, returns 0. In case of errors, such as `CONTRACT_NOT_FOUND` or `BLOCK_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the specific issue. + /// Returns the value at the given key for the given contract, represented as a `FieldElement`. + /// If no value is found at the specified storage key, returns 0. In case of errors, such as + /// `CONTRACT_NOT_FOUND` or `BLOCK_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the + /// specific issue. fn get_storage_at(&self, contract_address: FieldElement, key: FieldElement, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -415,14 +448,16 @@ where /// /// ### Arguments /// - /// * `request` - The details of the function call to be made. This includes information such as the - /// contract address, function signature, and arguments. - /// * `block_id` - The identifier of the block used to reference the state or call the transaction on. - /// This can be the hash of the block, its number (height), or a specific block tag. + /// * `request` - The details of the function call to be made. This includes information such as + /// the contract address, function signature, and arguments. + /// * `block_id` - The identifier of the block used to reference the state or call the + /// transaction on. This can be the hash of the block, its number (height), or a specific + /// block tag. /// /// ### Returns /// - /// * `result` - The function's return value, as defined in the Cairo output. This is an array of field elements (`Felt`). + /// * `result` - The function's return value, as defined in the Cairo output. This is an array + /// of field elements (`Felt`). /// /// ### Errors /// @@ -430,7 +465,6 @@ where /// * `CONTRACT_NOT_FOUND` - If the specified contract address does not exist. /// * `CONTRACT_ERROR` - If there is an error with the contract or the function call. /// * `BLOCK_NOT_FOUND` - If the specified block does not exist in the blockchain. - /// fn call(&self, request: FunctionCall, block_id: BlockId) -> RpcResult> { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -462,21 +496,21 @@ where /// /// ### Arguments /// - /// * `block_id` - The identifier of the block. This can be the hash of the block, its number (height), - /// or a specific block tag. + /// * `block_id` - The identifier of the block. This can be the hash of the block, its number + /// (height), or a specific block tag. /// * `contract_address` - The address of the contract whose class definition will be returned. /// /// ### Returns /// - /// * `contract_class` - The contract class definition. This may be either a standard contract class - /// or a deprecated contract class, depending on the contract's status and the blockchain's version. + /// * `contract_class` - The contract class definition. This may be either a standard contract + /// class or a deprecated contract class, depending on the contract's status and the + /// blockchain's version. /// /// ### Errors /// /// This method may return the following errors: /// * `BLOCK_NOT_FOUND` - If the specified block does not exist in the blockchain. /// * `CONTRACT_NOT_FOUND` - If the specified contract address does not exist. - /// fn get_class_at(&self, block_id: BlockId, contract_address: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -538,11 +572,13 @@ where /// /// ### Returns /// - /// * `Syncing` - An Enum that can either be a `mc_rpc_core::SyncStatus` struct representing the sync status, - /// or a `Boolean` (`false`) indicating that the node is not currently synchronizing. - /// - /// This is an asynchronous function due to its reliance on `sync_service.best_seen_block()`, - /// which potentially involves network communication and processing to determine the best block seen by the sync service. + /// * `Syncing` - An Enum that can either be a `mc_rpc_core::SyncStatus` struct representing the + /// sync status, or a `Boolean` (`false`) indicating that the node is not currently + /// synchronizing. + /// + /// This is an asynchronous function due to its reliance on `sync_service.best_seen_block()`, + /// which potentially involves network communication and processing to determine the best block + /// seen by the sync service. async fn syncing(&self) -> RpcResult { // obtain best seen (highest) block number match self.sync_service.best_seen_block().await { @@ -604,12 +640,14 @@ where /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. /// * `class_hash` - The hash of the requested contract class. /// /// ### Returns /// - /// Returns the contract class definition if found. In case of an error, returns a `StarknetRpcApiError` indicating either `BlockNotFound` or `ClassHashNotFound`. + /// Returns the contract class definition if found. In case of an error, returns a + /// `StarknetRpcApiError` indicating either `BlockNotFound` or `ClassHashNotFound`. fn get_class(&self, block_id: BlockId, class_hash: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -637,11 +675,13 @@ where /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. /// /// ### Returns /// - /// Returns block information with transaction hashes. This includes either a confirmed block or a pending block with transaction hashes, depending on the state of the requested block. + /// Returns block information with transaction hashes. This includes either a confirmed block or + /// a pending block with transaction hashes, depending on the state of the requested block. /// In case the block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. fn get_block_with_tx_hashes(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { @@ -688,13 +728,18 @@ where /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter specifies the block in which the nonce is to be checked. - /// * `contract_address` - The address of the contract whose nonce we're seeking. This is the unique identifier of the contract in the Starknet network. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter specifies the block in which the nonce is to be checked. + /// * `contract_address` - The address of the contract whose nonce we're seeking. This is the + /// unique identifier of the contract in the Starknet network. /// /// ### Returns /// - /// Returns the contract's nonce at the requested state. The nonce is returned as a `FieldElement`, representing the current state of the contract in terms of transactions count or other contract-specific operations. - /// In case of errors, such as `BLOCK_NOT_FOUND` or `CONTRACT_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the specific issue. + /// Returns the contract's nonce at the requested state. The nonce is returned as a + /// `FieldElement`, representing the current state of the contract in terms of transactions + /// count or other contract-specific operations. In case of errors, such as + /// `BLOCK_NOT_FOUND` or `CONTRACT_NOT_FOUND`, returns a `StarknetRpcApiError` indicating the + /// specific issue. fn get_nonce(&self, block_id: BlockId, contract_address: FieldElement) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -717,7 +762,9 @@ where /// Return the currently configured chain id. /// - /// This function provides the chain id for the network that the node is connected to. The chain id is a unique identifier that distinguishes between different networks, such as mainnet or testnet. + /// This function provides the chain id for the network that the node is connected to. The chain + /// id is a unique identifier that distinguishes between different networks, such as mainnet or + /// testnet. /// /// ### Arguments /// @@ -725,7 +772,8 @@ where /// /// ### Returns /// - /// Returns the chain id this node is connected to. The chain id is returned as a specific type, defined by the Starknet protocol, indicating the particular network. + /// Returns the chain id this node is connected to. The chain id is returned as a specific type, + /// defined by the Starknet protocol, indicating the particular network. fn chain_id(&self) -> RpcResult { let best_block_hash = self.client.info().best_hash; let chain_id = self.client.runtime_api().chain_id(best_block_hash).map_err(|e| { @@ -802,16 +850,25 @@ where /// Get the details of a transaction by a given block id and index. /// - /// This function fetches the details of a specific transaction in the StarkNet network by identifying it through its block and position (index) within that block. If no transaction is found at the specified index, null is returned. + /// This function fetches the details of a specific transaction in the StarkNet network by + /// identifying it through its block and position (index) within that block. If no transaction + /// is found at the specified index, null is returned. /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter is used to specify the block in which the transaction is located. - /// * `index` - An integer representing the index in the block where the transaction is expected to be found. The index starts from 0 and increases sequentially for each transaction in the block. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter is used to specify the block in which the transaction is + /// located. + /// * `index` - An integer representing the index in the block where the transaction is expected + /// to be found. The index starts from 0 and increases sequentially for each transaction in + /// the block. /// /// ### Returns /// - /// Returns the details of the transaction if found, including the transaction hash. The transaction details are returned as a type conforming to the StarkNet protocol. In case of errors like `BLOCK_NOT_FOUND` or `INVALID_TXN_INDEX`, returns a `StarknetRpcApiError` indicating the specific issue. + /// Returns the details of the transaction if found, including the transaction hash. The + /// transaction details are returned as a type conforming to the StarkNet protocol. In case of + /// errors like `BLOCK_NOT_FOUND` or `INVALID_TXN_INDEX`, returns a `StarknetRpcApiError` + /// indicating the specific issue. fn get_transaction_by_block_id_and_index(&self, block_id: BlockId, index: u64) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -849,15 +906,22 @@ where /// Get block information with full transactions given the block id. /// - /// This function retrieves detailed information about a specific block in the StarkNet network, including all transactions contained within that block. The block is identified using its unique block id, which can be the block's hash, its number (height), or a block tag. + /// This function retrieves detailed information about a specific block in the StarkNet network, + /// including all transactions contained within that block. The block is identified using its + /// unique block id, which can be the block's hash, its number (height), or a block tag. /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter is used to specify the block from which to retrieve information and transactions. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter is used to specify the block from which to retrieve + /// information and transactions. /// /// ### Returns /// - /// Returns detailed block information along with full transactions. Depending on the state of the block, this can include either a confirmed block or a pending block with its transactions. In case the specified block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. + /// Returns detailed block information along with full transactions. Depending on the state of + /// the block, this can include either a confirmed block or a pending block with its + /// transactions. In case the specified block is not found, returns a `StarknetRpcApiError` with + /// `BlockNotFound`. fn get_block_with_txs(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("Block not found: '{e}'"); @@ -911,15 +975,22 @@ where /// Get the information about the result of executing the requested block. /// - /// This function fetches details about the state update resulting from executing a specific block in the StarkNet network. The block is identified using its unique block id, which can be the block's hash, its number (height), or a block tag. + /// This function fetches details about the state update resulting from executing a specific + /// block in the StarkNet network. The block is identified using its unique block id, which can + /// be the block's hash, its number (height), or a block tag. /// /// ### Arguments /// - /// * `block_id` - The hash of the requested block, or number (height) of the requested block, or a block tag. This parameter specifies the block for which the state update information is required. + /// * `block_id` - The hash of the requested block, or number (height) of the requested block, + /// or a block tag. This parameter specifies the block for which the state update information + /// is required. /// /// ### Returns /// - /// Returns information about the state update of the requested block, including any changes to the state of the network as a result of the block's execution. This can include a confirmed state update or a pending state update. If the block is not found, returns a `StarknetRpcApiError` with `BlockNotFound`. + /// Returns information about the state update of the requested block, including any changes to + /// the state of the network as a result of the block's execution. This can include a confirmed + /// state update or a pending state update. If the block is not found, returns a + /// `StarknetRpcApiError` with `BlockNotFound`. fn get_state_update(&self, block_id: BlockId) -> RpcResult { let substrate_block_hash = self.substrate_block_hash_from_starknet_block(block_id).map_err(|e| { error!("'{e}'"); @@ -958,7 +1029,8 @@ where }) } - /// TODO: Transaction Status API: Added starknet_getTransactionStatus and removed starknet_pendingTransactions. + /// 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; @@ -997,16 +1069,24 @@ where /// Returns all events matching the given filter. /// - /// This function retrieves all event objects that match the conditions specified in the provided event filter. The filter can include various criteria such as contract addresses, event types, and block ranges. The function supports pagination through the result page request schema. + /// This function retrieves all event objects that match the conditions specified in the + /// provided event filter. The filter can include various criteria such as contract addresses, + /// event types, and block ranges. The function supports pagination through the result page + /// request schema. /// /// ### Arguments /// - /// * `filter` - The conditions used to filter the returned events. The filter is a combination of an event filter and a result page request, allowing for precise control over which events are returned and in what quantity. + /// * `filter` - The conditions used to filter the returned events. The filter is a combination + /// of an event filter and a result page request, allowing for precise control over which + /// events are returned and in what quantity. /// /// ### Returns /// - /// Returns a chunk of event objects that match the filter criteria, encapsulated in an `EventsChunk` type. The chunk includes details about the events, such as their data, the block in which they occurred, and the transaction that triggered them. - /// In case of errors, such as `PAGE_SIZE_TOO_BIG`, `INVALID_CONTINUATION_TOKEN`, `BLOCK_NOT_FOUND`, or `TOO_MANY_KEYS_IN_FILTER`, returns a `StarknetRpcApiError` indicating the specific issue. + /// Returns a chunk of event objects that match the filter criteria, encapsulated in an + /// `EventsChunk` type. The chunk includes details about the events, such as their data, the + /// block in which they occurred, and the transaction that triggered them. In case of + /// errors, such as `PAGE_SIZE_TOO_BIG`, `INVALID_CONTINUATION_TOKEN`, `BLOCK_NOT_FOUND`, or + /// `TOO_MANY_KEYS_IN_FILTER`, returns a `StarknetRpcApiError` indicating the specific issue. async fn get_events(&self, filter: EventFilterWithPage) -> RpcResult { let continuation_token = match filter.result_page_request.continuation_token { Some(token) => types::ContinuationToken::parse(token).map_err(|e| { @@ -1060,16 +1140,22 @@ where /// Get the details and status of a submitted transaction. /// - /// This function retrieves the detailed information and status of a transaction identified by its hash. The transaction hash uniquely identifies a specific transaction that has been submitted to the StarkNet network. + /// This function retrieves the detailed information and status of a transaction identified by + /// its hash. The transaction hash uniquely identifies a specific transaction that has been + /// submitted to the StarkNet network. /// /// ### Arguments /// - /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the transaction for which details and status are requested. + /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the + /// transaction for which details and status are requested. /// /// ### Returns /// - /// Returns information about the requested transaction, including its status, sender, recipient, and other transaction details. The information is encapsulated in a `Transaction` type, which is a combination of the `TXN` schema and additional properties, such as the `transaction_hash`. - /// In case the specified transaction hash is not found, returns a `StarknetRpcApiError` with `TXN_HASH_NOT_FOUND`. + /// Returns information about the requested transaction, including its status, sender, + /// recipient, and other transaction details. The information is encapsulated in a `Transaction` + /// type, which is a combination of the `TXN` schema and additional properties, such as the + /// `transaction_hash`. In case the specified transaction hash is not found, returns a + /// `StarknetRpcApiError` with `TXN_HASH_NOT_FOUND`. /// /// ### Errors /// @@ -1077,7 +1163,8 @@ where /// - `PAGE_SIZE_TOO_BIG` if the requested page size exceeds the allowed limit. /// - `INVALID_CONTINUATION_TOKEN` if the provided continuation token is invalid or expired. /// - `BLOCK_NOT_FOUND` if the specified block is not found. - /// - `TOO_MANY_KEYS_IN_FILTER` if there are too many keys in the filter, which may exceed the system's capacity. + /// - `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 .backend @@ -1115,21 +1202,26 @@ where /// Get the transaction receipt by the transaction hash. /// - /// This function retrieves the transaction receipt for a specific transaction identified by its hash. The transaction receipt includes information about the execution status of the transaction, events generated during its execution, and other relevant details. + /// This function retrieves the transaction receipt for a specific transaction identified by its + /// hash. The transaction receipt includes information about the execution status of the + /// transaction, events generated during its execution, and other relevant details. /// /// ### Arguments /// - /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the transaction for which the receipt is requested. + /// * `transaction_hash` - The hash of the requested transaction. This parameter specifies the + /// transaction for which the receipt is requested. /// /// ### Returns /// /// Returns a transaction receipt, which can be one of two types: /// - `TransactionReceipt` if the transaction has been processed and has a receipt. - /// - `PendingTransactionReceipt` if the transaction is pending and the receipt is not yet available. + /// - `PendingTransactionReceipt` if the transaction is pending and the receipt is not yet + /// available. /// /// ### Errors /// - /// The function may return a `TXN_HASH_NOT_FOUND` error if the specified transaction hash is not found. + /// The function may return a `TXN_HASH_NOT_FOUND` error if the specified transaction hash is + /// not found. async fn get_transaction_receipt( &self, transaction_hash: FieldElement, diff --git a/starknet-rpc-test/Cargo.toml b/starknet-rpc-test/Cargo.toml index 62c614256f..24aaca9d6e 100644 --- a/starknet-rpc-test/Cargo.toml +++ b/starknet-rpc-test/Cargo.toml @@ -25,6 +25,10 @@ thiserror = { workspace = true } tokio = { version = "1.34.0", features = ["rt", "macros", "parking_lot"] } url = "2.4.1" +[[test]] +name = "starknet_spec_version" +path = "spec_version.rs" + [[test]] name = "starknet_get_block_number" path = "get_block_number.rs" diff --git a/starknet-rpc-test/spec_version.rs b/starknet-rpc-test/spec_version.rs new file mode 100644 index 0000000000..f2e329c1a1 --- /dev/null +++ b/starknet-rpc-test/spec_version.rs @@ -0,0 +1,17 @@ +extern crate starknet_rpc_test; + +use rstest::rstest; +use starknet_providers::Provider; +use starknet_rpc_test::constants::SPEC_VERSION; +use starknet_rpc_test::fixtures::{madara, ThreadSafeMadaraClient}; + +#[rstest] +#[tokio::test] +async fn returns_hardcoded_spec_version(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { + let rpc = madara.get_starknet_client().await; + + // TODO: test it when starknet_providers::jsonrpc upgrades to v0.6.0 + assert_eq!(rpc.spec_version().await?, SPEC_VERSION); + + Ok(()) +} diff --git a/starknet-rpc-test/src/constants.rs b/starknet-rpc-test/src/constants.rs index 75681689ae..16157197a9 100644 --- a/starknet-rpc-test/src/constants.rs +++ b/starknet-rpc-test/src/constants.rs @@ -32,3 +32,5 @@ pub const MAX_FEE_OVERRIDE: &str = "0x100000"; /// ChainId for Starknet Goerli testnet pub const SN_GOERLI_CHAIN_ID: FieldElement = FieldElement::from_mont([3753493103916128178, 18446744073709548950, 18446744073709551615, 398700013197595345]); + +pub const SPEC_VERSION: &str = "0.4.0"; From b52c0e4c614047ea5450e59a1c81f237e2ebdd28 Mon Sep 17 00:00:00 2001 From: antiyro Date: Mon, 4 Dec 2023 16:44:18 +0100 Subject: [PATCH 05/18] removed unrelevent test --- starknet-rpc-test/get_spec_version.rs | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 starknet-rpc-test/get_spec_version.rs diff --git a/starknet-rpc-test/get_spec_version.rs b/starknet-rpc-test/get_spec_version.rs deleted file mode 100644 index 0e5b392626..0000000000 --- a/starknet-rpc-test/get_spec_version.rs +++ /dev/null @@ -1,27 +0,0 @@ -extern crate starknet_rpc_test; - -use rstest::rstest; -use starknet_providers::Provider; -use starknet_rpc_test::fixtures::{madara, ThreadSafeMadaraClient}; - -#[rstest] -#[tokio::test] -async fn work_ok_up_to_1000(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { - let rpc = madara.get_starknet_client().await; - - { - let mut madara_write_lock = madara.write().await; - let block_number = rpc.block_number().await?; - - madara_write_lock.create_empty_block().await?; - assert_eq!(rpc.block_number().await?, 1 + block_number); - - madara_write_lock.run_to_block(block_number + 20).await?; - assert_eq!(rpc.block_number().await?, 20 + block_number); - - madara_write_lock.create_n_blocks(4).await?; - assert_eq!(rpc.block_number().await?, 24 + block_number); - } - - Ok(()) -} From 285d8e74258da3f643b70f78b9b4b5a4609380cb Mon Sep 17 00:00:00 2001 From: antiyro Date: Mon, 4 Dec 2023 17:50:06 +0100 Subject: [PATCH 06/18] added ignore to future impl of spec version test --- starknet-rpc-test/spec_version.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/starknet-rpc-test/spec_version.rs b/starknet-rpc-test/spec_version.rs index f2e329c1a1..6c6db4d999 100644 --- a/starknet-rpc-test/spec_version.rs +++ b/starknet-rpc-test/spec_version.rs @@ -7,6 +7,7 @@ use starknet_rpc_test::fixtures::{madara, ThreadSafeMadaraClient}; #[rstest] #[tokio::test] +#[ignore = "Waiting for starknet_providers::jsonrpc upgrade to v0.6.0"] async fn returns_hardcoded_spec_version(madara: &ThreadSafeMadaraClient) -> Result<(), anyhow::Error> { let rpc = madara.get_starknet_client().await; From 30dce1edc53e57bd83f8869474efdf46aad70d59 Mon Sep 17 00:00:00 2001 From: antiyro Date: Mon, 4 Dec 2023 18:11:58 +0100 Subject: [PATCH 07/18] commented future impl of spec version test --- starknet-rpc-test/spec_version.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starknet-rpc-test/spec_version.rs b/starknet-rpc-test/spec_version.rs index 6c6db4d999..41dd9feafe 100644 --- a/starknet-rpc-test/spec_version.rs +++ b/starknet-rpc-test/spec_version.rs @@ -12,7 +12,7 @@ async fn returns_hardcoded_spec_version(madara: &ThreadSafeMadaraClient) -> Resu let rpc = madara.get_starknet_client().await; // TODO: test it when starknet_providers::jsonrpc upgrades to v0.6.0 - assert_eq!(rpc.spec_version().await?, SPEC_VERSION); + // assert_eq!(rpc.spec_version().await?, SPEC_VERSION); Ok(()) } From 587fc382e0eae423b8eaf829fb303a3edafe9f41 Mon Sep 17 00:00:00 2001 From: antiyro Date: Tue, 5 Dec 2023 12:15:21 +0100 Subject: [PATCH 08/18] removed starknet_pendingTransactions method + tests --- crates/client/rpc-core/src/lib.rs | 4 -- crates/client/rpc/src/lib.rs | 38 +---------- starknet-rpc-test/Cargo.toml | 4 -- starknet-rpc-test/pending_transactions.rs | 83 ----------------------- 4 files changed, 1 insertion(+), 128 deletions(-) delete mode 100644 starknet-rpc-test/pending_transactions.rs diff --git a/crates/client/rpc-core/src/lib.rs b/crates/client/rpc-core/src/lib.rs index 28cf13cc2f..caa90966a7 100644 --- a/crates/client/rpc-core/src/lib.rs +++ b/crates/client/rpc-core/src/lib.rs @@ -128,10 +128,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..91bd1ecf92 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -1035,43 +1035,7 @@ 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. /// 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(()) -} From a51c3eae2449cdeef9c1d1dcc1b5a9a799c8ea08 Mon Sep 17 00:00:00 2001 From: antiyro Date: Tue, 5 Dec 2023 18:57:24 +0100 Subject: [PATCH 09/18] implemented starknet_getTransactionStatus - missing formated result --- Cargo.lock | 51 +++++++++--------- crates/client/rpc-core/Cargo.toml | 4 ++ crates/client/rpc-core/src/lib.rs | 8 ++- crates/client/rpc/src/lib.rs | 66 +++++++++++++++++++++-- crates/primitives/transactions/src/lib.rs | 13 ++++- 5 files changed, 112 insertions(+), 30 deletions(-) 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..bdcf3c2d65 100644 --- a/crates/client/rpc-core/Cargo.toml +++ b/crates/client/rpc-core/Cargo.toml @@ -31,6 +31,7 @@ jsonrpsee = { workspace = true, features = [ "macros", ], default-features = true } mp-block = { workspace = true } +mp-transactions = { workspace = true , features = ["serde"] } mp-digest-log = { workspace = true } num-bigint = { workspace = true } serde = { workspace = true, default-features = true } @@ -46,3 +47,6 @@ thiserror = { workspace = true } [dev-dependencies] assert_matches = "1.5.0" + +[features] +serde = ["mp-transactions/serde"] diff --git a/crates/client/rpc-core/src/lib.rs b/crates/client/rpc-core/src/lib.rs index caa90966a7..d2a2ba46c3 100644 --- a/crates/client/rpc-core/src/lib.rs +++ b/crates/client/rpc-core/src/lib.rs @@ -20,9 +20,11 @@ use starknet_core::types::{ BroadcastedInvokeTransaction, BroadcastedTransaction, ContractClass, DeclareTransactionResult, DeployAccountTransactionResult, EventFilterWithPage, EventsPage, FeeEstimate, FieldElement, FunctionCall, InvokeTransactionResult, MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, MaybePendingTransactionReceipt, - StateUpdate, SyncStatusType, Transaction, + StateUpdate, SyncStatusType, Transaction }; +use mp_transactions::TransactionStatus; + #[serde_as] #[derive(Serialize, Deserialize)] pub struct Felt(#[serde_as(as = "UfeHex")] pub FieldElement); @@ -71,6 +73,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; diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index 91bd1ecf92..1f2a2a3e80 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::{UserTransaction, TransactionStatus}; 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, TransactionFinalityStatus, TransactionReceipt }; use crate::constants::{MAX_EVENTS_CHUNK_SIZE, MAX_EVENTS_KEYS}; @@ -400,6 +400,66 @@ where Ok(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 block_hash_from_db = 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 + })?; + + let substrate_block_hash = block_hash_from_db.ok_or(StarknetRpcApiError::TxnHashNotFound)?; + + let 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 find_tx = block.transactions() + .iter() + .find(|tx| tx.compute_hash::(chain_id, false).0 == transaction_hash) + .map(|tx| to_starknet_core_tx(tx.clone(), transaction_hash)) + .ok_or(StarknetRpcApiError::TxnHashNotFound)?; + + let execution_result: ExecutionResult = 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 + })? + .map_or(ExecutionResult::Succeeded, |message| { + ExecutionResult::Reverted { + reason: String::from_utf8(message).unwrap_or_else(|_| "Invalid UTF-8 sequence".to_string()), + } + }); + + Ok(TransactionStatus::AcceptedOnL2(execution_result)) + } + /// Get the value of the storage at the given address and key. /// /// This function retrieves the value stored in a specified contract's storage, identified by a diff --git a/crates/primitives/transactions/src/lib.rs b/crates/primitives/transactions/src/lib.rs index a5c079939c..f2fdb72698 100644 --- a/crates/primitives/transactions/src/lib.rs +++ b/crates/primitives/transactions/src/lib.rs @@ -19,15 +19,26 @@ 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::ExecutionResult; use starknet_ff::FieldElement; const SIMULATE_TX_VERSION_OFFSET: FieldElement = - FieldElement::from_mont([18446744073700081665, 17407, 18446744073709551584, 576460752142434320]); +FieldElement::from_mont([18446744073700081665, 17407, 18446744073709551584, 576460752142434320]); /// Functions related to transaction conversions // pub mod utils; use mp_felt::Felt252Wrapper; +// TODO(antiyro): remove this when released: https://github.com/xJonathanLEI/starknet-rs/blob/7b23df210f9d11fee4784c2546bff59491e2d3a1/starknet-core/src/types/mod.rs#L167 +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TransactionStatus { + Received, + Rejected, + AcceptedOnL2(ExecutionResult), + AcceptedOnL1(ExecutionResult), +} + /// Wrapper type for transaction execution error. /// Different tx types. /// See `https://docs.starknet.io/documentation/architecture_and_concepts/Blocks/transactions/` for more details. From 2fdfa2cedd60e80a5cdf6d1754b85a6078586d4a Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 11:00:19 +0100 Subject: [PATCH 10/18] implemented starknet_getTransactionStatus --- crates/client/rpc-core/src/lib.rs | 5 ++--- crates/client/rpc/src/lib.rs | 16 +++++++++------- crates/primitives/transactions/src/lib.rs | 14 ++++++-------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/crates/client/rpc-core/src/lib.rs b/crates/client/rpc-core/src/lib.rs index d2a2ba46c3..230351d5c1 100644 --- a/crates/client/rpc-core/src/lib.rs +++ b/crates/client/rpc-core/src/lib.rs @@ -14,17 +14,16 @@ 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, BroadcastedInvokeTransaction, BroadcastedTransaction, ContractClass, DeclareTransactionResult, DeployAccountTransactionResult, EventFilterWithPage, EventsPage, FeeEstimate, FieldElement, FunctionCall, InvokeTransactionResult, MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, MaybePendingTransactionReceipt, - StateUpdate, SyncStatusType, Transaction + StateUpdate, SyncStatusType, Transaction, }; -use mp_transactions::TransactionStatus; - #[serde_as] #[derive(Serialize, Deserialize)] pub struct Felt(#[serde_as(as = "UfeHex")] pub FieldElement); diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index 1f2a2a3e80..570d44fb2d 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -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, TransactionFinalityStatus, TransactionReceipt, TransactionExecutionStatus }; 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, @@ -440,7 +441,7 @@ where .map(|tx| to_starknet_core_tx(tx.clone(), transaction_hash)) .ok_or(StarknetRpcApiError::TxnHashNotFound)?; - let execution_result: ExecutionResult = self + let execution_result: TransactionExecutionStatus = self .client .runtime_api() .get_tx_execution_outcome(substrate_block_hash, Felt252Wrapper(transaction_hash).into()) @@ -451,13 +452,14 @@ where ); StarknetRpcApiError::InternalServerError })? - .map_or(ExecutionResult::Succeeded, |message| { - ExecutionResult::Reverted { - reason: String::from_utf8(message).unwrap_or_else(|_| "Invalid UTF-8 sequence".to_string()), - } + .map_or(TransactionExecutionStatus::Succeeded, |message| { + TransactionExecutionStatus::Reverted }); - Ok(TransactionStatus::AcceptedOnL2(execution_result)) + Ok(TransactionStatus { + finality_status: TransactionFinalityStatus::AcceptedOnL2, + execution_status: execution_result + }) } /// Get the value of the storage at the given address and key. diff --git a/crates/primitives/transactions/src/lib.rs b/crates/primitives/transactions/src/lib.rs index f2fdb72698..64c8290b95 100644 --- a/crates/primitives/transactions/src/lib.rs +++ b/crates/primitives/transactions/src/lib.rs @@ -19,24 +19,22 @@ 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::ExecutionResult; +use starknet_core::types::{TransactionExecutionStatus, TransactionFinalityStatus}; use starknet_ff::FieldElement; const SIMULATE_TX_VERSION_OFFSET: FieldElement = -FieldElement::from_mont([18446744073700081665, 17407, 18446744073709551584, 576460752142434320]); + FieldElement::from_mont([18446744073700081665, 17407, 18446744073709551584, 576460752142434320]); /// Functions related to transaction conversions // pub mod utils; use mp_felt::Felt252Wrapper; -// TODO(antiyro): remove this when released: https://github.com/xJonathanLEI/starknet-rs/blob/7b23df210f9d11fee4784c2546bff59491e2d3a1/starknet-core/src/types/mod.rs#L167 +// 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 enum TransactionStatus { - Received, - Rejected, - AcceptedOnL2(ExecutionResult), - AcceptedOnL1(ExecutionResult), +pub struct TransactionStatus { + pub finality_status: TransactionFinalityStatus, + pub execution_status: TransactionExecutionStatus, } /// Wrapper type for transaction execution error. From 80727447fb8376e1543d4d67f263034af6dd70e5 Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 11:02:52 +0100 Subject: [PATCH 11/18] implemented starknet_getTransactionStatus - cleaned --- crates/client/rpc-core/Cargo.toml | 2 +- crates/client/rpc/src/lib.rs | 44 +++++++++++++++---------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/crates/client/rpc-core/Cargo.toml b/crates/client/rpc-core/Cargo.toml index bdcf3c2d65..d57d870b26 100644 --- a/crates/client/rpc-core/Cargo.toml +++ b/crates/client/rpc-core/Cargo.toml @@ -31,8 +31,8 @@ jsonrpsee = { workspace = true, features = [ "macros", ], default-features = true } mp-block = { workspace = true } -mp-transactions = { workspace = true , features = ["serde"] } 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/src/lib.rs b/crates/client/rpc/src/lib.rs index 570d44fb2d..297bdaf5af 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -23,7 +23,7 @@ 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, TransactionStatus}; +use mp_transactions::{TransactionStatus, UserTransaction}; use pallet_starknet_runtime_api::{ConvertTransactionRuntimeApi, StarknetRuntimeApi}; use sc_client_api::backend::{Backend, StorageProvider}; use sc_client_api::BlockBackend; @@ -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, TransactionExecutionStatus + SyncStatus, SyncStatusType, Transaction, TransactionExecutionStatus, TransactionFinalityStatus, TransactionReceipt, }; use crate::constants::{MAX_EVENTS_CHUNK_SIZE, MAX_EVENTS_KEYS}; @@ -403,9 +403,10 @@ where /// 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. + /// 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 /// @@ -414,10 +415,10 @@ where /// ### 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. + /// - `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 block_hash_from_db = self .backend @@ -427,20 +428,21 @@ where error!("Failed to get transaction's substrate block hash from mapping_db: {e}"); StarknetRpcApiError::TxnHashNotFound })?; - + let substrate_block_hash = block_hash_from_db.ok_or(StarknetRpcApiError::TxnHashNotFound)?; - + let 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 find_tx = block.transactions() + + let find_tx = block + .transactions() .iter() .find(|tx| tx.compute_hash::(chain_id, false).0 == transaction_hash) .map(|tx| to_starknet_core_tx(tx.clone(), transaction_hash)) .ok_or(StarknetRpcApiError::TxnHashNotFound)?; - + let execution_result: TransactionExecutionStatus = self .client .runtime_api() @@ -452,15 +454,13 @@ where ); StarknetRpcApiError::InternalServerError })? - .map_or(TransactionExecutionStatus::Succeeded, |message| { - TransactionExecutionStatus::Reverted - }); - + .map_or(TransactionExecutionStatus::Succeeded, |message| TransactionExecutionStatus::Reverted); + Ok(TransactionStatus { finality_status: TransactionFinalityStatus::AcceptedOnL2, - execution_status: execution_result + execution_status: execution_result, }) - } + } /// Get the value of the storage at the given address and key. /// @@ -1097,8 +1097,6 @@ where }) } - - /// Returns all events matching the given filter. /// /// This function retrieves all event objects that match the conditions specified in the From c9d78c0d0f3277c444097bd5685b686d46366d12 Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 11:19:30 +0100 Subject: [PATCH 12/18] updated changelog.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b68f6bcaf2..05cd1bd768 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Next release +- 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 From 7dbcfa130b00abbd36f4931a831169faf9bd3764 Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 11:21:35 +0100 Subject: [PATCH 13/18] runned prettier --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05cd1bd768..9c788bc6d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ## Next release -- feat(rpc): Added starknet_getTransactionStatus and removed starknet_pendingTransactions +- 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 From f4a1950f69922a9c05c637005c3c4d8cf8259e8a Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 14:12:56 +0100 Subject: [PATCH 14/18] added starknet_ before starknet data for concencus + corrected review --- crates/client/rpc/src/lib.rs | 140 +++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 63 deletions(-) diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index 297bdaf5af..9b7f7d031a 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -120,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 @@ -160,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. @@ -396,9 +396,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(); - Ok(block.header().transaction_count) + Ok(starknet_block.header().transaction_count) } /// Gets the Transaction Status, Including Mempool Status and Execution Details @@ -420,7 +420,7 @@ where /// - `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 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())) @@ -429,32 +429,46 @@ where StarknetRpcApiError::TxnHashNotFound })?; - let substrate_block_hash = block_hash_from_db.ok_or(StarknetRpcApiError::TxnHashNotFound)?; + let substrate_block_hash = substrate_block_hash_from_db.ok_or(StarknetRpcApiError::TxnHashNotFound)?; - 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(StarknetRpcApiError::BlockNotFound)?; let chain_id = self.chain_id()?.0.into(); - let find_tx = block - .transactions() - .iter() - .find(|tx| tx.compute_hash::(chain_id, false).0 == transaction_hash) - .map(|tx| to_starknet_core_tx(tx.clone(), transaction_hash)) - .ok_or(StarknetRpcApiError::TxnHashNotFound)?; + 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)) + }; - let execution_result: TransactionExecutionStatus = 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 - })? - .map_or(TransactionExecutionStatus::Succeeded, |message| TransactionExecutionStatus::Reverted); + let execution_result = { + 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 + })?; + + match revert_error { + None => ExecutionResult::Succeeded, + // This is safe because the message is a Vec build from a String + Some(message) => ExecutionResult::Reverted { reason: unsafe { String::from_utf8_unchecked(message) } }, + } + }; Ok(TransactionStatus { finality_status: TransactionFinalityStatus::AcceptedOnL2, @@ -757,9 +771,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()); @@ -773,20 +787,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)) @@ -943,12 +957,12 @@ 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 @@ -996,15 +1010,15 @@ 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) @@ -1030,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, }; @@ -1065,10 +1079,10 @@ 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}'"); @@ -1083,8 +1097,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(), @@ -1196,7 +1210,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())) @@ -1205,22 +1219,22 @@ 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()) { + let find_tx = if let Some(tx_hashes) = self.get_cached_transaction_hashes(starknet_block.header().hash::().into()) { tx_hashes .into_iter() - .zip(block.transactions()) + .zip(starknet_block.transactions()) .find(|(tx_hash, _)| *tx_hash == Felt252Wrapper(transaction_hash).into()) .map(|(_, tx)| to_starknet_core_tx(tx.clone(), transaction_hash)) } else { - block + starknet_block .transactions() .iter() .find(|tx| tx.compute_hash::(chain_id, false).0 == transaction_hash) @@ -1263,7 +1277,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| { @@ -1271,7 +1285,7 @@ where StarknetRpcApiError::InternalServerError })?; - match block_hash_from_db { + match substrate_block_hash_from_db { Some(block_hash) => { substrate_block_hash = block_hash; break; @@ -1300,9 +1314,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; From a91289a03851a440c19f7c99dd75bb51c83f51e4 Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 14:47:18 +0100 Subject: [PATCH 15/18] added starknet_ before starknet data for concencus + corrected review --- CHANGELOG.md | 1 + crates/client/rpc/src/lib.rs | 81 +++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c788bc6d7..7f9cf8f74b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 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 diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index 9b7f7d031a..6ad29d0a8d 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -436,21 +436,22 @@ where let chain_id = self.chain_id()?.0.into(); - 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)) - }; + 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_result = { + let execution_status = { let revert_error = self .client .runtime_api() @@ -463,17 +464,14 @@ where StarknetRpcApiError::InternalServerError })?; - match revert_error { - None => ExecutionResult::Succeeded, - // This is safe because the message is a Vec build from a String - Some(message) => ExecutionResult::Reverted { reason: unsafe { String::from_utf8_unchecked(message) } }, + if revert_error.is_none() { + TransactionExecutionStatus::Succeeded + } else { + TransactionExecutionStatus::Reverted } }; - Ok(TransactionStatus { - finality_status: TransactionFinalityStatus::AcceptedOnL2, - execution_status: execution_result, - }) + Ok(TransactionStatus { finality_status: TransactionFinalityStatus::AcceptedOnL2, execution_status }) } /// Get the value of the storage at the given address and key. @@ -959,10 +957,12 @@ where let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); - let transaction = starknet_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(starknet_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 @@ -1016,7 +1016,8 @@ where let chain_id = self.chain_id()?; let chain_id = Felt252Wrapper(chain_id.0); - let opt_cached_transaction_hashes = self.get_cached_transaction_hashes(starknet_block.header().hash::().into()); + 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() { @@ -1082,7 +1083,8 @@ where let starknet_block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); 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 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}'"); @@ -1227,19 +1229,20 @@ where 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(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 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()) } From 09227cf031020139f2f63638ebf87533241cec61 Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 15:07:16 +0100 Subject: [PATCH 16/18] chained substrate_block_hash and substrate_block_hash_from_db --- crates/client/rpc/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index 6ad29d0a8d..0eedf4c469 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -420,16 +420,15 @@ where /// - `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_from_db = self + 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 - })?; - - let substrate_block_hash = substrate_block_hash_from_db.ok_or(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)?; From a50b3c1adebc87f46067893fd29727ade58b8383 Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 15:21:00 +0100 Subject: [PATCH 17/18] cleaned prettier --- docs/content/articles/en/madara-beast-article.md | 9 ++++----- docs/contributor-starter-pack.md | 7 ++++--- 2 files changed, 8 insertions(+), 8 deletions(-) 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: From 96b833365b791744a0bdb88c73f1192eed96e46c Mon Sep 17 00:00:00 2001 From: antiyro Date: Wed, 6 Dec 2023 16:13:37 +0100 Subject: [PATCH 18/18] removed unecessary serde = [mp-transactions/serde] --- crates/client/rpc-core/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/client/rpc-core/Cargo.toml b/crates/client/rpc-core/Cargo.toml index d57d870b26..758cc578c2 100644 --- a/crates/client/rpc-core/Cargo.toml +++ b/crates/client/rpc-core/Cargo.toml @@ -47,6 +47,3 @@ thiserror = { workspace = true } [dev-dependencies] assert_matches = "1.5.0" - -[features] -serde = ["mp-transactions/serde"]