Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Introduce rpc client for relay chain full node #963

Merged
merged 72 commits into from
Mar 1, 2022
Merged
Changes from 56 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
3d7d222
Initial network interface preparations
skunert Dec 21, 2021
b23547c
Implement get_storage_by_key
skunert Jan 4, 2022
cfaa211
Implement `validators` and `session_index_for_child`
skunert Jan 6, 2022
af362b4
Implement persisted_validation_data and candidate_pending_availability
skunert Jan 7, 2022
a8d80d5
Fix method name for persisted_validation_data and add encoded params
skunert Jan 7, 2022
482ecd4
Implement `retrieve_dmq_contents` and `retrieve_all_inbound_hrmp_chan…
skunert Jan 10, 2022
c03ba54
Implement `prove_read`
skunert Jan 10, 2022
b4ca285
Introduce separate RPC client, expose JsonRpSee errors
skunert Jan 10, 2022
f0d6c18
Simplify closure in call_remote_runtime_function
skunert Jan 10, 2022
d4dada5
Implement import stream, upgrade JsonRpSee
skunert Jan 12, 2022
dc5de78
Implement finality stream
skunert Jan 12, 2022
2675a7d
Remove unused method from interface
skunert Jan 12, 2022
f9a228d
Implement `is_major_syncing`
skunert Jan 12, 2022
7a89c73
Implement `wait_on_block`
skunert Jan 13, 2022
b92f204
Merge branch 'master' into network-interface-master
skunert Jan 13, 2022
532ba1d
Fix tests
skunert Jan 13, 2022
d49e25b
Unify error handling `ApiError`
skunert Jan 13, 2022
051068f
Replace WaitError with RelayChainError
skunert Jan 13, 2022
4b664a7
Wrap BlockChainError in RelayChainError
skunert Jan 13, 2022
40432e8
Unify error handling in relay chain intefaces
skunert Jan 17, 2022
5e03777
Fix return type of proof method
skunert Jan 17, 2022
d916d69
Improve error handling of new methods
skunert Jan 17, 2022
ee60f31
Improve error handling and move logging outside of interface
skunert Jan 18, 2022
0a1dd44
Clean up
skunert Jan 18, 2022
68fa074
Remove unwanted changes, clean up
skunert Jan 18, 2022
2764ea2
Remove unused import
skunert Jan 18, 2022
3be8d65
Add format for StatemachineError and remove nused From trait
skunert Jan 19, 2022
4c9b8ea
Use 'thiserror' crate to simplify error handling
skunert Jan 24, 2022
f2caf4b
Expose error for overseer, further simplify error handling
skunert Jan 24, 2022
7c95a65
Merge branch 'master' into relay-chain-interface-error-handling
skunert Jan 24, 2022
af4c50c
Reintroduce network interface
skunert Jan 19, 2022
f0212f9
Implement cli option
skunert Jan 20, 2022
c4fd3ae
Adjust call_state method to use hashes
skunert Jan 24, 2022
3a5e69b
Merge branch 'master' into skunert-network-interface
skunert Jan 28, 2022
2bf24bb
Disable PoV recovery when RPC is used
skunert Jan 28, 2022
3a4766b
Add integration test for network full node
skunert Feb 1, 2022
156f453
Use Hash instead of BlockId to ensure compatibility with RPC interface
skunert Feb 1, 2022
b2f5163
Fix cargo check warnings
skunert Feb 1, 2022
bf9293e
Implement retries
skunert Feb 3, 2022
cc8862f
Remove `expect` statements from code
skunert Feb 3, 2022
99535a0
Update jsonrpsee to 0.8.0 and make collator keys optional
skunert Feb 4, 2022
fcbd51e
Make cli arguments conflicting
skunert Feb 4, 2022
31e2ebf
Remove unused `block_status` method
skunert Feb 4, 2022
277a584
Add clippy fixes
skunert Feb 4, 2022
7af8820
Merge branch 'master' into skunert-network-interface
skunert Feb 7, 2022
8bd395d
Cargo fmt
skunert Feb 7, 2022
389777f
Validate relay chain rpc url
skunert Feb 7, 2022
53324c5
Clean up dependencies and add one more integration test
skunert Feb 7, 2022
470ce99
Clean up
skunert Feb 7, 2022
e39bc18
Clean up dependencies of relay-chain-network
skunert Feb 7, 2022
8bd74d5
Use hash instead of blockid for rpc methods
skunert Feb 7, 2022
a968c70
Fix tests
skunert Feb 7, 2022
332013b
Update client/cli/src/lib.rs
skunert Feb 8, 2022
f61cd81
Improve error message of cli validation
skunert Feb 8, 2022
ce0bd74
Add rpc client constructor
skunert Feb 8, 2022
2140165
Do not use debug formatting for errors
skunert Feb 9, 2022
2862b22
Merge branch 'master' into skunert-network-interface
skunert Feb 9, 2022
6c88d44
Improve logging for remote runtime methods
skunert Feb 17, 2022
1dc0e01
Merge branch 'master' into skunert-network-interface
skunert Feb 17, 2022
874dfb7
Only retry on transport problems
skunert Feb 21, 2022
28df792
Use PHash by value, rename test
skunert Feb 21, 2022
b6236a1
Improve tracing, return error on relay-chain-interface build
skunert Feb 21, 2022
c763d46
Fix naming, use generics instead of deserializing manually
skunert Feb 21, 2022
c502ae8
Rename RelayChainLocal and RelayChainNetwork
skunert Feb 21, 2022
43eb056
lock
skunert Feb 21, 2022
f15097c
Merge branch 'master' into skunert-network-interface
skunert Feb 21, 2022
ac455e9
Format
skunert Feb 21, 2022
69e5a38
Use impl trait for encodable runtime payload
skunert Feb 28, 2022
8d851cf
Only instantiate full node in tests when we need it
skunert Feb 28, 2022
f6965a2
Merge branch 'master' into skunert-network-interface
skunert Feb 28, 2022
f9aa4f0
Upgrade scale-codec to 3.0.0
skunert Mar 1, 2022
3587259
Improve expect log
skunert Mar 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
298 changes: 274 additions & 24 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ members = [
"client/service",
"client/relay-chain-interface",
"client/relay-chain-local",
"client/relay-chain-network",
"pallets/aura-ext",
"pallets/collator-selection",
"pallets/dmp-queue",
1 change: 1 addition & 0 deletions client/cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -10,3 +10,4 @@ clap = { version = "3.0", features = ["derive"] }
# Substrate dependencies
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
url = "2.2.2"
37 changes: 36 additions & 1 deletion client/cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@
#![warn(missing_docs)]

use clap::Parser;
use sc_cli;
use sc_service::{
config::{PrometheusConfig, TelemetryEndpoints},
BasePath, TransactionPoolOptions,
@@ -29,6 +28,7 @@ use std::{
io::{self, Write},
net::SocketAddr,
};
use url::Url;

/// The `purge-chain` command used to remove the whole chain: the parachain and the relay chain.
#[derive(Debug, Parser)]
@@ -119,6 +119,19 @@ impl sc_cli::CliConfiguration for PurgeChainCmd {
}
}

fn validate_relay_chain_url(arg: &str) -> Result<(), String> {
let url = Url::parse(arg).map_err(|e| e.to_string())?;

if url.scheme() == "ws" {
Ok(())
} else {
Err(format!(
"'{}' URL scheme not supported. Only websocket RPC is currently supported",
url.scheme()
))
}
}

/// The `run` command used to run a node.
#[derive(Debug, Parser)]
pub struct RunCmd {
@@ -131,6 +144,23 @@ pub struct RunCmd {
/// Note that this is the same as running with `--validator`.
#[clap(long, conflicts_with = "validator")]
pub collator: bool,

/// EXPERIMENTAL: Specify an URL to a relay chain full node to communicate with.
#[clap(
long,
parse(try_from_str),
validator = validate_relay_chain_url,
conflicts_with = "collator",
conflicts_with = "validator"
)]
pub relay_chain_rpc_url: Option<Url>,
}

/// Options only relevant for collator nodes
#[derive(Clone, Debug)]
pub struct CollatorOptions {
/// Location of relay chain full node
pub relay_chain_rpc_url: Option<Url>,
}

/// A non-redundant version of the `RunCmd` that sets the `validator` field when the
@@ -150,6 +180,11 @@ impl RunCmd {

NormalizedRunCmd { base: new_base }
}

/// Create [`CollatorOptions`] representing options only relevant to parachain collator nodes
pub fn collator_options(&self) -> CollatorOptions {
CollatorOptions { relay_chain_rpc_url: self.relay_chain_rpc_url.clone() }
}
}

impl sc_cli::CliConfiguration for NormalizedRunCmd {
22 changes: 5 additions & 17 deletions client/consensus/common/src/parachain_consensus.rs
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ use sp_runtime::{
traits::{Block as BlockT, Header as HeaderT},
};

use polkadot_primitives::v1::{Block as PBlock, Id as ParaId, OccupiedCoreAssumption};
use polkadot_primitives::v1::{Hash as PHash, Id as ParaId, OccupiedCoreAssumption};

use codec::Decode;
use futures::{select, FutureExt, Stream, StreamExt};
@@ -54,7 +54,7 @@ pub trait RelaychainClient: Clone + 'static {
/// Returns the parachain head for the given `para_id` at the given block id.
async fn parachain_head_at(
&self,
at: &BlockId<PBlock>,
at: &PHash,
para_id: ParaId,
) -> RelayChainResult<Option<Vec<u8>>>;
}
@@ -402,13 +402,7 @@ where
.await?
.filter_map(move |n| {
let relay_chain = relay_chain.clone();
async move {
relay_chain
.parachain_head_at(&BlockId::hash(n.hash()), para_id)
.await
.ok()
.flatten()
}
async move { relay_chain.parachain_head_at(&n.hash(), para_id).await.ok().flatten() }
})
.boxed();
Ok(new_best_notification_stream)
@@ -422,21 +416,15 @@ where
.await?
.filter_map(move |n| {
let relay_chain = relay_chain.clone();
async move {
relay_chain
.parachain_head_at(&BlockId::hash(n.hash()), para_id)
.await
.ok()
.flatten()
}
async move { relay_chain.parachain_head_at(&n.hash(), para_id).await.ok().flatten() }
})
.boxed();
Ok(finality_notification_stream)
}

async fn parachain_head_at(
&self,
at: &BlockId<PBlock>,
at: &PHash,
para_id: ParaId,
) -> RelayChainResult<Option<Vec<u8>>> {
self.persisted_validation_data(at, para_id, OccupiedCoreAssumption::TimedOut)
8 changes: 2 additions & 6 deletions client/consensus/common/src/tests.rs
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ use cumulus_test_client::{
};
use futures::{channel::mpsc, executor::block_on, select, FutureExt, Stream, StreamExt};
use futures_timer::Delay;
use polkadot_primitives::v1::{Block as PBlock, Id as ParaId};
use polkadot_primitives::v1::Id as ParaId;
use sc_client_api::UsageProvider;
use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy};
use sp_blockchain::Error as ClientError;
@@ -98,11 +98,7 @@ impl crate::parachain_consensus::RelaychainClient for Relaychain {
Ok(Box::new(stream.map(|v| v.encode())))
}

async fn parachain_head_at(
&self,
_: &BlockId<PBlock>,
_: ParaId,
) -> RelayChainResult<Option<Vec<u8>>> {
async fn parachain_head_at(&self, _: &PHash, _: ParaId) -> RelayChainResult<Option<Vec<u8>>> {
unimplemented!("Not required for tests")
}
}
2 changes: 2 additions & 0 deletions client/network/Cargo.toml
Original file line number Diff line number Diff line change
@@ -33,6 +33,8 @@ async-trait = "0.1.52"

[dev-dependencies]
tokio = { version = "1.10", features = ["macros"] }
portpicker = "0.1.1"
url = "2.2.2"

# Cumulus deps
cumulus-test-service = { path = "../../test/service" }
39 changes: 15 additions & 24 deletions client/network/src/lib.rs
Original file line number Diff line number Diff line change
@@ -24,17 +24,14 @@ use sp_consensus::block_validation::{
BlockAnnounceValidator as BlockAnnounceValidatorT, Validation,
};
use sp_core::traits::SpawnNamed;
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header as HeaderT},
};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};

use cumulus_relay_chain_interface::RelayChainInterface;
use polkadot_node_primitives::{CollationSecondedSignal, Statement};
use polkadot_parachain::primitives::HeadData;
use polkadot_primitives::v1::{
Block as PBlock, CandidateReceipt, CompactStatement, Hash as PHash, Id as ParaId,
OccupiedCoreAssumption, SigningContext, UncheckedSigned,
CandidateReceipt, CompactStatement, Hash as PHash, Id as ParaId, OccupiedCoreAssumption,
SigningContext, UncheckedSigned,
};

use codec::{Decode, DecodeAll, Encode};
@@ -133,17 +130,16 @@ impl BlockAnnounceData {
{
let validator_index = self.statement.unchecked_validator_index();

let runtime_api_block_id = BlockId::Hash(self.relay_parent);
let session_index =
match relay_chain_client.session_index_for_child(&runtime_api_block_id).await {
match relay_chain_client.session_index_for_child(&self.relay_parent).await {
Ok(r) => r,
Err(e) => return Err(BlockAnnounceError(format!("{:?}", e))),
};

let signing_context = SigningContext { parent_hash: self.relay_parent, session_index };

// Check that the signer is a legit validator.
let authorities = match relay_chain_client.validators(&runtime_api_block_id).await {
let authorities = match relay_chain_client.validators(&self.relay_parent).await {
Ok(r) => r,
Err(e) => return Err(BlockAnnounceError(format!("{:?}", e))),
};
@@ -160,7 +156,7 @@ impl BlockAnnounceData {
};

// Check statement is correctly signed.
if self.statement.try_into_checked(&signing_context, &signer).is_err() {
if self.statement.try_into_checked(&signing_context, signer).is_err() {
tracing::debug!(
target: LOG_TARGET,
"Block announcement justification signature is invalid.",
@@ -231,11 +227,7 @@ where
{
/// Create a new [`BlockAnnounceValidator`].
pub fn new(relay_chain_interface: RCInterface, para_id: ParaId) -> Self {
Self {
phantom: Default::default(),
relay_chain_interface: relay_chain_interface.clone(),
para_id,
}
Self { phantom: Default::default(), relay_chain_interface, para_id }
}
}

@@ -246,11 +238,11 @@ where
/// Get the included block of the given parachain in the relay chain.
async fn included_block(
relay_chain_interface: &RCInterface,
block_id: &BlockId<PBlock>,
hash: &PHash,
para_id: ParaId,
) -> Result<Block::Header, BoxedError> {
let validation_data = relay_chain_interface
.persisted_validation_data(block_id, para_id, OccupiedCoreAssumption::TimedOut)
.persisted_validation_data(hash, para_id, OccupiedCoreAssumption::TimedOut)
.await
.map_err(|e| Box::new(BlockAnnounceError(format!("{:?}", e))) as Box<_>)?
.ok_or_else(|| {
@@ -269,11 +261,11 @@ where
/// Get the backed block hash of the given parachain in the relay chain.
async fn backed_block_hash(
relay_chain_interface: &RCInterface,
block_id: &BlockId<PBlock>,
hash: &PHash,
para_id: ParaId,
) -> Result<Option<PHash>, BoxedError> {
let candidate_receipt = relay_chain_interface
.candidate_pending_availability(block_id, para_id)
.candidate_pending_availability(hash, para_id)
.await
.map_err(|e| Box::new(BlockAnnounceError(format!("{:?}", e))) as Box<_>)?;

@@ -293,14 +285,13 @@ where
.best_block_hash()
.await
.map_err(|e| Box::new(e) as Box<_>)?;
let runtime_api_block_id = BlockId::Hash(relay_chain_best_hash);
let block_number = header.number();

let best_head =
Self::included_block(&relay_chain_interface, &runtime_api_block_id, para_id).await?;
Self::included_block(&relay_chain_interface, &relay_chain_best_hash, para_id).await?;
let known_best_number = best_head.number();
let backed_block = || async {
Self::backed_block_hash(&relay_chain_interface, &runtime_api_block_id, para_id).await
Self::backed_block_hash(&relay_chain_interface, &relay_chain_best_hash, para_id).await
};

if best_head == header {
@@ -335,7 +326,7 @@ where
data: &[u8],
) -> Pin<Box<dyn Future<Output = Result<Validation, BoxedError>> + Send>> {
let relay_chain_interface = self.relay_chain_interface.clone();
let mut data = data.to_vec();
let data = data.to_vec();
let header = header.clone();
let header_encoded = header.encode();
let block_announce_validator = self.clone();
@@ -357,7 +348,7 @@ where
return block_announce_validator.handle_empty_block_announce_data(header).await
}

let block_announce_data = match BlockAnnounceData::decode_all(&mut data) {
let block_announce_data = match BlockAnnounceData::decode_all(&data) {
Ok(r) => r,
Err(err) =>
return Err(Box::new(BlockAnnounceError(format!(
38 changes: 8 additions & 30 deletions client/network/src/tests.rs
Original file line number Diff line number Diff line change
@@ -77,23 +77,10 @@ impl DummyRelayChainInterface {

#[async_trait]
impl RelayChainInterface for DummyRelayChainInterface {
async fn validators(
&self,
_: &cumulus_primitives_core::relay_chain::BlockId,
) -> RelayChainResult<Vec<ValidatorId>> {
async fn validators(&self, _: &PHash) -> RelayChainResult<Vec<ValidatorId>> {
Ok(self.data.lock().validators.clone())
}

async fn block_status(
&self,
block_id: cumulus_primitives_core::relay_chain::BlockId,
) -> RelayChainResult<sp_blockchain::BlockStatus> {
self.relay_backend
.blockchain()
.status(block_id)
.map_err(RelayChainError::BlockchainError)
}

async fn best_block_hash(&self) -> RelayChainResult<PHash> {
Ok(self.relay_backend.blockchain().info().best_hash)
}
@@ -116,7 +103,7 @@ impl RelayChainInterface for DummyRelayChainInterface {

async fn persisted_validation_data(
&self,
_: &cumulus_primitives_core::relay_chain::BlockId,
_: &PHash,
_: ParaId,
_: OccupiedCoreAssumption,
) -> RelayChainResult<Option<PersistedValidationData>> {
@@ -128,7 +115,7 @@ impl RelayChainInterface for DummyRelayChainInterface {

async fn candidate_pending_availability(
&self,
_: &cumulus_primitives_core::relay_chain::BlockId,
_: &PHash,
_: ParaId,
) -> RelayChainResult<Option<CommittedCandidateReceipt>> {
if self.data.lock().has_pending_availability {
@@ -159,10 +146,7 @@ impl RelayChainInterface for DummyRelayChainInterface {
}
}

async fn session_index_for_child(
&self,
_: &cumulus_primitives_core::relay_chain::BlockId,
) -> RelayChainResult<SessionIndex> {
async fn session_index_for_child(&self, _: &PHash) -> RelayChainResult<SessionIndex> {
Ok(0)
}

@@ -196,15 +180,15 @@ impl RelayChainInterface for DummyRelayChainInterface {

async fn get_storage_by_key(
&self,
_: &polkadot_service::BlockId,
_: &PHash,
_: &[u8],
) -> RelayChainResult<Option<StorageValue>> {
unimplemented!("Not needed for test")
}

async fn prove_read(
&self,
_: &polkadot_service::BlockId,
_: &PHash,
_: &Vec<Vec<u8>>,
) -> RelayChainResult<sc_client_api::StorageProof> {
unimplemented!("Not needed for test")
@@ -293,10 +277,7 @@ async fn make_gossip_message_and_header(
Some(&Sr25519Keyring::Alice.to_seed()),
)
.unwrap();
let session_index = relay_chain_interface
.session_index_for_child(&BlockId::Hash(relay_parent))
.await
.unwrap();
let session_index = relay_chain_interface.session_index_for_child(&relay_parent).await.unwrap();
let signing_context = SigningContext { parent_hash: relay_parent, session_index };

let header = default_header();
@@ -477,10 +458,7 @@ async fn check_statement_seconded() {
Some(&Sr25519Keyring::Alice.to_seed()),
)
.unwrap();
let session_index = relay_chain_interface
.session_index_for_child(&BlockId::Hash(relay_parent))
.await
.unwrap();
let session_index = relay_chain_interface.session_index_for_child(&relay_parent).await.unwrap();
let signing_context = SigningContext { parent_hash: relay_parent, session_index };

let statement = Statement::Valid(Default::default());
Loading