From 6982788354fc7953abde2ac29190317a62544269 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 26 Jul 2023 15:03:22 +0300 Subject: [PATCH 1/6] chainHead/events: Remove network config Signed-off-by: Alexandru Vasile --- client/rpc-spec-v2/src/chain_head/api.rs | 11 +----- .../rpc-spec-v2/src/chain_head/chain_head.rs | 5 +-- client/rpc-spec-v2/src/chain_head/event.rs | 37 ------------------- client/rpc-spec-v2/src/chain_head/mod.rs | 2 +- 4 files changed, 4 insertions(+), 51 deletions(-) diff --git a/client/rpc-spec-v2/src/chain_head/api.rs b/client/rpc-spec-v2/src/chain_head/api.rs index 8347617279c4c..8905e03687747 100644 --- a/client/rpc-spec-v2/src/chain_head/api.rs +++ b/client/rpc-spec-v2/src/chain_head/api.rs @@ -19,7 +19,7 @@ #![allow(non_snake_case)] //! API trait of the chain head. -use crate::chain_head::event::{ChainHeadEvent, FollowEvent, NetworkConfig, StorageQuery}; +use crate::chain_head::event::{ChainHeadEvent, FollowEvent, StorageQuery}; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; #[rpc(client, server)] @@ -52,12 +52,7 @@ pub trait ChainHeadApi { unsubscribe = "chainHead_unstable_stopBody", item = ChainHeadEvent, )] - fn chain_head_unstable_body( - &self, - follow_subscription: String, - hash: Hash, - network_config: Option, - ); + fn chain_head_unstable_body(&self, follow_subscription: String, hash: Hash); /// Retrieves the header of a pinned block. /// @@ -102,7 +97,6 @@ pub trait ChainHeadApi { hash: Hash, items: Vec>, child_trie: Option, - network_config: Option, ); /// Call into the Runtime API at a specified block's state. @@ -121,7 +115,6 @@ pub trait ChainHeadApi { hash: Hash, function: String, call_parameters: String, - network_config: Option, ); /// Unpin a block reported by the `follow` method. diff --git a/client/rpc-spec-v2/src/chain_head/chain_head.rs b/client/rpc-spec-v2/src/chain_head/chain_head.rs index 7f34bde68862c..a241052961986 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head.rs +++ b/client/rpc-spec-v2/src/chain_head/chain_head.rs @@ -23,7 +23,7 @@ use crate::{ api::ChainHeadApiServer, chain_head_follow::ChainHeadFollower, error::Error as ChainHeadRpcError, - event::{ChainHeadEvent, ChainHeadResult, ErrorEvent, FollowEvent, NetworkConfig}, + event::{ChainHeadEvent, ChainHeadResult, ErrorEvent, FollowEvent}, hex_string, subscription::{SubscriptionManagement, SubscriptionManagementError}, }, @@ -205,7 +205,6 @@ where mut sink: SubscriptionSink, follow_subscription: String, hash: Block::Hash, - _network_config: Option, ) -> SubscriptionResult { let client = self.client.clone(); let subscriptions = self.subscriptions.clone(); @@ -294,7 +293,6 @@ where hash: Block::Hash, items: Vec>, child_trie: Option, - _network_config: Option, ) -> SubscriptionResult { // Gain control over parameter parsing and returned error. let items = items @@ -362,7 +360,6 @@ where hash: Block::Hash, function: String, call_parameters: String, - _network_config: Option, ) -> SubscriptionResult { let call_parameters = Bytes::from(parse_hex_param(&mut sink, call_parameters)?); diff --git a/client/rpc-spec-v2/src/chain_head/event.rs b/client/rpc-spec-v2/src/chain_head/event.rs index 0199edee42342..259556580b9f8 100644 --- a/client/rpc-spec-v2/src/chain_head/event.rs +++ b/client/rpc-spec-v2/src/chain_head/event.rs @@ -21,27 +21,6 @@ use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer}; use sp_api::ApiError; use sp_version::RuntimeVersion; -use std::num::NonZeroUsize; - -/// The network config parameter is used when a function -/// needs to request the information from its peers. -/// -/// These values can be tweaked depending on the urgency of the JSON-RPC function call. -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct NetworkConfig { - /// The total number of peers from which the information is requested. - total_attempts: u64, - /// The maximum number of requests to perform in parallel. - /// - /// # Note - /// - /// A zero value is illegal. - max_parallel: NonZeroUsize, - /// The time, in milliseconds, after which a single requests towards one peer - /// is considered unsuccessful. - timeout_ms: u64, -} /// The operation could not be processed due to an error. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -539,22 +518,6 @@ mod tests { assert_eq!(event_dec, event); } - #[test] - fn chain_head_network_config() { - let conf = NetworkConfig { - total_attempts: 1, - max_parallel: NonZeroUsize::new(2).expect("Non zero number; qed"), - timeout_ms: 3, - }; - - let ser = serde_json::to_string(&conf).unwrap(); - let exp = r#"{"totalAttempts":1,"maxParallel":2,"timeoutMs":3}"#; - assert_eq!(ser, exp); - - let conf_dec: NetworkConfig = serde_json::from_str(exp).unwrap(); - assert_eq!(conf_dec, conf); - } - #[test] fn chain_head_storage_query() { // Item with Value. diff --git a/client/rpc-spec-v2/src/chain_head/mod.rs b/client/rpc-spec-v2/src/chain_head/mod.rs index fc138e863e538..604f565ce7585 100644 --- a/client/rpc-spec-v2/src/chain_head/mod.rs +++ b/client/rpc-spec-v2/src/chain_head/mod.rs @@ -40,7 +40,7 @@ pub use api::ChainHeadApiServer; pub use chain_head::ChainHead; pub use event::{ BestBlockChanged, ChainHeadEvent, ChainHeadResult, ErrorEvent, Finalized, FollowEvent, - Initialized, NetworkConfig, NewBlock, RuntimeEvent, RuntimeVersionEvent, + Initialized, NewBlock, RuntimeEvent, RuntimeVersionEvent, }; use sp_core::hexdisplay::{AsBytesRef, HexDisplay}; From 82dd313707c0a5d76771f72996753352ef3f3d3b Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 26 Jul 2023 15:52:50 +0300 Subject: [PATCH 2/6] chainHead/events: Add events for operations Signed-off-by: Alexandru Vasile --- client/rpc-spec-v2/src/chain_head/event.rs | 83 +++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/client/rpc-spec-v2/src/chain_head/event.rs b/client/rpc-spec-v2/src/chain_head/event.rs index 259556580b9f8..91b9e5e187712 100644 --- a/client/rpc-spec-v2/src/chain_head/event.rs +++ b/client/rpc-spec-v2/src/chain_head/event.rs @@ -168,14 +168,76 @@ pub struct Finalized { pub pruned_block_hashes: Vec, } +/// Indicate the operation id of the event. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OperationId { + /// The operation id of the event. + pub operation_id: String, +} + +/// The response of the `chainHead_body` method. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OperationBodyDone { + /// The operation id of the event. + pub operation_id: String, + /// Array of hexadecimal-encoded scale-encoded extrinsics found in the block. + pub value: Vec, +} + +/// The response of the `chainHead_call` method. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OperationCallDone { + /// The operation id of the event. + pub operation_id: String, + /// Hexadecimal-encoded output of the runtime function call. + pub output: String, +} + +/// The response of the `chainHead_call` method. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OperationStorageItems { + /// The operation id of the event. + pub operation_id: String, + /// The resulting items. + pub items: Vec>, +} + +/// Indicate a problem during the operation. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OperationError { + /// The operation id of the event. + pub operation_id: String, + /// The reason of the error. + pub error: String, +} + /// The event generated by the `follow` method. /// -/// The events are generated in the following order: +/// The block events are generated in the following order: /// 1. Initialized - generated only once to signal the latest finalized block /// 2. NewBlock - a new block was added. /// 3. BestBlockChanged - indicate that the best block is now the one from this event. The block was /// announced priorly with the `NewBlock` event. /// 4. Finalized - State the finalized and pruned blocks. +/// +/// The following events are related to operations: +/// - OperationBodyDone: The response of the `chianHead_body` +/// - OperationCallDone: The response of the `chianHead_call` +/// - OperationStorageItems: Items produced by the `chianHead_storage` +/// - OperationWaitingForContinue: Generated after OperationStorageItems and requires the user to +/// call `chainHead_continue` +/// - OperationStorageDone: The `chianHead_storage` method has produced all the results +/// - OperationInaccessible: The server was unable to provide the result, retries might succeed in +/// the future +/// - OperationError: The server encountered an error, retries will not succeed +/// +/// The stop event indicates that the JSON-RPC server was unable to provide a consistent list of +/// the blocks at the head of the chain. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[serde(tag = "event")] @@ -190,6 +252,25 @@ pub enum FollowEvent { BestBlockChanged(BestBlockChanged), /// A list of finalized and pruned blocks. Finalized(Finalized), + /// The response of the `chainHead_body` method. + OperationBodyDone(OperationBodyDone), + /// The response of the `chainHead_call` method. + OperationCallDone(OperationCallDone), + /// Yield one or more items found in the storage. + OperationStorageItems(OperationStorageItems), + /// Ask the user to call `chainHead_continue` to produce more events + /// regarding the operation id. + OperationWaitingForContinue(OperationId), + /// The responses of the `chainHead_storage` method have been produced. + OperationStorageDone(OperationId), + /// The RPC server was unable to provide the response of the following operation id. + /// + /// Repeating the same operation in the future might succeed. + OperationInaccessible(OperationId), + /// The RPC server encountered an error while processing an operation id. + /// + /// Repeating the same operation in the future will not succeed. + OperationError(OperationError), /// The subscription is dropped and no further events /// will be generated. Stop, From e0e55b980c5d834deb44cdf3743084bec0435ede Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 26 Jul 2023 19:32:26 +0300 Subject: [PATCH 3/6] chainHead/tests: Test chainHead events serialize/deserialize Signed-off-by: Alexandru Vasile --- client/rpc-spec-v2/src/chain_head/event.rs | 103 +++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/client/rpc-spec-v2/src/chain_head/event.rs b/client/rpc-spec-v2/src/chain_head/event.rs index 91b9e5e187712..6e5801b632de8 100644 --- a/client/rpc-spec-v2/src/chain_head/event.rs +++ b/client/rpc-spec-v2/src/chain_head/event.rs @@ -537,6 +537,109 @@ mod tests { assert_eq!(event_dec, event); } + #[test] + fn follow_op_body_event() { + let event: FollowEvent = FollowEvent::OperationBodyDone(OperationBodyDone { + operation_id: "123".into(), + value: vec!["0x1".into()], + }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"event":"operationBodyDone","operationId":"123","value":["0x1"]}"#; + assert_eq!(ser, exp); + + let event_dec: FollowEvent = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + } + + #[test] + fn follow_op_call_event() { + let event: FollowEvent = FollowEvent::OperationCallDone(OperationCallDone { + operation_id: "123".into(), + output: "0x1".into(), + }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"event":"operationCallDone","operationId":"123","output":"0x1"}"#; + assert_eq!(ser, exp); + + let event_dec: FollowEvent = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + } + + #[test] + fn follow_op_storage_items_event() { + let event: FollowEvent = + FollowEvent::OperationStorageItems(OperationStorageItems { + operation_id: "123".into(), + items: vec![StorageResult { + key: "0x1".into(), + result: StorageResultType::Value("0x123".to_string()), + }], + }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"event":"operationStorageItems","operationId":"123","items":[{"key":"0x1","value":"0x123"}]}"#; + assert_eq!(ser, exp); + + let event_dec: FollowEvent = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + } + + #[test] + fn follow_op_wait_event() { + let event: FollowEvent = + FollowEvent::OperationWaitingForContinue(OperationId { operation_id: "123".into() }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"event":"operationWaitingForContinue","operationId":"123"}"#; + assert_eq!(ser, exp); + + let event_dec: FollowEvent = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + } + + #[test] + fn follow_op_storage_done_event() { + let event: FollowEvent = + FollowEvent::OperationStorageDone(OperationId { operation_id: "123".into() }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"event":"operationStorageDone","operationId":"123"}"#; + assert_eq!(ser, exp); + + let event_dec: FollowEvent = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + } + + #[test] + fn follow_op_inaccessible_event() { + let event: FollowEvent = + FollowEvent::OperationInaccessible(OperationId { operation_id: "123".into() }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"event":"operationInaccessible","operationId":"123"}"#; + assert_eq!(ser, exp); + + let event_dec: FollowEvent = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + } + + #[test] + fn follow_op_error_event() { + let event: FollowEvent = FollowEvent::OperationError(OperationError { + operation_id: "123".into(), + error: "reason".into(), + }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"event":"operationError","operationId":"123","error":"reason"}"#; + assert_eq!(ser, exp); + + let event_dec: FollowEvent = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + } + #[test] fn follow_stop_event() { let event: FollowEvent = FollowEvent::Stop; From c099d360a8d572b5c7ecb38c94aa4ee6c803f7b0 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 26 Jul 2023 19:57:03 +0300 Subject: [PATCH 4/6] chainHead/events: Remove generics from the storage event Signed-off-by: Alexandru Vasile --- .../rpc-spec-v2/src/chain_head/chain_head.rs | 7 +-- .../src/chain_head/chain_head_storage.rs | 20 +++---- client/rpc-spec-v2/src/chain_head/event.rs | 56 +++++++++++-------- client/rpc-spec-v2/src/chain_head/tests.rs | 56 +++++++++---------- 4 files changed, 72 insertions(+), 67 deletions(-) diff --git a/client/rpc-spec-v2/src/chain_head/chain_head.rs b/client/rpc-spec-v2/src/chain_head/chain_head.rs index a241052961986..a2c9afc034906 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head.rs +++ b/client/rpc-spec-v2/src/chain_head/chain_head.rs @@ -325,7 +325,7 @@ where Ok(block) => block, Err(SubscriptionManagementError::SubscriptionAbsent) => { // Invalid invalid subscription ID. - let _ = sink.send(&ChainHeadStorageEvent::::Disjoint); + let _ = sink.send(&ChainHeadStorageEvent::Disjoint); return Ok(()) }, Err(SubscriptionManagementError::BlockHashAbsent) => { @@ -334,9 +334,8 @@ where return Ok(()) }, Err(error) => { - let _ = sink.send(&ChainHeadStorageEvent::::Error(ErrorEvent { - error: error.to_string(), - })); + let _ = sink + .send(&ChainHeadStorageEvent::Error(ErrorEvent { error: error.to_string() })); return Ok(()) }, }; diff --git a/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs b/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs index 310e48901876c..df1600628ded4 100644 --- a/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs +++ b/client/rpc-spec-v2/src/chain_head/chain_head_storage.rs @@ -70,10 +70,10 @@ fn is_key_queryable(key: &[u8]) -> bool { } /// The result of making a query call. -type QueryResult = Result>, ChainHeadStorageEvent>; +type QueryResult = Result, ChainHeadStorageEvent>; /// The result of iterating over keys. -type QueryIterResult = Result>, ChainHeadStorageEvent>; +type QueryIterResult = Result, ChainHeadStorageEvent>; impl ChainHeadStorage where @@ -96,13 +96,13 @@ where result .map(|opt| { - QueryResult::Ok(opt.map(|storage_data| StorageResult:: { + QueryResult::Ok(opt.map(|storage_data| StorageResult { key: hex_string(&key.0), result: StorageResultType::Value(hex_string(&storage_data.0)), })) }) .unwrap_or_else(|err| { - QueryResult::Err(ChainHeadStorageEvent::::Error(ErrorEvent { + QueryResult::Err(ChainHeadStorageEvent::Error(ErrorEvent { error: err.to_string(), })) }) @@ -123,13 +123,13 @@ where result .map(|opt| { - QueryResult::Ok(opt.map(|storage_data| StorageResult:: { + QueryResult::Ok(opt.map(|storage_data| StorageResult { key: hex_string(&key.0), result: StorageResultType::Hash(hex_string(&storage_data.as_ref())), })) }) .unwrap_or_else(|err| { - QueryResult::Err(ChainHeadStorageEvent::::Error(ErrorEvent { + QueryResult::Err(ChainHeadStorageEvent::Error(ErrorEvent { error: err.to_string(), })) }) @@ -148,9 +148,7 @@ where } else { self.client.storage_keys(hash, Some(key), None) } - .map_err(|err| { - ChainHeadStorageEvent::::Error(ErrorEvent { error: err.to_string() }) - })?; + .map_err(|err| ChainHeadStorageEvent::Error(ErrorEvent { error: err.to_string() }))?; let mut ret = Vec::with_capacity(MAX_ITER_ITEMS); let mut keys_iter = keys_iter.take(MAX_ITER_ITEMS); @@ -178,7 +176,7 @@ where ) { if let Some(child_key) = child_key.as_ref() { if !is_key_queryable(child_key.storage_key()) { - let _ = sink.send(&ChainHeadStorageEvent::::Done); + let _ = sink.send(&ChainHeadStorageEvent::Done); return } } @@ -242,6 +240,6 @@ where let _ = sink.send(&event); } - let _ = sink.send(&ChainHeadStorageEvent::::Done); + let _ = sink.send(&ChainHeadStorageEvent::Done); } } diff --git a/client/rpc-spec-v2/src/chain_head/event.rs b/client/rpc-spec-v2/src/chain_head/event.rs index 6e5801b632de8..cbf1d3fe72026 100644 --- a/client/rpc-spec-v2/src/chain_head/event.rs +++ b/client/rpc-spec-v2/src/chain_head/event.rs @@ -203,7 +203,7 @@ pub struct OperationStorageItems { /// The operation id of the event. pub operation_id: String, /// The resulting items. - pub items: Vec>, + pub items: Vec, } /// Indicate a problem during the operation. @@ -331,33 +331,33 @@ pub enum StorageQueryType { /// The storage result. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct StorageResult { +pub struct StorageResult { /// The hex-encoded key of the result. pub key: String, /// The result of the query. #[serde(flatten)] - pub result: StorageResultType, + pub result: StorageResultType, } /// The type of the storage query. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] -pub enum StorageResultType { +pub enum StorageResultType { /// Fetch the value of the provided key. - Value(T), + Value(String), /// Fetch the hash of the value of the provided key. - Hash(T), + Hash(String), /// Fetch the closest descendant merkle value. - ClosestDescendantMerkleValue(T), + ClosestDescendantMerkleValue(String), } /// The event generated by storage method. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] #[serde(tag = "event")] -pub enum ChainHeadStorageEvent { +pub enum ChainHeadStorageEvent { /// The request produced multiple result items. - Items(ItemsEvent), + Items(ItemsEvent), /// The request produced multiple result items. WaitForContinue, /// The request completed successfully and all the results were provided. @@ -375,9 +375,9 @@ pub enum ChainHeadStorageEvent { /// The request produced multiple result items. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ItemsEvent { +pub struct ItemsEvent { /// The resulting items. - pub items: Vec>, + pub items: Vec, } #[cfg(test)] @@ -759,36 +759,38 @@ mod tests { #[test] fn chain_head_storage_result() { // Item with Value. - let item = StorageResult { key: "0x1".into(), result: StorageResultType::Value("res") }; + let item = + StorageResult { key: "0x1".into(), result: StorageResultType::Value("res".into()) }; // Encode let ser = serde_json::to_string(&item).unwrap(); let exp = r#"{"key":"0x1","value":"res"}"#; assert_eq!(ser, exp); // Decode - let dec: StorageResult<&str> = serde_json::from_str(exp).unwrap(); + let dec: StorageResult = serde_json::from_str(exp).unwrap(); assert_eq!(dec, item); // Item with Hash. - let item = StorageResult { key: "0x1".into(), result: StorageResultType::Hash("res") }; + let item = + StorageResult { key: "0x1".into(), result: StorageResultType::Hash("res".into()) }; // Encode let ser = serde_json::to_string(&item).unwrap(); let exp = r#"{"key":"0x1","hash":"res"}"#; assert_eq!(ser, exp); // Decode - let dec: StorageResult<&str> = serde_json::from_str(exp).unwrap(); + let dec: StorageResult = serde_json::from_str(exp).unwrap(); assert_eq!(dec, item); // Item with DescendantsValues. let item = StorageResult { key: "0x1".into(), - result: StorageResultType::ClosestDescendantMerkleValue("res"), + result: StorageResultType::ClosestDescendantMerkleValue("res".into()), }; // Encode let ser = serde_json::to_string(&item).unwrap(); let exp = r#"{"key":"0x1","closest-descendant-merkle-value":"res"}"#; assert_eq!(ser, exp); // Decode - let dec: StorageResult<&str> = serde_json::from_str(exp).unwrap(); + let dec: StorageResult = serde_json::from_str(exp).unwrap(); assert_eq!(dec, item); } @@ -797,8 +799,14 @@ mod tests { // Event with Items. let event = ChainHeadStorageEvent::Items(ItemsEvent { items: vec![ - StorageResult { key: "0x1".into(), result: StorageResultType::Value("first") }, - StorageResult { key: "0x2".into(), result: StorageResultType::Hash("second") }, + StorageResult { + key: "0x1".into(), + result: StorageResultType::Value("first".into()), + }, + StorageResult { + key: "0x2".into(), + result: StorageResultType::Hash("second".into()), + }, ], }); // Encode @@ -806,7 +814,7 @@ mod tests { let exp = r#"{"event":"items","items":[{"key":"0x1","value":"first"},{"key":"0x2","hash":"second"}]}"#; assert_eq!(ser, exp); // Decode - let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); + let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap(); assert_eq!(dec, event); // Event with WaitForContinue. @@ -816,7 +824,7 @@ mod tests { let exp = r#"{"event":"wait-for-continue"}"#; assert_eq!(ser, exp); // Decode - let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); + let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap(); assert_eq!(dec, event); // Event with Done. @@ -826,7 +834,7 @@ mod tests { let exp = r#"{"event":"done"}"#; assert_eq!(ser, exp); // Decode - let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); + let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap(); assert_eq!(dec, event); // Event with Inaccessible. @@ -836,7 +844,7 @@ mod tests { let exp = r#"{"event":"inaccessible"}"#; assert_eq!(ser, exp); // Decode - let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); + let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap(); assert_eq!(dec, event); // Event with Inaccessible. @@ -846,7 +854,7 @@ mod tests { let exp = r#"{"event":"error","error":"reason"}"#; assert_eq!(ser, exp); // Decode - let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); + let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap(); assert_eq!(dec, event); } } diff --git a/client/rpc-spec-v2/src/chain_head/tests.rs b/client/rpc-spec-v2/src/chain_head/tests.rs index 5608a474c7185..fc2f1e85b42a3 100644 --- a/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/client/rpc-spec-v2/src/chain_head/tests.rs @@ -532,8 +532,8 @@ async fn get_storage_hash() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; - assert_eq!(event, ChainHeadStorageEvent::::Disjoint); + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + assert_eq!(event, ChainHeadStorageEvent::Disjoint); // Valid subscription ID with invalid block hash will error. let err = api @@ -563,7 +563,7 @@ async fn get_storage_hash() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; // The `Done` event is generated directly since the key does not have any value associated. assert_matches!(event, ChainHeadStorageEvent::Done); @@ -597,9 +597,9 @@ async fn get_storage_hash() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; - assert_matches!(event, ChainHeadStorageEvent::::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Hash(expected_hash)); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + assert_matches!(event, ChainHeadStorageEvent::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Hash(expected_hash)); + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); // Child value set in `setup_api`. @@ -618,9 +618,9 @@ async fn get_storage_hash() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; - assert_matches!(event, ChainHeadStorageEvent::::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Hash(expected_hash)); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + assert_matches!(event, ChainHeadStorageEvent::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Hash(expected_hash)); + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); } @@ -669,13 +669,13 @@ async fn get_storage_multi_query_iter() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; - assert_matches!(event, ChainHeadStorageEvent::::Items(res) if res.items.len() == 2 && + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + assert_matches!(event, ChainHeadStorageEvent::Items(res) if res.items.len() == 2 && res.items[0].key == key && res.items[1].key == key && res.items[0].result == StorageResultType::Hash(expected_hash) && res.items[1].result == StorageResultType::Value(expected_value)); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); // Child value set in `setup_api`. @@ -704,13 +704,13 @@ async fn get_storage_multi_query_iter() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; - assert_matches!(event, ChainHeadStorageEvent::::Items(res) if res.items.len() == 2 && + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + assert_matches!(event, ChainHeadStorageEvent::Items(res) if res.items.len() == 2 && res.items[0].key == key && res.items[1].key == key && res.items[0].result == StorageResultType::Hash(expected_hash) && res.items[1].result == StorageResultType::Value(expected_value)); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); } @@ -733,8 +733,8 @@ async fn get_storage_value() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; - assert_eq!(event, ChainHeadStorageEvent::::Disjoint); + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + assert_eq!(event, ChainHeadStorageEvent::Disjoint); // Valid subscription ID with invalid block hash will error. let err = api @@ -764,7 +764,7 @@ async fn get_storage_value() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; // The `Done` event is generated directly since the key does not have any value associated. assert_matches!(event, ChainHeadStorageEvent::Done); @@ -798,9 +798,9 @@ async fn get_storage_value() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; - assert_matches!(event, ChainHeadStorageEvent::::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Value(expected_value)); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + assert_matches!(event, ChainHeadStorageEvent::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Value(expected_value)); + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); // Child value set in `setup_api`. @@ -819,9 +819,9 @@ async fn get_storage_value() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; - assert_matches!(event, ChainHeadStorageEvent::::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Value(expected_value)); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + assert_matches!(event, ChainHeadStorageEvent::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Value(expected_value)); + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); } @@ -846,7 +846,7 @@ async fn get_storage_wrong_key() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); // Key is prefixed by DEFAULT_CHILD_STORAGE_KEY_PREFIX. @@ -864,7 +864,7 @@ async fn get_storage_wrong_key() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); // Child key is prefixed by CHILD_STORAGE_KEY_PREFIX. @@ -883,7 +883,7 @@ async fn get_storage_wrong_key() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); // Child key is prefixed by DEFAULT_CHILD_STORAGE_KEY_PREFIX. @@ -902,7 +902,7 @@ async fn get_storage_wrong_key() { ) .await .unwrap(); - let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; + let event: ChainHeadStorageEvent = get_next_event(&mut sub).await; assert_matches!(event, ChainHeadStorageEvent::Done); } From 462094000d4440232e3c5283931a24ed0f45f7f0 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 27 Jul 2023 12:14:15 +0300 Subject: [PATCH 5/6] chainHead/events: Rename kebab-case to camelCase Signed-off-by: Alexandru Vasile --- client/rpc-spec-v2/src/chain_head/event.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/rpc-spec-v2/src/chain_head/event.rs b/client/rpc-spec-v2/src/chain_head/event.rs index cbf1d3fe72026..5565a0c986561 100644 --- a/client/rpc-spec-v2/src/chain_head/event.rs +++ b/client/rpc-spec-v2/src/chain_head/event.rs @@ -314,7 +314,7 @@ pub struct StorageQuery { /// The type of the storage query. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] +#[serde(rename_all = "camelCase")] pub enum StorageQueryType { /// Fetch the value of the provided key. Value, @@ -341,7 +341,7 @@ pub struct StorageResult { /// The type of the storage query. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] +#[serde(rename_all = "camelCase")] pub enum StorageResultType { /// Fetch the value of the provided key. Value(String), @@ -728,7 +728,7 @@ mod tests { let item = StorageQuery { key: "0x1", query_type: StorageQueryType::DescendantsValues }; // Encode let ser = serde_json::to_string(&item).unwrap(); - let exp = r#"{"key":"0x1","type":"descendants-values"}"#; + let exp = r#"{"key":"0x1","type":"descendantsValues"}"#; assert_eq!(ser, exp); // Decode let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap(); @@ -738,7 +738,7 @@ mod tests { let item = StorageQuery { key: "0x1", query_type: StorageQueryType::DescendantsHashes }; // Encode let ser = serde_json::to_string(&item).unwrap(); - let exp = r#"{"key":"0x1","type":"descendants-hashes"}"#; + let exp = r#"{"key":"0x1","type":"descendantsHashes"}"#; assert_eq!(ser, exp); // Decode let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap(); @@ -749,7 +749,7 @@ mod tests { StorageQuery { key: "0x1", query_type: StorageQueryType::ClosestDescendantMerkleValue }; // Encode let ser = serde_json::to_string(&item).unwrap(); - let exp = r#"{"key":"0x1","type":"closest-descendant-merkle-value"}"#; + let exp = r#"{"key":"0x1","type":"closestDescendantMerkleValue"}"#; assert_eq!(ser, exp); // Decode let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap(); @@ -787,7 +787,7 @@ mod tests { }; // Encode let ser = serde_json::to_string(&item).unwrap(); - let exp = r#"{"key":"0x1","closest-descendant-merkle-value":"res"}"#; + let exp = r#"{"key":"0x1","closestDescendantMerkleValue":"res"}"#; assert_eq!(ser, exp); // Decode let dec: StorageResult = serde_json::from_str(exp).unwrap(); From 6dad8514827a75148b0f68294e1ede6509b9a635 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 27 Jul 2023 13:39:28 +0300 Subject: [PATCH 6/6] chainHead/events: Add methodResponse object Signed-off-by: Alexandru Vasile --- client/rpc-spec-v2/src/chain_head/event.rs | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/client/rpc-spec-v2/src/chain_head/event.rs b/client/rpc-spec-v2/src/chain_head/event.rs index 5565a0c986561..971a0a9f46b95 100644 --- a/client/rpc-spec-v2/src/chain_head/event.rs +++ b/client/rpc-spec-v2/src/chain_head/event.rs @@ -380,6 +380,29 @@ pub struct ItemsEvent { pub items: Vec, } +/// The method respose of `chainHead_body`, `chainHead_call` and `chainHead_storage`. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(tag = "result")] +pub enum MethodResponse { + /// The method has started. + Started(MethodResponseStarted), + /// The RPC server cannot handle the request at the moment. + LimitReached, +} + +/// The `started` result of a method. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MethodResponseStarted { + /// The operation id of the response. + pub operation_id: String, + /// The number of items from the back of the `chainHead_storage` that have been discarded. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub discarded_items: Option, +} + #[cfg(test)] mod tests { use super::*; @@ -652,6 +675,45 @@ mod tests { assert_eq!(event_dec, event); } + #[test] + fn method_response() { + // Response of `call` and `body` + let event = MethodResponse::Started(MethodResponseStarted { + operation_id: "123".into(), + discarded_items: None, + }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"result":"started","operationId":"123"}"#; + assert_eq!(ser, exp); + + let event_dec: MethodResponse = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + + // Response of `storage` + let event = MethodResponse::Started(MethodResponseStarted { + operation_id: "123".into(), + discarded_items: Some(1), + }); + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"result":"started","operationId":"123","discardedItems":1}"#; + assert_eq!(ser, exp); + + let event_dec: MethodResponse = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + + // Limit reached. + let event = MethodResponse::LimitReached; + + let ser = serde_json::to_string(&event).unwrap(); + let exp = r#"{"result":"limitReached"}"#; + assert_eq!(ser, exp); + + let event_dec: MethodResponse = serde_json::from_str(exp).unwrap(); + assert_eq!(event_dec, event); + } + #[test] fn chain_head_done_event() { let event: ChainHeadEvent =