Skip to content

Commit 63b3791

Browse files
lexnvskunert
authored andcommitted
rpc: Implement chainHead RPC API (paritytech#12544)
* rpc/chain_head: Add event structure for serialization Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Add tests for events Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Add API trait for `chainHead` Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Add RPC errors Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Manage subscription ID tracking for pinned blocks Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Add tests for subscription management Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Constructor for the API Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Placeholders for API implementation Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Accept RPC subscription sink Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Generate the runtime API event Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Implement the `follow` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Implement the `body` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Implement the `header` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Implement the `storage` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Implement the `call` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Implement the `unpin` method Signed-off-by: Alexandru Vasile <[email protected]> * Update `Cargo.lock` Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Implement `getGenesis` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Fix clippy Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Parse params from hex string Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Constuct API with genesis hash Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Add the finalized block to reported tree route Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Export the API and events for better ergonomics Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Add test module with helper functions Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Test block events from the `follow` pubsub Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Test `genesisHash` getter Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Test `header` method Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Test `body` method Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Test calling into the runtime API Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Test runtime for the `follow` method Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Add runtime code changes for `follow` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Remove space from rustdoc Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Use the `child_key` for storage queries Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Test `storage` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Test child trie query for `storage` method Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Event serialization typo Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Remove subscription aliases Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Add `NetworkConfig` parameter Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Named parameters as camelCase if present Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Implement From<ApiError> for RuntimeEvents Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Handle pruning of the best block in finalization window Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Generate initial block events Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Verify that initial in-memory blocks are reported Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Verify the finalized event with forks and pruned blocks Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Fix clippy Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Separate logic for generating initial events Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Handle stopping a subscription ID Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Submit events until the "Stop" event is triggered Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Separate logic for handling new and finalized blocks Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Extend subscription logic with subId handle Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Adjust to the new subscription mngmt API Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Refuse RuntimeAPI calls without the runtime flag Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Verify RuntimeAPI calls without runtime flag Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Add best block per subscription Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Check storage keys for prefixes Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Check storage queries with invalid prefixes Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Allow maximum number of pinned blocks Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Test the maximum number of pinned blocks Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Adjust to origin/master and apply clippy Signed-off-by: Alexandru Vasile <[email protected]> * client/service: Enable the `chainHead` API Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Stop subscription on client disconnect and add debug logs Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Fix sending `Stop` on subscription exit Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Check best block is descendent of latest finalized Signed-off-by: Alexandru Vasile <[email protected]> * chain_head/tests: Report events before pruning the best block Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Nonrecursive initial block generation Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Generate initial events on subscription executor Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Reduce dev-dependencies for tokio Signed-off-by: Alexandru Vasile <[email protected]> * Apply suggestions from code review Co-authored-by: Sebastian Kunert <[email protected]> * rpc/chain_head: Accept empty parameters Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Use debug of `HexDisplay` for full format Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Enable subscription ID Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Use jsonrpsee 16.2 camelCase feature for paramaters Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Use `NonZeroUsize` for `NetworkConfig` param Signed-off-by: Alexandru Vasile <[email protected]> * rpc/chain_head: Rename `runtime_updates` to `has_runtime_updates` Signed-off-by: Alexandru Vasile <[email protected]> Signed-off-by: Alexandru Vasile <[email protected]> Co-authored-by: Sebastian Kunert <[email protected]>
1 parent 033e7e9 commit 63b3791

File tree

11 files changed

+2885
-9
lines changed

11 files changed

+2885
-9
lines changed

Cargo.lock

Lines changed: 33 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/rpc-spec-v2/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,25 @@ sp-core = { version = "7.0.0", path = "../../primitives/core" }
2222
sp-runtime = { version = "7.0.0", path = "../../primitives/runtime" }
2323
sp-api = { version = "4.0.0-dev", path = "../../primitives/api" }
2424
sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" }
25+
sp-version = { version = "5.0.0", path = "../../primitives/version" }
26+
sc-client-api = { version = "4.0.0-dev", path = "../api" }
2527
codec = { package = "parity-scale-codec", version = "3.0.0" }
2628
thiserror = "1.0"
2729
serde = "1.0"
2830
hex = "0.4"
2931
futures = "0.3.21"
32+
parking_lot = "0.12.1"
33+
tokio-stream = { version = "0.1", features = ["sync"] }
34+
array-bytes = "4.1"
35+
log = "0.4.17"
36+
futures-util = { version = "0.3.19", default-features = false }
3037

3138
[dev-dependencies]
3239
serde_json = "1.0"
3340
tokio = { version = "1.22.0", features = ["macros"] }
41+
substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" }
42+
substrate-test-runtime = { version = "2.0.0", path = "../../test-utils/runtime" }
43+
sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" }
44+
sp-maybe-compressed-blob = { version = "4.1.0-dev", path = "../../primitives/maybe-compressed-blob" }
45+
sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" }
46+
assert_matches = "1.3.0"
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// This file is part of Substrate.
2+
3+
// Copyright (C) 2022 Parity Technologies (UK) Ltd.
4+
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5+
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU General Public License as published by
8+
// the Free Software Foundation, either version 3 of the License, or
9+
// (at your option) any later version.
10+
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU General Public License for more details.
15+
16+
// You should have received a copy of the GNU General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
#![allow(non_snake_case)]
20+
21+
//! API trait of the chain head.
22+
use crate::chain_head::event::{ChainHeadEvent, FollowEvent, NetworkConfig};
23+
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
24+
25+
#[rpc(client, server)]
26+
pub trait ChainHeadApi<Hash> {
27+
/// Track the state of the head of the chain: the finalized, non-finalized, and best blocks.
28+
///
29+
/// # Unstable
30+
///
31+
/// This method is unstable and subject to change in the future.
32+
#[subscription(
33+
name = "chainHead_unstable_follow",
34+
unsubscribe = "chainHead_unstable_unfollow",
35+
item = FollowEvent<Hash>,
36+
)]
37+
fn chain_head_unstable_follow(&self, runtime_updates: bool);
38+
39+
/// Retrieves the body (list of transactions) of a pinned block.
40+
///
41+
/// This method should be seen as a complement to `chainHead_unstable_follow`,
42+
/// allowing the JSON-RPC client to retrieve more information about a block
43+
/// that has been reported.
44+
///
45+
/// Use `archive_unstable_body` if instead you want to retrieve the body of an arbitrary block.
46+
///
47+
/// # Unstable
48+
///
49+
/// This method is unstable and subject to change in the future.
50+
#[subscription(
51+
name = "chainHead_unstable_body",
52+
unsubscribe = "chainHead_unstable_stopBody",
53+
item = ChainHeadEvent<String>,
54+
)]
55+
fn chain_head_unstable_body(
56+
&self,
57+
follow_subscription: String,
58+
hash: Hash,
59+
network_config: Option<NetworkConfig>,
60+
);
61+
62+
/// Retrieves the header of a pinned block.
63+
///
64+
/// This method should be seen as a complement to `chainHead_unstable_follow`,
65+
/// allowing the JSON-RPC client to retrieve more information about a block
66+
/// that has been reported.
67+
///
68+
/// Use `archive_unstable_header` if instead you want to retrieve the header of an arbitrary
69+
/// block.
70+
///
71+
/// # Unstable
72+
///
73+
/// This method is unstable and subject to change in the future.
74+
#[method(name = "chainHead_unstable_header", blocking)]
75+
fn chain_head_unstable_header(
76+
&self,
77+
follow_subscription: String,
78+
hash: Hash,
79+
) -> RpcResult<Option<String>>;
80+
81+
/// Get the chain's genesis hash.
82+
///
83+
/// # Unstable
84+
///
85+
/// This method is unstable and subject to change in the future.
86+
#[method(name = "chainHead_unstable_genesisHash", blocking)]
87+
fn chain_head_unstable_genesis_hash(&self) -> RpcResult<String>;
88+
89+
/// Return a storage entry at a specific block's state.
90+
///
91+
/// # Unstable
92+
///
93+
/// This method is unstable and subject to change in the future.
94+
#[subscription(
95+
name = "chainHead_unstable_storage",
96+
unsubscribe = "chainHead_unstable_stopStorage",
97+
item = ChainHeadEvent<String>,
98+
)]
99+
fn chain_head_unstable_storage(
100+
&self,
101+
follow_subscription: String,
102+
hash: Hash,
103+
key: String,
104+
child_key: Option<String>,
105+
network_config: Option<NetworkConfig>,
106+
);
107+
108+
/// Call into the Runtime API at a specified block's state.
109+
///
110+
/// # Unstable
111+
///
112+
/// This method is unstable and subject to change in the future.
113+
#[subscription(
114+
name = "chainHead_unstable_call",
115+
unsubscribe = "chainHead_unstable_stopCall",
116+
item = ChainHeadEvent<String>,
117+
)]
118+
fn chain_head_unstable_call(
119+
&self,
120+
follow_subscription: String,
121+
hash: Hash,
122+
function: String,
123+
call_parameters: String,
124+
network_config: Option<NetworkConfig>,
125+
);
126+
127+
/// Unpin a block reported by the `follow` method.
128+
///
129+
/// Ongoing operations that require the provided block
130+
/// will continue normally.
131+
///
132+
/// # Unstable
133+
///
134+
/// This method is unstable and subject to change in the future.
135+
#[method(name = "chainHead_unstable_unpin", blocking)]
136+
fn chain_head_unstable_unpin(&self, follow_subscription: String, hash: Hash) -> RpcResult<()>;
137+
}

0 commit comments

Comments
 (0)