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

config: allow configuring jsonrpc server type #18099

Merged
merged 2 commits into from
Jun 7, 2024
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.

23 changes: 17 additions & 6 deletions crates/sui-config/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,15 @@ pub struct NodeConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub consensus_config: Option<ConsensusConfig>,

// TODO: Remove this as it's no longer used.
#[serde(default)]
pub enable_event_processing: bool,

#[serde(default = "default_enable_index_processing")]
pub enable_index_processing: bool,

// only alow websocket connections for jsonrpc traffic
#[serde(default)]
pub websocket_only: bool,
/// Determines the jsonrpc server type as either:
/// - 'websocket' for a websocket based service (deprecated)
/// - 'http' for an http based service
/// - 'both' for both a websocket and http based service (deprecated)
pub jsonrpc_server_type: Option<ServerType>,

#[serde(default)]
pub grpc_load_shed: Option<bool>,
Expand Down Expand Up @@ -197,6 +196,14 @@ pub enum ExecutionCacheConfig {
},
}

#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum ServerType {
WebSocket,
Http,
Both,
}

#[derive(Clone, Debug, Deserialize, Serialize, Default)]
#[serde(rename_all = "kebab-case")]
pub struct TransactionKeyValueStoreReadConfig {
Expand Down Expand Up @@ -372,6 +379,10 @@ impl NodeConfig {
})
.collect()
}

pub fn jsonrpc_server_type(&self) -> ServerType {
self.jsonrpc_server_type.unwrap_or(ServerType::Http)
}
}

#[derive(Debug, Clone, Deserialize, Serialize)]
Expand Down
114 changes: 4 additions & 110 deletions crates/sui-e2e-tests/tests/full_node_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@
// SPDX-License-Identifier: Apache-2.0

use futures::future;
use jsonrpsee::core::client::{ClientT, Subscription, SubscriptionClientT};
use jsonrpsee::core::client::ClientT;
use jsonrpsee::rpc_params;
use move_core_types::annotated_value::MoveStructLayout;
use move_core_types::ident_str;
use move_core_types::parser::parse_struct_tag;
use rand::rngs::OsRng;
use serde_json::json;
use std::sync::Arc;
use sui::client_commands::{OptsWithGas, SuiClientCommandResult, SuiClientCommands};
use sui_config::node::RunWithRange;
use sui_json_rpc_types::{EventFilter, TransactionFilter};
use sui_json_rpc_types::{
type_and_fields_from_move_event_data, EventPage, SuiEvent, SuiExecutionStatus,
SuiTransactionBlockEffectsAPI, SuiTransactionBlockResponse, SuiTransactionBlockResponseOptions,
EventPage, SuiEvent, SuiExecutionStatus, SuiTransactionBlockEffectsAPI,
SuiTransactionBlockResponse, SuiTransactionBlockResponseOptions,
};
use sui_json_rpc_types::{EventFilter, TransactionFilter};
use sui_keys::keystore::AccountKeystore;
use sui_macros::*;
use sui_node::SuiNodeHandle;
Expand All @@ -33,7 +31,6 @@ use sui_types::base_types::{ObjectID, SuiAddress, TransactionDigest};
use sui_types::base_types::{ObjectRef, SequenceNumber};
use sui_types::crypto::{get_key_pair, SuiKeyPair};
use sui_types::error::{SuiError, UserInputError};
use sui_types::event::{Event, EventID};
use sui_types::message_envelope::Message;
use sui_types::messages_grpc::TransactionInfoRequest;
use sui_types::object::{Object, ObjectRead, Owner, PastObjectRead};
Expand All @@ -47,13 +44,11 @@ use sui_types::transaction::{
CallArg, GasData, TransactionData, TransactionKind, TEST_ONLY_GAS_UNIT_FOR_OBJECT_BASICS,
TEST_ONLY_GAS_UNIT_FOR_SPLIT_COIN, TEST_ONLY_GAS_UNIT_FOR_TRANSFER,
};
use sui_types::type_resolver::get_layout_from_struct_tag;
use sui_types::utils::{
to_sender_signed_transaction, to_sender_signed_transaction_with_multi_signers,
};
use test_cluster::TestClusterBuilder;
use tokio::sync::Mutex;
use tokio::time::timeout;
use tokio::time::{sleep, Duration};
use tracing::info;

