Skip to content

Commit

Permalink
shahak/json rpc/move error to each version (#1002)
Browse files Browse the repository at this point in the history
* refactor(JSON-RPC): move code around

* refactor(JSON-RPC): split JsonRpcError for each error
  • Loading branch information
ShahakShama authored Aug 8, 2023
1 parent 71742c0 commit 3c73be3
Show file tree
Hide file tree
Showing 19 changed files with 331 additions and 175 deletions.
47 changes: 1 addition & 46 deletions crates/papyrus_gateway/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use std::collections::HashSet;
use std::sync::Arc;

use jsonrpsee::{Methods, RpcModule};
use papyrus_common::BlockHashAndNumber;
use papyrus_storage::StorageReader;
use serde::{Deserialize, Serialize};
use starknet_api::block::{BlockHash, BlockNumber};
use starknet_api::core::{ChainId, ContractAddress};
use starknet_api::transaction::EventKey;
use starknet_api::core::ChainId;
use starknet_client::writer::StarknetWriter;
use tokio::sync::RwLock;

Expand Down Expand Up @@ -40,49 +38,6 @@ pub enum BlockId {
Tag(Tag),
}

#[derive(thiserror::Error, Clone, Copy, Debug)]
pub enum JsonRpcError {
#[error("There are no blocks.")]
NoBlocks,
#[error("Contract not found.")]
ContractNotFound = 20,
#[error("Block not found.")]
BlockNotFound = 24,
#[error("Transaction hash not found.")]
TransactionHashNotFound = 25,
#[error("Invalid transaction index in a block.")]
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.")]
InvalidContinuationToken = 33,
#[error("Too many keys provided in a filter.")]
TooManyKeysInFilter = 34,
#[error("Contract error.")]
ContractError = 40,
// TODO(dvir): delete this when start support pending blocks.
#[error("Currently, Papyrus doesn't support pending blocks.")]
PendingBlocksNotSupported = 41,
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct EventFilter {
pub from_block: Option<BlockId>,
pub to_block: Option<BlockId>,
pub continuation_token: Option<ContinuationToken>,
pub chunk_size: usize,
pub address: Option<ContractAddress>,
#[serde(default)]
pub keys: Vec<HashSet<EventKey>>,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct ContinuationToken(pub String);

/// Returns a `Methods` object with all the methods from the supported APIs.
/// Whenever adding a new API version we need to add the new version mapping here.
pub fn get_methods_from_supported_apis(
Expand Down
23 changes: 0 additions & 23 deletions crates/papyrus_gateway/src/block.rs

This file was deleted.

2 changes: 1 addition & 1 deletion crates/papyrus_gateway/src/gateway_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use starknet_api::block::{BlockHash, BlockHeader, BlockNumber, BlockStatus};
use test_utils::get_rng;
use tower::BoxError;

use crate::api::JsonRpcError;
use crate::middleware::proxy_rpc_request;
use crate::test_utils::{get_test_gateway_config, get_test_highest_block};
use crate::v0_4_0::error::JsonRpcError;
use crate::version_config::VERSION_CONFIG;
use crate::{get_block_status, run_server, SERVER_MAX_BODY_SIZE};

Expand Down
52 changes: 1 addition & 51 deletions crates/papyrus_gateway/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
mod api;
mod block;
mod gateway_metrics;
#[cfg(test)]
mod gateway_test;
mod middleware;
mod syncing_state;
#[cfg(test)]
mod test_utils;
mod transaction;
mod v0_3_0;
mod v0_4_0;
mod version_config;
Expand Down Expand Up @@ -40,10 +38,7 @@ use starknet_client::RetryConfig;
use tokio::sync::RwLock;
use tracing::{debug, error, info, instrument};

use crate::api::{
get_methods_from_supported_apis, BlockHashOrNumber, BlockId, ContinuationToken, JsonRpcError,
Tag,
};
use crate::api::get_methods_from_supported_apis;
use crate::middleware::{deny_requests_with_unsupported_path, proxy_rpc_request};

/// Maximum size of a supported transaction body - 10MB.
Expand Down Expand Up @@ -103,43 +98,11 @@ impl SerializeConfig for GatewayConfig {
}
}

impl From<JsonRpcError> for ErrorObjectOwned {
fn from(err: JsonRpcError) -> Self {
ErrorObjectOwned::owned(err as i32, err.to_string(), None::<()>)
}
}

fn internal_server_error(err: impl Display) -> ErrorObjectOwned {
error!("{}: {}", INTERNAL_ERROR_MSG, err);
ErrorObjectOwned::owned(InternalError.code(), INTERNAL_ERROR_MSG, None::<()>)
}

fn get_block_number<Mode: TransactionKind>(
txn: &StorageTxn<'_, Mode>,
block_id: BlockId,
) -> Result<BlockNumber, ErrorObjectOwned> {
Ok(match block_id {
BlockId::HashOrNumber(BlockHashOrNumber::Hash(block_hash)) => txn
.get_block_number_by_hash(&block_hash)
.map_err(internal_server_error)?
.ok_or_else(|| ErrorObjectOwned::from(JsonRpcError::BlockNotFound))?,
BlockId::HashOrNumber(BlockHashOrNumber::Number(block_number)) => {
// Check that the block exists.
let last_block_number = get_latest_block_number(txn)?
.ok_or_else(|| ErrorObjectOwned::from(JsonRpcError::BlockNotFound))?;
if block_number > last_block_number {
return Err(ErrorObjectOwned::from(JsonRpcError::BlockNotFound));
}
block_number
}
BlockId::Tag(Tag::Latest) => get_latest_block_number(txn)?
.ok_or_else(|| ErrorObjectOwned::from(JsonRpcError::BlockNotFound))?,
BlockId::Tag(Tag::Pending) => {
return Err(ErrorObjectOwned::from(JsonRpcError::PendingBlocksNotSupported));
}
})
}

fn get_latest_block_number<Mode: TransactionKind>(
txn: &StorageTxn<'_, Mode>,
) -> Result<Option<BlockNumber>, ErrorObjectOwned> {
Expand All @@ -161,19 +124,6 @@ fn get_block_status<Mode: TransactionKind>(
}
struct ContinuationTokenAsStruct(EventIndex);

impl ContinuationToken {
fn parse(&self) -> Result<ContinuationTokenAsStruct, ErrorObjectOwned> {
let ct = serde_json::from_str(&self.0)
.map_err(|_| ErrorObjectOwned::from(JsonRpcError::InvalidContinuationToken))?;

Ok(ContinuationTokenAsStruct(ct))
}

fn new(ct: ContinuationTokenAsStruct) -> Result<Self, ErrorObjectOwned> {
Ok(Self(serde_json::to_string(&ct.0).map_err(internal_server_error)?))
}
}

#[instrument(skip(storage_reader), level = "debug", err)]
pub async fn run_server(
config: &GatewayConfig,
Expand Down
36 changes: 0 additions & 36 deletions crates/papyrus_gateway/src/transaction.rs

This file was deleted.

14 changes: 8 additions & 6 deletions crates/papyrus_gateway/src/v0_3_0/api/api_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ use super::super::transaction::{
Event, Transaction, TransactionOutput, TransactionReceipt, TransactionReceiptWithStatus,
TransactionWithHash, Transactions,
};
use super::{BlockId, EventFilter, EventsChunk, GatewayContractClass, JsonRpcV0_3Server};
use crate::api::{BlockHashOrNumber, ContinuationToken, JsonRpcError, JsonRpcServerImpl};
use crate::block::get_block_header_by_number;
use super::{
BlockId, ContinuationToken, EventFilter, EventsChunk, GatewayContractClass, JsonRpcV0_3Server,
};
use crate::api::{BlockHashOrNumber, JsonRpcServerImpl};
use crate::syncing_state::SyncingState;
use crate::transaction::{get_block_tx_hashes_by_number, get_block_txs_by_number};
use crate::v0_3_0::block::{get_block_header_by_number, get_block_number};
use crate::v0_3_0::error::JsonRpcError;
use crate::v0_3_0::transaction::{get_block_tx_hashes_by_number, get_block_txs_by_number};
use crate::{
get_block_number, get_block_status, get_latest_block_number, internal_server_error,
ContinuationTokenAsStruct,
get_block_status, get_latest_block_number, internal_server_error, ContinuationTokenAsStruct,
};

/// Rpc server.
Expand Down
36 changes: 34 additions & 2 deletions crates/papyrus_gateway/src/v0_3_0/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
use std::collections::HashSet;

use jsonrpsee::core::RpcResult;
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::types::ErrorObjectOwned;
use papyrus_common::BlockHashAndNumber;
use papyrus_proc_macros::versioned_rpc;
use serde::{Deserialize, Serialize};
use starknet_api::block::BlockNumber;
use starknet_api::core::{ClassHash, ContractAddress, Nonce};
use starknet_api::hash::StarkFelt;
use starknet_api::state::StorageKey;
use starknet_api::transaction::{TransactionHash, TransactionOffsetInBlock};
use starknet_api::transaction::{EventKey, TransactionHash, TransactionOffsetInBlock};

use super::block::Block;
use super::deprecated_contract_class::ContractClass as DeprecatedContractClass;
use super::state::{ContractClass, StateUpdate};
use super::transaction::{Event, TransactionReceiptWithStatus, TransactionWithHash};
use crate::api::{BlockId, ContinuationToken, EventFilter};
use crate::api::BlockId;
use crate::syncing_state::SyncingState;
use crate::v0_3_0::error::JsonRpcError;
use crate::{internal_server_error, ContinuationTokenAsStruct};

pub mod api_impl;
#[cfg(test)]
Expand Down Expand Up @@ -131,3 +136,30 @@ pub struct EventsChunk {
pub events: Vec<Event>,
pub continuation_token: Option<ContinuationToken>,
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct EventFilter {
pub from_block: Option<BlockId>,
pub to_block: Option<BlockId>,
pub continuation_token: Option<ContinuationToken>,
pub chunk_size: usize,
pub address: Option<ContractAddress>,
#[serde(default)]
pub keys: Vec<HashSet<EventKey>>,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct ContinuationToken(pub String);

impl ContinuationToken {
fn parse(&self) -> Result<ContinuationTokenAsStruct, ErrorObjectOwned> {
let ct = serde_json::from_str(&self.0)
.map_err(|_| ErrorObjectOwned::from(JsonRpcError::InvalidContinuationToken))?;

Ok(ContinuationTokenAsStruct(ct))
}

fn new(ct: ContinuationTokenAsStruct) -> Result<Self, ErrorObjectOwned> {
Ok(Self(serde_json::to_string(&ct.0).map_err(internal_server_error)?))
}
}
4 changes: 3 additions & 1 deletion crates/papyrus_gateway/src/v0_3_0/api/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ use super::super::transaction::{
TransactionWithHash, Transactions,
};
use super::api_impl::JsonRpcServerV0_3Impl;
use crate::api::{BlockHashOrNumber, BlockId, ContinuationToken, EventFilter, JsonRpcError, Tag};
use super::{ContinuationToken, EventFilter};
use crate::api::{BlockHashOrNumber, BlockId, Tag};
use crate::test_utils::{
get_starknet_spec_api_schema_for_components, get_test_gateway_config, get_test_highest_block,
get_test_rpc_server_and_storage_writer, validate_schema, SpecFile,
};
use crate::v0_3_0::error::JsonRpcError;
use crate::version_config::VERSION_0_3;
use crate::{run_server, ContinuationTokenAsStruct};

Expand Down
48 changes: 48 additions & 0 deletions crates/papyrus_gateway/src/v0_3_0/block.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
use jsonrpsee::types::ErrorObjectOwned;
use papyrus_storage::db::TransactionKind;
use papyrus_storage::header::HeaderStorageReader;
use papyrus_storage::StorageTxn;
use serde::{Deserialize, Serialize};
use starknet_api::block::{BlockHash, BlockNumber, BlockStatus, BlockTimestamp};
use starknet_api::core::{ContractAddress, GlobalRoot};

use super::transaction::Transactions;
use crate::api::{BlockHashOrNumber, BlockId, Tag};
use crate::v0_3_0::error::JsonRpcError;
use crate::{get_latest_block_number, internal_server_error};

#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)]
pub struct BlockHeader {
Expand Down Expand Up @@ -34,3 +41,44 @@ pub struct Block {
pub header: BlockHeader,
pub transactions: Transactions,
}

pub fn get_block_header_by_number<
Mode: TransactionKind,
BlockHeader: From<starknet_api::block::BlockHeader>,
>(
txn: &StorageTxn<'_, Mode>,
block_number: BlockNumber,
) -> Result<BlockHeader, ErrorObjectOwned> {
let header = txn
.get_block_header(block_number)
.map_err(internal_server_error)?
.ok_or_else(|| ErrorObjectOwned::from(JsonRpcError::BlockNotFound))?;

Ok(BlockHeader::from(header))
}

pub(crate) fn get_block_number<Mode: TransactionKind>(
txn: &StorageTxn<'_, Mode>,
block_id: BlockId,
) -> Result<BlockNumber, ErrorObjectOwned> {
Ok(match block_id {
BlockId::HashOrNumber(BlockHashOrNumber::Hash(block_hash)) => txn
.get_block_number_by_hash(&block_hash)
.map_err(internal_server_error)?
.ok_or_else(|| ErrorObjectOwned::from(JsonRpcError::BlockNotFound))?,
BlockId::HashOrNumber(BlockHashOrNumber::Number(block_number)) => {
// Check that the block exists.
let last_block_number = get_latest_block_number(txn)?
.ok_or_else(|| ErrorObjectOwned::from(JsonRpcError::BlockNotFound))?;
if block_number > last_block_number {
return Err(ErrorObjectOwned::from(JsonRpcError::BlockNotFound));
}
block_number
}
BlockId::Tag(Tag::Latest) => get_latest_block_number(txn)?
.ok_or_else(|| ErrorObjectOwned::from(JsonRpcError::BlockNotFound))?,
BlockId::Tag(Tag::Pending) => {
return Err(ErrorObjectOwned::from(JsonRpcError::PendingBlocksNotSupported));
}
})
}
Loading

0 comments on commit 3c73be3

Please sign in to comment.