chainHead: Sync events with spec (#14654)

* chainHead/events: Remove network config

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* chainHead/events: Add events for operations

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* chainHead/tests: Test chainHead events serialize/deserialize

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* chainHead/events: Remove generics from the storage event

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* chainHead/events: Rename kebab-case to camelCase

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* chainHead/events: Add methodResponse object

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
Alexandru Vasile
2023-07-31 10:26:13 +03:00
committed by GitHub
parent 6da4e90e51
commit 6d5f0a1f1d
6 changed files with 328 additions and 124 deletions
@@ -19,7 +19,7 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
//! API trait of the chain head. //! 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}; use jsonrpsee::{core::RpcResult, proc_macros::rpc};
#[rpc(client, server)] #[rpc(client, server)]
@@ -52,12 +52,7 @@ pub trait ChainHeadApi<Hash> {
unsubscribe = "chainHead_unstable_stopBody", unsubscribe = "chainHead_unstable_stopBody",
item = ChainHeadEvent<String>, item = ChainHeadEvent<String>,
)] )]
fn chain_head_unstable_body( fn chain_head_unstable_body(&self, follow_subscription: String, hash: Hash);
&self,
follow_subscription: String,
hash: Hash,
network_config: Option<NetworkConfig>,
);
/// Retrieves the header of a pinned block. /// Retrieves the header of a pinned block.
/// ///
@@ -102,7 +97,6 @@ pub trait ChainHeadApi<Hash> {
hash: Hash, hash: Hash,
items: Vec<StorageQuery<String>>, items: Vec<StorageQuery<String>>,
child_trie: Option<String>, child_trie: Option<String>,
network_config: Option<NetworkConfig>,
); );
/// Call into the Runtime API at a specified block's state. /// Call into the Runtime API at a specified block's state.
@@ -121,7 +115,6 @@ pub trait ChainHeadApi<Hash> {
hash: Hash, hash: Hash,
function: String, function: String,
call_parameters: String, call_parameters: String,
network_config: Option<NetworkConfig>,
); );
/// Unpin a block reported by the `follow` method. /// Unpin a block reported by the `follow` method.
@@ -23,7 +23,7 @@ use crate::{
api::ChainHeadApiServer, api::ChainHeadApiServer,
chain_head_follow::ChainHeadFollower, chain_head_follow::ChainHeadFollower,
error::Error as ChainHeadRpcError, error::Error as ChainHeadRpcError,
event::{ChainHeadEvent, ChainHeadResult, ErrorEvent, FollowEvent, NetworkConfig}, event::{ChainHeadEvent, ChainHeadResult, ErrorEvent, FollowEvent},
hex_string, hex_string,
subscription::{SubscriptionManagement, SubscriptionManagementError}, subscription::{SubscriptionManagement, SubscriptionManagementError},
}, },
@@ -205,7 +205,6 @@ where
mut sink: SubscriptionSink, mut sink: SubscriptionSink,
follow_subscription: String, follow_subscription: String,
hash: Block::Hash, hash: Block::Hash,
_network_config: Option<NetworkConfig>,
) -> SubscriptionResult { ) -> SubscriptionResult {
let client = self.client.clone(); let client = self.client.clone();
let subscriptions = self.subscriptions.clone(); let subscriptions = self.subscriptions.clone();
@@ -294,7 +293,6 @@ where
hash: Block::Hash, hash: Block::Hash,
items: Vec<StorageQuery<String>>, items: Vec<StorageQuery<String>>,
child_trie: Option<String>, child_trie: Option<String>,
_network_config: Option<NetworkConfig>,
) -> SubscriptionResult { ) -> SubscriptionResult {
// Gain control over parameter parsing and returned error. // Gain control over parameter parsing and returned error.
let items = items let items = items
@@ -327,7 +325,7 @@ where
Ok(block) => block, Ok(block) => block,
Err(SubscriptionManagementError::SubscriptionAbsent) => { Err(SubscriptionManagementError::SubscriptionAbsent) => {
// Invalid invalid subscription ID. // Invalid invalid subscription ID.
let _ = sink.send(&ChainHeadStorageEvent::<String>::Disjoint); let _ = sink.send(&ChainHeadStorageEvent::Disjoint);
return Ok(()) return Ok(())
}, },
Err(SubscriptionManagementError::BlockHashAbsent) => { Err(SubscriptionManagementError::BlockHashAbsent) => {
@@ -336,9 +334,8 @@ where
return Ok(()) return Ok(())
}, },
Err(error) => { Err(error) => {
let _ = sink.send(&ChainHeadStorageEvent::<String>::Error(ErrorEvent { let _ = sink
error: error.to_string(), .send(&ChainHeadStorageEvent::Error(ErrorEvent { error: error.to_string() }));
}));
return Ok(()) return Ok(())
}, },
}; };
@@ -362,7 +359,6 @@ where
hash: Block::Hash, hash: Block::Hash,
function: String, function: String,
call_parameters: String, call_parameters: String,
_network_config: Option<NetworkConfig>,
) -> SubscriptionResult { ) -> SubscriptionResult {
let call_parameters = Bytes::from(parse_hex_param(&mut sink, call_parameters)?); let call_parameters = Bytes::from(parse_hex_param(&mut sink, call_parameters)?);
@@ -70,10 +70,10 @@ fn is_key_queryable(key: &[u8]) -> bool {
} }
/// The result of making a query call. /// The result of making a query call.
type QueryResult = Result<Option<StorageResult<String>>, ChainHeadStorageEvent<String>>; type QueryResult = Result<Option<StorageResult>, ChainHeadStorageEvent>;
/// The result of iterating over keys. /// The result of iterating over keys.
type QueryIterResult = Result<Vec<StorageResult<String>>, ChainHeadStorageEvent<String>>; type QueryIterResult = Result<Vec<StorageResult>, ChainHeadStorageEvent>;
impl<Client, Block, BE> ChainHeadStorage<Client, Block, BE> impl<Client, Block, BE> ChainHeadStorage<Client, Block, BE>
where where
@@ -96,13 +96,13 @@ where
result result
.map(|opt| { .map(|opt| {
QueryResult::Ok(opt.map(|storage_data| StorageResult::<String> { QueryResult::Ok(opt.map(|storage_data| StorageResult {
key: hex_string(&key.0), key: hex_string(&key.0),
result: StorageResultType::Value(hex_string(&storage_data.0)), result: StorageResultType::Value(hex_string(&storage_data.0)),
})) }))
}) })
.unwrap_or_else(|err| { .unwrap_or_else(|err| {
QueryResult::Err(ChainHeadStorageEvent::<String>::Error(ErrorEvent { QueryResult::Err(ChainHeadStorageEvent::Error(ErrorEvent {
error: err.to_string(), error: err.to_string(),
})) }))
}) })
@@ -123,13 +123,13 @@ where
result result
.map(|opt| { .map(|opt| {
QueryResult::Ok(opt.map(|storage_data| StorageResult::<String> { QueryResult::Ok(opt.map(|storage_data| StorageResult {
key: hex_string(&key.0), key: hex_string(&key.0),
result: StorageResultType::Hash(hex_string(&storage_data.as_ref())), result: StorageResultType::Hash(hex_string(&storage_data.as_ref())),
})) }))
}) })
.unwrap_or_else(|err| { .unwrap_or_else(|err| {
QueryResult::Err(ChainHeadStorageEvent::<String>::Error(ErrorEvent { QueryResult::Err(ChainHeadStorageEvent::Error(ErrorEvent {
error: err.to_string(), error: err.to_string(),
})) }))
}) })
@@ -148,9 +148,7 @@ where
} else { } else {
self.client.storage_keys(hash, Some(key), None) self.client.storage_keys(hash, Some(key), None)
} }
.map_err(|err| { .map_err(|err| ChainHeadStorageEvent::Error(ErrorEvent { error: err.to_string() }))?;
ChainHeadStorageEvent::<String>::Error(ErrorEvent { error: err.to_string() })
})?;
let mut ret = Vec::with_capacity(MAX_ITER_ITEMS); let mut ret = Vec::with_capacity(MAX_ITER_ITEMS);
let mut keys_iter = keys_iter.take(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 let Some(child_key) = child_key.as_ref() {
if !is_key_queryable(child_key.storage_key()) { if !is_key_queryable(child_key.storage_key()) {
let _ = sink.send(&ChainHeadStorageEvent::<String>::Done); let _ = sink.send(&ChainHeadStorageEvent::Done);
return return
} }
} }
@@ -242,6 +240,6 @@ where
let _ = sink.send(&event); let _ = sink.send(&event);
} }
let _ = sink.send(&ChainHeadStorageEvent::<String>::Done); let _ = sink.send(&ChainHeadStorageEvent::Done);
} }
} }
@@ -21,27 +21,6 @@
use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer}; use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};
use sp_api::ApiError; use sp_api::ApiError;
use sp_version::RuntimeVersion; 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. /// The operation could not be processed due to an error.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -189,14 +168,76 @@ pub struct Finalized<Hash> {
pub pruned_block_hashes: Vec<Hash>, pub pruned_block_hashes: Vec<Hash>,
} }
/// 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<String>,
}
/// 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<StorageResult>,
}
/// 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 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 /// 1. Initialized - generated only once to signal the latest finalized block
/// 2. NewBlock - a new block was added. /// 2. NewBlock - a new block was added.
/// 3. BestBlockChanged - indicate that the best block is now the one from this event. The block was /// 3. BestBlockChanged - indicate that the best block is now the one from this event. The block was
/// announced priorly with the `NewBlock` event. /// announced priorly with the `NewBlock` event.
/// 4. Finalized - State the finalized and pruned blocks. /// 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)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
#[serde(tag = "event")] #[serde(tag = "event")]
@@ -211,6 +252,25 @@ pub enum FollowEvent<Hash> {
BestBlockChanged(BestBlockChanged<Hash>), BestBlockChanged(BestBlockChanged<Hash>),
/// A list of finalized and pruned blocks. /// A list of finalized and pruned blocks.
Finalized(Finalized<Hash>), Finalized(Finalized<Hash>),
/// 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 /// The subscription is dropped and no further events
/// will be generated. /// will be generated.
Stop, Stop,
@@ -254,7 +314,7 @@ pub struct StorageQuery<Key> {
/// The type of the storage query. /// The type of the storage query.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "camelCase")]
pub enum StorageQueryType { pub enum StorageQueryType {
/// Fetch the value of the provided key. /// Fetch the value of the provided key.
Value, Value,
@@ -271,33 +331,33 @@ pub enum StorageQueryType {
/// The storage result. /// The storage result.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct StorageResult<T> { pub struct StorageResult {
/// The hex-encoded key of the result. /// The hex-encoded key of the result.
pub key: String, pub key: String,
/// The result of the query. /// The result of the query.
#[serde(flatten)] #[serde(flatten)]
pub result: StorageResultType<T>, pub result: StorageResultType,
} }
/// The type of the storage query. /// The type of the storage query.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "camelCase")]
pub enum StorageResultType<T> { pub enum StorageResultType {
/// Fetch the value of the provided key. /// Fetch the value of the provided key.
Value(T), Value(String),
/// Fetch the hash of the value of the provided key. /// Fetch the hash of the value of the provided key.
Hash(T), Hash(String),
/// Fetch the closest descendant merkle value. /// Fetch the closest descendant merkle value.
ClosestDescendantMerkleValue(T), ClosestDescendantMerkleValue(String),
} }
/// The event generated by storage method. /// The event generated by storage method.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
#[serde(tag = "event")] #[serde(tag = "event")]
pub enum ChainHeadStorageEvent<T> { pub enum ChainHeadStorageEvent {
/// The request produced multiple result items. /// The request produced multiple result items.
Items(ItemsEvent<T>), Items(ItemsEvent),
/// The request produced multiple result items. /// The request produced multiple result items.
WaitForContinue, WaitForContinue,
/// The request completed successfully and all the results were provided. /// The request completed successfully and all the results were provided.
@@ -315,9 +375,32 @@ pub enum ChainHeadStorageEvent<T> {
/// The request produced multiple result items. /// The request produced multiple result items.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ItemsEvent<T> { pub struct ItemsEvent {
/// The resulting items. /// The resulting items.
pub items: Vec<StorageResult<T>>, pub items: Vec<StorageResult>,
}
/// 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<usize>,
} }
#[cfg(test)] #[cfg(test)]
@@ -477,6 +560,109 @@ mod tests {
assert_eq!(event_dec, event); assert_eq!(event_dec, event);
} }
#[test]
fn follow_op_body_event() {
let event: FollowEvent<String> = 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<String> = serde_json::from_str(exp).unwrap();
assert_eq!(event_dec, event);
}
#[test]
fn follow_op_call_event() {
let event: FollowEvent<String> = 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<String> = serde_json::from_str(exp).unwrap();
assert_eq!(event_dec, event);
}
#[test]
fn follow_op_storage_items_event() {
let event: FollowEvent<String> =
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<String> = serde_json::from_str(exp).unwrap();
assert_eq!(event_dec, event);
}
#[test]
fn follow_op_wait_event() {
let event: FollowEvent<String> =
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<String> = serde_json::from_str(exp).unwrap();
assert_eq!(event_dec, event);
}
#[test]
fn follow_op_storage_done_event() {
let event: FollowEvent<String> =
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<String> = serde_json::from_str(exp).unwrap();
assert_eq!(event_dec, event);
}
#[test]
fn follow_op_inaccessible_event() {
let event: FollowEvent<String> =
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<String> = serde_json::from_str(exp).unwrap();
assert_eq!(event_dec, event);
}
#[test]
fn follow_op_error_event() {
let event: FollowEvent<String> = 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<String> = serde_json::from_str(exp).unwrap();
assert_eq!(event_dec, event);
}
#[test] #[test]
fn follow_stop_event() { fn follow_stop_event() {
let event: FollowEvent<String> = FollowEvent::Stop; let event: FollowEvent<String> = FollowEvent::Stop;
@@ -489,6 +675,45 @@ mod tests {
assert_eq!(event_dec, event); 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] #[test]
fn chain_head_done_event() { fn chain_head_done_event() {
let event: ChainHeadEvent<String> = let event: ChainHeadEvent<String> =
@@ -539,22 +764,6 @@ mod tests {
assert_eq!(event_dec, event); 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] #[test]
fn chain_head_storage_query() { fn chain_head_storage_query() {
// Item with Value. // Item with Value.
@@ -581,7 +790,7 @@ mod tests {
let item = StorageQuery { key: "0x1", query_type: StorageQueryType::DescendantsValues }; let item = StorageQuery { key: "0x1", query_type: StorageQueryType::DescendantsValues };
// Encode // Encode
let ser = serde_json::to_string(&item).unwrap(); 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); assert_eq!(ser, exp);
// Decode // Decode
let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap(); let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap();
@@ -591,7 +800,7 @@ mod tests {
let item = StorageQuery { key: "0x1", query_type: StorageQueryType::DescendantsHashes }; let item = StorageQuery { key: "0x1", query_type: StorageQueryType::DescendantsHashes };
// Encode // Encode
let ser = serde_json::to_string(&item).unwrap(); 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); assert_eq!(ser, exp);
// Decode // Decode
let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap(); let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap();
@@ -602,7 +811,7 @@ mod tests {
StorageQuery { key: "0x1", query_type: StorageQueryType::ClosestDescendantMerkleValue }; StorageQuery { key: "0x1", query_type: StorageQueryType::ClosestDescendantMerkleValue };
// Encode // Encode
let ser = serde_json::to_string(&item).unwrap(); 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); assert_eq!(ser, exp);
// Decode // Decode
let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap(); let dec: StorageQuery<&str> = serde_json::from_str(exp).unwrap();
@@ -612,36 +821,38 @@ mod tests {
#[test] #[test]
fn chain_head_storage_result() { fn chain_head_storage_result() {
// Item with Value. // 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 // Encode
let ser = serde_json::to_string(&item).unwrap(); let ser = serde_json::to_string(&item).unwrap();
let exp = r#"{"key":"0x1","value":"res"}"#; let exp = r#"{"key":"0x1","value":"res"}"#;
assert_eq!(ser, exp); assert_eq!(ser, exp);
// Decode // Decode
let dec: StorageResult<&str> = serde_json::from_str(exp).unwrap(); let dec: StorageResult = serde_json::from_str(exp).unwrap();
assert_eq!(dec, item); assert_eq!(dec, item);
// Item with Hash. // 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 // Encode
let ser = serde_json::to_string(&item).unwrap(); let ser = serde_json::to_string(&item).unwrap();
let exp = r#"{"key":"0x1","hash":"res"}"#; let exp = r#"{"key":"0x1","hash":"res"}"#;
assert_eq!(ser, exp); assert_eq!(ser, exp);
// Decode // Decode
let dec: StorageResult<&str> = serde_json::from_str(exp).unwrap(); let dec: StorageResult = serde_json::from_str(exp).unwrap();
assert_eq!(dec, item); assert_eq!(dec, item);
// Item with DescendantsValues. // Item with DescendantsValues.
let item = StorageResult { let item = StorageResult {
key: "0x1".into(), key: "0x1".into(),
result: StorageResultType::ClosestDescendantMerkleValue("res"), result: StorageResultType::ClosestDescendantMerkleValue("res".into()),
}; };
// Encode // Encode
let ser = serde_json::to_string(&item).unwrap(); 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); assert_eq!(ser, exp);
// Decode // Decode
let dec: StorageResult<&str> = serde_json::from_str(exp).unwrap(); let dec: StorageResult = serde_json::from_str(exp).unwrap();
assert_eq!(dec, item); assert_eq!(dec, item);
} }
@@ -650,8 +861,14 @@ mod tests {
// Event with Items. // Event with Items.
let event = ChainHeadStorageEvent::Items(ItemsEvent { let event = ChainHeadStorageEvent::Items(ItemsEvent {
items: vec![ items: vec![
StorageResult { key: "0x1".into(), result: StorageResultType::Value("first") }, StorageResult {
StorageResult { key: "0x2".into(), result: StorageResultType::Hash("second") }, key: "0x1".into(),
result: StorageResultType::Value("first".into()),
},
StorageResult {
key: "0x2".into(),
result: StorageResultType::Hash("second".into()),
},
], ],
}); });
// Encode // Encode
@@ -659,7 +876,7 @@ mod tests {
let exp = r#"{"event":"items","items":[{"key":"0x1","value":"first"},{"key":"0x2","hash":"second"}]}"#; let exp = r#"{"event":"items","items":[{"key":"0x1","value":"first"},{"key":"0x2","hash":"second"}]}"#;
assert_eq!(ser, exp); assert_eq!(ser, exp);
// Decode // Decode
let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap();
assert_eq!(dec, event); assert_eq!(dec, event);
// Event with WaitForContinue. // Event with WaitForContinue.
@@ -669,7 +886,7 @@ mod tests {
let exp = r#"{"event":"wait-for-continue"}"#; let exp = r#"{"event":"wait-for-continue"}"#;
assert_eq!(ser, exp); assert_eq!(ser, exp);
// Decode // Decode
let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap();
assert_eq!(dec, event); assert_eq!(dec, event);
// Event with Done. // Event with Done.
@@ -679,7 +896,7 @@ mod tests {
let exp = r#"{"event":"done"}"#; let exp = r#"{"event":"done"}"#;
assert_eq!(ser, exp); assert_eq!(ser, exp);
// Decode // Decode
let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap();
assert_eq!(dec, event); assert_eq!(dec, event);
// Event with Inaccessible. // Event with Inaccessible.
@@ -689,7 +906,7 @@ mod tests {
let exp = r#"{"event":"inaccessible"}"#; let exp = r#"{"event":"inaccessible"}"#;
assert_eq!(ser, exp); assert_eq!(ser, exp);
// Decode // Decode
let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap();
assert_eq!(dec, event); assert_eq!(dec, event);
// Event with Inaccessible. // Event with Inaccessible.
@@ -699,7 +916,7 @@ mod tests {
let exp = r#"{"event":"error","error":"reason"}"#; let exp = r#"{"event":"error","error":"reason"}"#;
assert_eq!(ser, exp); assert_eq!(ser, exp);
// Decode // Decode
let dec: ChainHeadStorageEvent<&str> = serde_json::from_str(exp).unwrap(); let dec: ChainHeadStorageEvent = serde_json::from_str(exp).unwrap();
assert_eq!(dec, event); assert_eq!(dec, event);
} }
} }
@@ -40,7 +40,7 @@ pub use api::ChainHeadApiServer;
pub use chain_head::ChainHead; pub use chain_head::ChainHead;
pub use event::{ pub use event::{
BestBlockChanged, ChainHeadEvent, ChainHeadResult, ErrorEvent, Finalized, FollowEvent, BestBlockChanged, ChainHeadEvent, ChainHeadResult, ErrorEvent, Finalized, FollowEvent,
Initialized, NetworkConfig, NewBlock, RuntimeEvent, RuntimeVersionEvent, Initialized, NewBlock, RuntimeEvent, RuntimeVersionEvent,
}; };
use sp_core::hexdisplay::{AsBytesRef, HexDisplay}; use sp_core::hexdisplay::{AsBytesRef, HexDisplay};
@@ -532,8 +532,8 @@ async fn get_storage_hash() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_eq!(event, ChainHeadStorageEvent::<String>::Disjoint); assert_eq!(event, ChainHeadStorageEvent::Disjoint);
// Valid subscription ID with invalid block hash will error. // Valid subscription ID with invalid block hash will error.
let err = api let err = api
@@ -563,7 +563,7 @@ async fn get_storage_hash() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = 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. // The `Done` event is generated directly since the key does not have any value associated.
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
@@ -597,9 +597,9 @@ async fn get_storage_hash() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::<String>::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Hash(expected_hash)); 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<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
// Child value set in `setup_api`. // Child value set in `setup_api`.
@@ -618,9 +618,9 @@ async fn get_storage_hash() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::<String>::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Hash(expected_hash)); 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<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
} }
@@ -669,13 +669,13 @@ async fn get_storage_multi_query_iter() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::<String>::Items(res) if res.items.len() == 2 && assert_matches!(event, ChainHeadStorageEvent::Items(res) if res.items.len() == 2 &&
res.items[0].key == key && res.items[0].key == key &&
res.items[1].key == key && res.items[1].key == key &&
res.items[0].result == StorageResultType::Hash(expected_hash) && res.items[0].result == StorageResultType::Hash(expected_hash) &&
res.items[1].result == StorageResultType::Value(expected_value)); res.items[1].result == StorageResultType::Value(expected_value));
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
// Child value set in `setup_api`. // Child value set in `setup_api`.
@@ -704,13 +704,13 @@ async fn get_storage_multi_query_iter() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::<String>::Items(res) if res.items.len() == 2 && assert_matches!(event, ChainHeadStorageEvent::Items(res) if res.items.len() == 2 &&
res.items[0].key == key && res.items[0].key == key &&
res.items[1].key == key && res.items[1].key == key &&
res.items[0].result == StorageResultType::Hash(expected_hash) && res.items[0].result == StorageResultType::Hash(expected_hash) &&
res.items[1].result == StorageResultType::Value(expected_value)); res.items[1].result == StorageResultType::Value(expected_value));
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
} }
@@ -733,8 +733,8 @@ async fn get_storage_value() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_eq!(event, ChainHeadStorageEvent::<String>::Disjoint); assert_eq!(event, ChainHeadStorageEvent::Disjoint);
// Valid subscription ID with invalid block hash will error. // Valid subscription ID with invalid block hash will error.
let err = api let err = api
@@ -764,7 +764,7 @@ async fn get_storage_value() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = 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. // The `Done` event is generated directly since the key does not have any value associated.
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
@@ -798,9 +798,9 @@ async fn get_storage_value() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::<String>::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Value(expected_value)); 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<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
// Child value set in `setup_api`. // Child value set in `setup_api`.
@@ -819,9 +819,9 @@ async fn get_storage_value() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::<String>::Items(res) if res.items.len() == 1 && res.items[0].key == key && res.items[0].result == StorageResultType::Value(expected_value)); 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<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
} }
@@ -846,7 +846,7 @@ async fn get_storage_wrong_key() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
// Key is prefixed by DEFAULT_CHILD_STORAGE_KEY_PREFIX. // Key is prefixed by DEFAULT_CHILD_STORAGE_KEY_PREFIX.
@@ -864,7 +864,7 @@ async fn get_storage_wrong_key() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
// Child key is prefixed by CHILD_STORAGE_KEY_PREFIX. // Child key is prefixed by CHILD_STORAGE_KEY_PREFIX.
@@ -883,7 +883,7 @@ async fn get_storage_wrong_key() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
// Child key is prefixed by DEFAULT_CHILD_STORAGE_KEY_PREFIX. // Child key is prefixed by DEFAULT_CHILD_STORAGE_KEY_PREFIX.
@@ -902,7 +902,7 @@ async fn get_storage_wrong_key() {
) )
.await .await
.unwrap(); .unwrap();
let event: ChainHeadStorageEvent<String> = get_next_event(&mut sub).await; let event: ChainHeadStorageEvent = get_next_event(&mut sub).await;
assert_matches!(event, ChainHeadStorageEvent::Done); assert_matches!(event, ChainHeadStorageEvent::Done);
} }