Expand Down Expand Up @@ -638,107 +633,6 @@ async fn do_test_full_node_sync_flood() {
.unwrap();
}

#[sim_test]
async fn test_full_node_sub_and_query_move_event_ok() -> Result<(), anyhow::Error> {
let mut test_cluster = TestClusterBuilder::new()
.enable_fullnode_events()
.build()
.await;

// Start a new fullnode that is not on the write path
let fullnode = test_cluster.spawn_new_fullnode().await;

let ws_client = fullnode.ws_client().await;
let node = fullnode.sui_node;

let context = &mut test_cluster.wallet;
let package_id = publish_nfts_package(context).await.0;

let struct_tag_str = format!("{package_id}::devnet_nft::MintNFTEvent");
let struct_tag = parse_struct_tag(&struct_tag_str).unwrap();

let mut sub: Subscription<SuiEvent> = ws_client
.subscribe(
"suix_subscribeEvent",
rpc_params![EventFilter::MoveEventType(struct_tag.clone())],
"suix_unsubscribeEvent",
)
.await
.unwrap();

let (sender, object_id, digest) = create_devnet_nft(context, package_id).await;
node.state()
.get_transaction_cache_reader()
.notify_read_executed_effects(&[digest])
.await
.unwrap();

// Wait for streaming
let bcs = match timeout(Duration::from_secs(5), sub.next()).await {
Ok(Some(Ok(SuiEvent {
type_,
parsed_json,
bcs,
..
}))) => {
assert_eq!(&type_, &struct_tag);
assert_eq!(
parsed_json,
json!({
"creator" : sender,
"name": "example_nft_name",
"object_id" : object_id,
})
);
bcs
}
other => panic!("Failed to get SuiEvent, but {:?}", other),
};
let struct_tag = parse_struct_tag(&struct_tag_str).unwrap();
let layout = get_layout_from_struct_tag(
struct_tag.clone(),
&**node.state().epoch_store_for_testing().module_cache(),
)?;

let expected_parsed_event = Event::move_event_to_move_value(&bcs, layout).unwrap();
let (_, expected_parsed_events) =
type_and_fields_from_move_event_data(expected_parsed_event).unwrap();
let expected_event = SuiEvent {
id: EventID {
tx_digest: digest,
event_seq: 0,
},
package_id,
transaction_module: ident_str!("devnet_nft").into(),
sender,
type_: struct_tag,
parsed_json: expected_parsed_events,
bcs,
timestamp_ms: None,
};

// get tx events
let events = test_cluster
.sui_client()
.event_api()
.get_events(digest)
.await?;
assert_eq!(events.len(), 1);
assert_eq!(events[0], expected_event);
assert_eq!(events[0].id.tx_digest, digest);

// No more
match timeout(Duration::from_secs(5), sub.next()).await {
Err(_) => (),
other => panic!(
"Expect to time out because no new events are coming in. Got {:?}",
other
),
}

Ok(())
}

