diff --git a/crates/papyrus_gateway/resources/V0_3_0_starknet_api_openrpc.json b/crates/papyrus_gateway/resources/V0_3_0_starknet_api_openrpc.json index aeb1cece57..96a4321886 100644 --- a/crates/papyrus_gateway/resources/V0_3_0_starknet_api_openrpc.json +++ b/crates/papyrus_gateway/resources/V0_3_0_starknet_api_openrpc.json @@ -2455,6 +2455,10 @@ "code": 28, "message": "Class hash not found" }, + "TRANSACTION_REVERTED": { + "code": 29, + "message": "Transaction reverted" + }, "PAGE_SIZE_TOO_BIG": { "code": 31, "message": "Requested page size is too big" diff --git a/crates/papyrus_gateway/src/api.rs b/crates/papyrus_gateway/src/api.rs index 0406bc9853..c0f27aca08 100644 --- a/crates/papyrus_gateway/src/api.rs +++ b/crates/papyrus_gateway/src/api.rs @@ -50,6 +50,8 @@ pub enum JsonRpcError { InvalidTransactionIndex = 27, #[error("Class hash not found.")] ClassHashNotFound = 28, + #[error("Transaction reverted.")] + TransactionReverted = 29, #[error("Requested page size is too big.")] PageSizeTooBig = 31, #[error("The supplied continuation token is invalid or unknown.")] diff --git a/crates/papyrus_gateway/src/v0_3_0/api/api_impl.rs b/crates/papyrus_gateway/src/v0_3_0/api/api_impl.rs index 775652e62e..4de9380b9a 100644 --- a/crates/papyrus_gateway/src/v0_3_0/api/api_impl.rs +++ b/crates/papyrus_gateway/src/v0_3_0/api/api_impl.rs @@ -6,12 +6,13 @@ use papyrus_storage::body::events::{EventIndex, EventsReader}; use papyrus_storage::body::{BodyStorageReader, TransactionIndex}; use papyrus_storage::state::StateStorageReader; use papyrus_storage::StorageReader; -use starknet_api::block::BlockNumber; +use starknet_api::block::{BlockNumber, BlockStatus}; use starknet_api::core::{ChainId, ClassHash, ContractAddress, GlobalRoot, Nonce}; use starknet_api::hash::{StarkFelt, StarkHash, GENESIS_HASH}; use starknet_api::state::{StateNumber, StorageKey}; use starknet_api::transaction::{ - EventIndexInTransactionOutput, TransactionHash, TransactionOffsetInBlock, + EventIndexInTransactionOutput, TransactionExecutionStatus, TransactionHash, + TransactionOffsetInBlock, }; use tracing::instrument; @@ -214,10 +215,30 @@ impl JsonRpcV0_3_0Server for JsonRpcServerV0_3_0Impl { let block_number = transaction_index.0; let status = get_block_status(&txn, block_number)?; + + // rejected blocks should not be a part of the API so we early return here. + // this assumption also holds for the conversion from block status to transaction status + // where we set rejected blocks to unreachable. + if status == BlockStatus::Rejected { + return Err(ErrorObjectOwned::from(JsonRpcError::BlockNotFound))?; + } + let block_hash = get_block_header_by_number::<_, BlockHeader>(&txn, block_number) .map_err(internal_server_error)? .block_hash; + let (_, transaction_execution_status) = txn + .get_transaction(transaction_index) + .map_err(internal_server_error)? + .ok_or_else(|| ErrorObjectOwned::from(JsonRpcError::TransactionHashNotFound))?; + + // starting from starknet v0.12.1 blocks can have reverted transactions (transactions that + // failed execution). RPC API v0.3 does not support these transactions therefore we + // return here with an error. + if transaction_execution_status == TransactionExecutionStatus::Reverted { + return Err(ErrorObjectOwned::from(JsonRpcError::TransactionReverted))?; + } + let thin_tx_output = txn .get_transaction_output(transaction_index) .map_err(internal_server_error)? diff --git a/crates/papyrus_gateway/src/v0_3_0/transaction.rs b/crates/papyrus_gateway/src/v0_3_0/transaction.rs index c8a67342a0..ba3989093e 100644 --- a/crates/papyrus_gateway/src/v0_3_0/transaction.rs +++ b/crates/papyrus_gateway/src/v0_3_0/transaction.rs @@ -222,7 +222,10 @@ impl From for TransactionStatus { BlockStatus::AcceptedOnL1 => TransactionStatus::AcceptedOnL1, BlockStatus::AcceptedOnL2 => TransactionStatus::AcceptedOnL2, BlockStatus::Pending => TransactionStatus::Pending, - BlockStatus::Rejected => TransactionStatus::Rejected, + // we convert the block status to transaction status only in the creation of + // TransactionReceiptWithStatus before that we verify that the block is not + // rejected so this conversion should never happen + BlockStatus::Rejected => unreachable!("Rejected blocks are not returned by the API"), } } }