Skip to content

Commit

Permalink
config: allow configuring jsonrpc server type
Browse files Browse the repository at this point in the history
Allow for configuring the jsonrpc server type as well as setting the
default to be an HTTP only based service.
  • Loading branch information
bmwill committed Jun 7, 2024
1 parent 3e77eed commit f5bea1d
Show file tree
Hide file tree
Showing 15 changed files with 59 additions and 312 deletions.
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.

19 changes: 17 additions & 2 deletions crates/sui-config/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ pub struct NodeConfig {
#[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 @@ -193,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 @@ -368,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

0 comments on commit f5bea1d

Please sign in to comment.