// Test fullnode has event read jsonrpc endpoints working
#[sim_test]
async fn test_full_node_event_read_api_ok() {
Expand Down
2 changes: 1 addition & 1 deletion crates/sui-indexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ pub async fn build_json_rpc_server<T: R2D2Connection>(
.start(
default_socket_addr,
custom_runtime,
Some(ServerType::Http),
ServerType::Http,
Some(cancel),
)
.await?)
Expand Down
12 changes: 9 additions & 3 deletions crates/sui-json-rpc-tests/tests/routing_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use jsonrpsee::RpcModule;
use prometheus::Registry;
use std::env;
use sui_config::local_ip_utils;
use sui_json_rpc::{JsonRpcServerBuilder, SuiRpcModule};
use sui_json_rpc::{JsonRpcServerBuilder, ServerType, SuiRpcModule};
use sui_json_rpc_api::CLIENT_TARGET_API_VERSION_HEADER;
use sui_open_rpc::Module;
use sui_open_rpc_macros::open_rpc;
Expand All @@ -24,7 +24,10 @@ async fn test_rpc_backward_compatibility() {
builder.register_module(TestApiModule).unwrap();

let address = local_ip_utils::new_local_tcp_socket_for_testing();
let _handle = builder.start(address, None, None, None).await.unwrap();
let _handle = builder
.start(address, None, ServerType::Http, None)
.await
.unwrap();
let url = format!("http://0.0.0.0:{}", address.port());

// Test with un-versioned client
Expand Down Expand Up @@ -103,7 +106,10 @@ async fn test_disable_routing() {
builder.register_module(TestApiModule).unwrap();

let address = local_ip_utils::new_local_tcp_socket_for_testing();
let _handle = builder.start(address, None, None, None).await.unwrap();
let _handle = builder
.start(address, None, ServerType::Http, None)
.await
.unwrap();
let url = format!("http://0.0.0.0:{}", address.port());

// try to access old method directly should fail
Expand Down
48 changes: 0 additions & 48 deletions crates/sui-json-rpc-tests/tests/subscription_tests.rs

This file was deleted.

1 change: 1 addition & 0 deletions crates/sui-json-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ sui-json-rpc-api.workspace = true
sui-open-rpc.workspace = true
sui-open-rpc-macros.workspace = true
sui-protocol-config.workspace = true
sui-config.workspace = true
sui-json-rpc-types.workspace = true
sui-macros.workspace = true
sui-transaction-builder.workspace = true
Expand Down
16 changes: 6 additions & 10 deletions crates/sui-json-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use tracing::info;

pub use balance_changes::*;
pub use object_changes::*;
pub use sui_config::node::ServerType;
use sui_json_rpc_api::{
CLIENT_SDK_TYPE_HEADER, CLIENT_SDK_VERSION_HEADER, CLIENT_TARGET_API_VERSION_HEADER,
};
Expand Down Expand Up @@ -75,11 +76,6 @@ pub fn sui_rpc_doc(version: &str) -> Project {
)
}

pub enum ServerType {
WebSocket,
Http,
}

impl JsonRpcServerBuilder {
pub fn new(
version: &str,
Expand Down Expand Up @@ -155,7 +151,7 @@ impl JsonRpcServerBuilder {
.on_failure(())
}

pub async fn to_router(&self, server_type: Option<ServerType>) -> Result<axum::Router, Error> {
pub async fn to_router(&self, server_type: ServerType) -> Result<axum::Router, Error> {
let routing = self.rpc_doc.method_routing.clone();

let disable_routing = env::var("DISABLE_BACKWARD_COMPATIBILITY")
Expand Down Expand Up @@ -196,7 +192,7 @@ impl JsonRpcServerBuilder {
let mut router = axum::Router::new();

match server_type {
Some(ServerType::WebSocket) => {
ServerType::WebSocket => {
router = router
.route(
"/",
Expand All @@ -207,7 +203,7 @@ impl JsonRpcServerBuilder {
axum::routing::get(crate::axum_router::ws::ws_json_rpc_upgrade),
);
}
Some(ServerType::Http) => {
ServerType::Http => {
router = router
.route(
"/",
Expand All @@ -222,7 +218,7 @@ impl JsonRpcServerBuilder {
axum::routing::post(crate::axum_router::json_rpc_handler),
);
}
None => {
ServerType::Both => {
router = router
.route(
"/",
Expand Down Expand Up @@ -258,7 +254,7 @@ impl JsonRpcServerBuilder {
self,
listen_address: SocketAddr,
_custom_runtime: Option<Handle>,
server_type: Option<ServerType>,
server_type: ServerType,
cancel: Option<CancellationToken>,
) -> Result<ServerHandle, Error> {
let app = self.to_router(server_type).await?;
Expand Down
8 changes: 2 additions & 6 deletions crates/sui-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use sui_core::execution_cache::build_execution_cache;
use sui_core::storage::RestReadStore;
use sui_core::traffic_controller::metrics::TrafficControllerMetrics;
use sui_json_rpc::bridge_api::BridgeReadApi;
use sui_json_rpc::ServerType;
use sui_json_rpc_api::JsonRpcMetrics;
use sui_network::randomness;
use sui_rest_api::RestMetrics;
Expand Down Expand Up @@ -1898,11 +1897,8 @@ pub async fn build_http_server(
))?;
server.register_module(MoveUtils::new(state.clone()))?;

let server_type = if config.websocket_only {
Some(ServerType::WebSocket)
} else {
None
};
let server_type = config.jsonrpc_server_type();

server.to_router(server_type).await?
};

Expand Down
Loading
Loading