Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(JSON-RPC): support version without patch #929

Merged
merged 1 commit into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/papyrus_gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ test_utils = { path = "../test_utils" }
starknet_api = { workspace = true, features = ["testing"] }
starknet_client = { path = "../starknet_client", features = ["testing"] }
indexmap = { workspace = true, features = ["serde"] }
rand.workspace = true
10 changes: 5 additions & 5 deletions crates/papyrus_gateway/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use starknet_api::block::{BlockHash, BlockNumber};
use starknet_api::core::{ChainId, ContractAddress};
use starknet_api::transaction::EventKey;

use crate::v0_3_0::api::api_impl::JsonRpcServerV0_3_0Impl;
use crate::v0_3_0::api::JsonRpcV0_3_0Server;
use crate::v0_3_0::api::api_impl::JsonRpcServerV0_3Impl;
use crate::v0_3_0::api::JsonRpcV0_3Server;
use crate::version_config;

#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
Expand Down Expand Up @@ -92,11 +92,11 @@ pub fn get_methods_from_supported_apis(
version_config::VERSION_CONFIG
.iter()
.filter_map(|version_config| {
let (version_id, version_state) = version_config;
let (version, version_state) = version_config;
match version_state {
version_config::VersionState::Deprecated => None,
version_config::VersionState::Supported => match *version_id {
version_config::VERSION_0_3_0 => Some(JsonRpcServerV0_3_0Impl {
version_config::VersionState::Supported => match *version {
version_config::VERSION_0_3 => Some(JsonRpcServerV0_3Impl {
chain_id: chain_id.clone(),
storage_reader: storage_reader.clone(),
max_events_chunk_size,
Expand Down
19 changes: 16 additions & 3 deletions crates/papyrus_gateway/src/gateway_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use papyrus_storage::base_layer::BaseLayerStorageWriter;
use papyrus_storage::header::HeaderStorageWriter;
use papyrus_storage::test_utils::get_test_storage;
use pretty_assertions::assert_eq;
use rand::seq::SliceRandom;
use starknet_api::block::{BlockHash, BlockHeader, BlockNumber, BlockStatus};
use test_utils::get_rng;
use tower::BoxError;

use crate::api::JsonRpcError;
Expand Down Expand Up @@ -121,8 +123,12 @@ async fn test_version_middleware() {
let base_uri = "http://localhost:8080/rpc/";
let mut path_options = vec![];
VERSION_CONFIG.iter().for_each(|(version_id, _)| {
path_options.push(((*version_id).to_string(), (*version_id).to_string()));
path_options.push(((*version_id).to_lowercase(), (*version_id).to_string()))
// add version name with capital V
path_options.push((version_id.name.to_string(), version_id.name.to_string()));
// add version name with lower case v
path_options.push((version_id.name.to_lowercase(), version_id.name.to_string()));
// add version name with patch version
path_options.push((version_id.to_string(), version_id.name.to_string()));
});

// test all versions with single and batch requests
Expand Down Expand Up @@ -151,7 +157,14 @@ async fn test_version_middleware() {
}
});
let unknown_version = "not_a_valid_version";
let bad_uri = format!("{base_uri}/{unknown_version}");
let bad_uri = format!("{base_uri}{unknown_version}");
if let Ok(res) = call_proxy_request_get_method_in_out(bad_uri, false).await {
panic!("expected failure got: {res:?}");
};
let mut rng = get_rng();
let version_id = VERSION_CONFIG.choose(&mut rng).unwrap().0;
let newer_version_then_we_have = format!("{}_{}", version_id.name, version_id.patch + 1);
let bad_uri = format!("{base_uri}{newer_version_then_we_have}");
if let Ok(res) = call_proxy_request_get_method_in_out(bad_uri, false).await {
panic!("expected failure got: {res:?}");
};
Expand Down
16 changes: 12 additions & 4 deletions crates/papyrus_gateway/src/middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,24 +91,32 @@ fn strip_starknet_from_method(method: &str) -> Option<&str> {
fn get_version_as_prefix(path: &str) -> Result<&str, BoxError> {
// get the version name from the path (should be something like "http://host:port/rpc/version_id")
let uri_components = &mut path.split('/').collect::<Vec<_>>();
let Some(version) = uri_components.get(2) else {
let Some(temp_version) = uri_components.get(2) else {
// as long as 'deny_requests_with_unsupported_path' middleware is used, this should never happen
// but for safety we return an error and not unreachable!()
let msg = format!("Invalid path format: {}", path);
debug!(msg);
return Err(BoxError::from(msg));
};
let version_comps = temp_version.split('_').collect::<Vec<_>>();
let mut patch_num = 0;
if version_comps.len() == 3 {
// if the version is of the form "V0_0_1" we store the path num to check that our latest
// supported patch version is at least the requested version.
patch_num = version_comps[2].parse::<u8>().map_err(BoxError::from)?;
}
let version = format!("{}_{}", version_comps[0], version_comps[1]);
let Some((version_id, _)) =
// find a matching version in the version config
VERSION_CONFIG.iter().find(|(version_id, version_state)| {
(*version_id == *version || (*version_id).to_lowercase() == *version) && *version_state != VersionState::Deprecated
(version_id.name == version || version_id.name.to_lowercase() == version) && *version_state != VersionState::Deprecated && patch_num <= version_id.patch
}) else {
return Err(BoxError::from(format!("Invalid path, couldn't find matching version for version_id: {version}")));
};
Ok(*version_id)
Ok(version_id.name)
}

fn is_supported_path(path: &str) -> bool {
let re = Regex::new(r"^\/rpc\/[Vv][0-9]+_[0-9]+_[0-9]+$").expect("should be a valid regex");
let re = Regex::new(r"^\/rpc\/[Vv][0-9]+_[0-9]+(_[0-9]+)?$").expect("should be a valid regex");
re.is_match(path)
}
3 changes: 2 additions & 1 deletion crates/papyrus_gateway/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use papyrus_storage::StorageWriter;
use starknet_api::core::ChainId;

use crate::api::JsonRpcServerImpl;
use crate::version_config::VersionId;
use crate::GatewayConfig;

pub fn get_test_gateway_config() -> GatewayConfig {
Expand Down Expand Up @@ -35,7 +36,7 @@ pub(crate) fn get_test_rpc_server_and_storage_writer<T: JsonRpcServerImpl>()

pub async fn get_starknet_spec_api_schema(
component_names: &[&str],
version_id: &str,
version_id: &VersionId,
) -> JSONSchema {
let target = format!("./resources/{version_id}_starknet_api_openrpc.json");
let text = std::fs::read_to_string(target).unwrap();
Expand Down
9 changes: 4 additions & 5 deletions crates/papyrus_gateway/src/v0_3_0/api/api_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ use super::super::transaction::{
TransactionWithHash, Transactions,
};
use super::{
BlockHashAndNumber, BlockId, EventFilter, EventsChunk, GatewayContractClass,
JsonRpcV0_3_0Server,
BlockHashAndNumber, BlockId, EventFilter, EventsChunk, GatewayContractClass, JsonRpcV0_3Server,
};
use crate::api::{BlockHashOrNumber, ContinuationToken, JsonRpcError, JsonRpcServerImpl};
use crate::block::get_block_header_by_number;
Expand All @@ -35,14 +34,14 @@ use crate::{
};

/// Rpc server.
pub struct JsonRpcServerV0_3_0Impl {
pub struct JsonRpcServerV0_3Impl {
pub chain_id: ChainId,
pub storage_reader: StorageReader,
pub max_events_chunk_size: usize,
pub max_events_keys: usize,
}

impl JsonRpcV0_3_0Server for JsonRpcServerV0_3_0Impl {
impl JsonRpcV0_3Server for JsonRpcServerV0_3Impl {
#[instrument(skip(self), level = "debug", err, ret)]
fn block_number(&self) -> RpcResult<BlockNumber> {
let txn = self.storage_reader.begin_ro_txn().map_err(internal_server_error)?;
Expand Down Expand Up @@ -448,7 +447,7 @@ impl JsonRpcV0_3_0Server for JsonRpcServerV0_3_0Impl {
}
}

impl JsonRpcServerImpl for JsonRpcServerV0_3_0Impl {
impl JsonRpcServerImpl for JsonRpcServerV0_3Impl {
fn new(
chain_id: ChainId,
storage_reader: StorageReader,
Expand Down
2 changes: 1 addition & 1 deletion crates/papyrus_gateway/src/v0_3_0/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub mod api_impl;
#[cfg(test)]
mod test;

#[versioned_rpc("V0_3_0")]
#[versioned_rpc("V0_3")]
pub trait JsonRpc {
/// Gets the most recent accepted block number.
#[method(name = "blockNumber")]
Expand Down
Loading
Loading