Millau -> Rialto messages relay (#399)

* Millau messages -> Rialto relay

* prepare for custom race strategy of delivery race

* custom strategy for delivery race

* update TODOs

* add reference to issue 457

* impl reconnect

* clippy

* fix check in test

* fmt

* removed obsolete TODO

* fixed another TODOs

* fmt

* use MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE const from primitives

* Update relays/messages-relay/src/message_lane_loop.rs

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>

* added SubstrateMessagesProof typedef

* fix test

* removed comment

* additional_proof_required -> ProofParameters

* typo

* multiline literal

* clippy

* fix typo

* and_then -> await

* update_source_latest_confirmed_nonce

* Update relays/messages-relay/src/message_race_delivery.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
This commit is contained in:
Svyatoslav Nikolsky
2020-11-05 13:12:31 +03:00
committed by Bastian Köcher
parent 804ef55146
commit d4fc7bebdc
27 changed files with 1506 additions and 451 deletions
@@ -16,6 +16,7 @@ rand = "0.7"
# Bridge dependencies
bp-message-lane = { path = "../../primitives/message-lane" }
bp-runtime = { path = "../../primitives/runtime" }
headers-relay = { path = "../headers-relay" }
relay-utils = { path = "../utils" }
@@ -27,6 +28,8 @@ frame-system = "2.0"
pallet-balances = "2.0"
sp-core = "2.0"
sp-runtime = "2.0"
sp-std = "2.0"
sp-trie = "2.0"
sp-version = "2.0"
#[dev-dependencies]
+89 -10
View File
@@ -17,11 +17,13 @@
//! Substrate node client.
use crate::chain::{Chain, ChainWithBalances};
use crate::error::Error;
use crate::rpc::Substrate;
use crate::{ConnectionParams, Result};
use crate::rpc::{Substrate, SubstrateMessageLane};
use crate::{ConnectionParams, Error, Result};
use bp_message_lane::{LaneId, MessageNonce};
use bp_runtime::InstanceId;
use codec::Decode;
use frame_support::weights::Weight;
use frame_system::AccountInfo;
use jsonrpsee::common::DeserializeOwned;
use jsonrpsee::raw::RawClient;
@@ -30,7 +32,9 @@ use jsonrpsee::{client::Subscription, Client as RpcClient};
use num_traits::Zero;
use pallet_balances::AccountData;
use sp_core::Bytes;
use sp_trie::StorageProof;
use sp_version::RuntimeVersion;
use std::ops::RangeInclusive;
const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities";
@@ -42,15 +46,26 @@ pub type OpaqueGrandpaAuthoritiesSet = Vec<u8>;
/// Substrate client type.
///
/// Cloning Client is a cheap operation.
#[derive(Clone)]
/// Cloning `Client` is a cheap operation.
pub struct Client<C: Chain> {
/// Client connection params.
params: ConnectionParams,
/// Substrate RPC client.
client: RpcClient,
/// Genesis block hash.
genesis_hash: C::Hash,
}
impl<C: Chain> Clone for Client<C> {
fn clone(&self) -> Self {
Client {
params: self.params.clone(),
client: self.client.clone(),
genesis_hash: self.genesis_hash,
}
}
}
impl<C: Chain> std::fmt::Debug for Client<C> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct("Client")
@@ -62,15 +77,33 @@ impl<C: Chain> std::fmt::Debug for Client<C> {
impl<C: Chain> Client<C> {
/// Returns client that is able to call RPCs on Substrate node over websocket connection.
pub async fn new(params: ConnectionParams) -> Result<Self> {
let uri = format!("ws://{}:{}", params.host, params.port);
let transport = WsTransportClient::new(&uri).await?;
let raw_client = RawClient::new(transport);
let client: RpcClient = raw_client.into();
let client = Self::build_client(params.clone()).await?;
let number: C::BlockNumber = Zero::zero();
let genesis_hash = Substrate::<C, _, _>::chain_get_block_hash(&client, number).await?;
Ok(Self { client, genesis_hash })
Ok(Self {
params,
client,
genesis_hash,
})
}
/// Reopen client connection.
pub async fn reconnect(self) -> Result<Self> {
Ok(Self {
params: self.params.clone(),
client: Self::build_client(self.params).await?,
genesis_hash: self.genesis_hash,
})
}
/// Build client to use in connection.
async fn build_client(params: ConnectionParams) -> Result<RpcClient> {
let uri = format!("ws://{}:{}", params.host, params.port);
let transport = WsTransportClient::new(&uri).await?;
let raw_client = RawClient::new(transport);
Ok(raw_client.into())
}
}
@@ -80,6 +113,11 @@ impl<C: Chain> Client<C> {
&self.genesis_hash
}
/// Return hash of the best finalized block.
pub async fn best_finalized_header_hash(&self) -> Result<C::Hash> {
Ok(Substrate::<C, _, _>::chain_get_finalized_head(&self.client).await?)
}
/// Returns the best Substrate header.
pub async fn best_header(&self) -> Result<C::Header>
where
@@ -169,6 +207,47 @@ impl<C: Chain> Client<C> {
.map_err(Into::into)
}
/// Returns proof-of-message(s) in given inclusive range.
pub async fn prove_messages(
&self,
instance: InstanceId,
lane: LaneId,
range: RangeInclusive<MessageNonce>,
include_outbound_lane_state: bool,
at_block: C::Hash,
) -> Result<(Weight, StorageProof)> {
let (dispatch_weight, encoded_trie_nodes) = SubstrateMessageLane::<C, _, _>::prove_messages(
&self.client,
instance,
lane,
*range.start(),
*range.end(),
include_outbound_lane_state,
Some(at_block),
)
.await
.map_err(Error::Request)?;
let decoded_trie_nodes: Vec<Vec<u8>> =
Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?;
Ok((dispatch_weight, StorageProof::new(decoded_trie_nodes)))
}
/// Returns proof-of-message(s) delivery.
pub async fn prove_messages_delivery(
&self,
instance: InstanceId,
lane: LaneId,
at_block: C::Hash,
) -> Result<StorageProof> {
let encoded_trie_nodes =
SubstrateMessageLane::<C, _, _>::prove_messages_delivery(&self.client, instance, lane, Some(at_block))
.await
.map_err(Error::Request)?;
let decoded_trie_nodes: Vec<Vec<u8>> =
Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?;
Ok(StorageProof::new(decoded_trie_nodes))
}
/// Return new justifications stream.
pub async fn subscribe_justifications(self) -> Result<JustificationsSubscription> {
Ok(self
@@ -31,6 +31,9 @@ pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthori
pub use crate::error::{Error, Result};
pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf};
/// Header id used by the chain.
pub type HeaderIdOf<C> = relay_utils::HeaderId<HashOf<C>, BlockNumberOf<C>>;
/// Substrate-over-websocket connection params.
#[derive(Debug, Clone)]
pub struct ConnectionParams {
@@ -23,6 +23,9 @@
use crate::chain::Chain;
use bp_message_lane::{LaneId, MessageNonce};
use bp_runtime::InstanceId;
use frame_support::weights::Weight;
use sp_core::{
storage::{StorageData, StorageKey},
Bytes,
@@ -33,6 +36,8 @@ jsonrpsee::rpc_api! {
pub(crate) Substrate<C: Chain> {
#[rpc(method = "chain_getHeader", positional_params)]
fn chain_get_header(block_hash: Option<C::Hash>) -> C::Header;
#[rpc(method = "chain_getFinalizedHead", positional_params)]
fn chain_get_finalized_head() -> C::Hash;
#[rpc(method = "chain_getBlock", positional_params)]
fn chain_get_block(block_hash: Option<C::Hash>) -> C::SignedBlock;
#[rpc(method = "chain_getBlockHash", positional_params)]
@@ -48,4 +53,23 @@ jsonrpsee::rpc_api! {
#[rpc(method = "state_getRuntimeVersion", positional_params)]
fn runtime_version() -> RuntimeVersion;
}
pub(crate) SubstrateMessageLane<C: Chain> {
#[rpc(method = "messageLane_proveMessages", positional_params)]
fn prove_messages(
instance: InstanceId,
lane: LaneId,
begin: MessageNonce,
end: MessageNonce,
include_outbound_lane_state: bool,
block: Option<C::Hash>,
) -> (Weight, Bytes);
#[rpc(method = "messageLane_proveMessagesDelivery", positional_params)]
fn prove_messages_delivery(
instance: InstanceId,
lane: LaneId,
block: Option<C::Hash>,
) -> Bytes;
}
}