From 358ee465ce3bc95f177d065861c1841893fff24d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 28 Oct 2020 21:35:29 +0300 Subject: [PATCH] Return cumulative dispatch weight of messages from the `messageLane_proveMessages` (#469) * implement OutboundLaneApi and InboundLaneApi for Millau /Rialto runtimes * fixed typo --- bridges/bin/millau/node/src/service.rs | 1 + bridges/bin/millau/runtime/src/lib.rs | 31 +++++++++++++++ bridges/bin/rialto/node/src/service.rs | 1 + bridges/bin/rialto/runtime/src/lib.rs | 31 +++++++++++++++ bridges/modules/message-lane/rpc/Cargo.toml | 2 + bridges/modules/message-lane/rpc/src/lib.rs | 42 ++++++++++++++++----- bridges/modules/message-lane/src/lib.rs | 29 +++++++++++++- bridges/primitives/message-lane/src/lib.rs | 4 +- 8 files changed, 129 insertions(+), 12 deletions(-) diff --git a/bridges/bin/millau/node/src/service.rs b/bridges/bin/millau/node/src/service.rs index 3e3917d7bd8dd..0a6b5d8b849e6 100644 --- a/bridges/bin/millau/node/src/service.rs +++ b/bridges/bin/millau/node/src/service.rs @@ -222,6 +222,7 @@ pub fn new_full(config: Configuration) -> Result { finality_proof_provider.clone(), ))); io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( + client.clone(), backend.clone(), Arc::new(MillauMessageLaneKeys), ))); diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 22df99bbb3711..1e5a8feddeaf0 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -31,6 +31,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto; pub mod rialto_messages; +use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -538,4 +539,34 @@ impl_runtime_apis! { BridgeRialto::is_finalized_header(hash) } } + + // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) + impl bp_message_lane::OutboundLaneApi for Runtime { + fn messages_dispatch_weight(lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, end: bp_message_lane::MessageNonce) -> Weight { + (begin..=end) + .filter_map(|nonce| BridgeRialtoMessageLane::outbound_message_payload(lane, nonce)) + .filter_map(|encoded_payload| rialto_messages::ToRialtoMessagePayload::decode(&mut &encoded_payload[..]).ok()) + .map(|decoded_payload| decoded_payload.weight) + .fold(0, |sum, weight| sum.saturating_add(weight)) + } + + fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeRialtoMessageLane::outbound_latest_received_nonce(lane) + } + + fn latest_generated_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeRialtoMessageLane::outbound_latest_generated_nonce(lane) + } + } + + // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) + impl bp_message_lane::InboundLaneApi for Runtime { + fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeRialtoMessageLane::inbound_latest_received_nonce(lane) + } + + fn latest_confirmed_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeRialtoMessageLane::inbound_latest_confirmed_nonce(lane) + } + } } diff --git a/bridges/bin/rialto/node/src/service.rs b/bridges/bin/rialto/node/src/service.rs index 21b2bf0bce7d5..07a49a26858ac 100644 --- a/bridges/bin/rialto/node/src/service.rs +++ b/bridges/bin/rialto/node/src/service.rs @@ -206,6 +206,7 @@ pub fn new_full(config: Configuration) -> Result { DenyUnsafe::No, ))); io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( + client.clone(), backend.clone(), Arc::new(RialtoMessageLaneKeys), ))); diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index 778b2afd18e95..1ab9984bec722 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -37,6 +37,7 @@ pub mod millau; pub mod millau_messages; pub mod rialto_poa; +use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -702,6 +703,36 @@ impl_runtime_apis! { } } + // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) + impl bp_message_lane::OutboundLaneApi for Runtime { + fn messages_dispatch_weight(lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, end: bp_message_lane::MessageNonce) -> Weight { + (begin..=end) + .filter_map(|nonce| BridgeMillauMessageLane::outbound_message_payload(lane, nonce)) + .filter_map(|encoded_payload| millau_messages::ToMillauMessagePayload::decode(&mut &encoded_payload[..]).ok()) + .map(|decoded_payload| decoded_payload.weight) + .fold(0, |sum, weight| sum.saturating_add(weight)) + } + + fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeMillauMessageLane::outbound_latest_received_nonce(lane) + } + + fn latest_generated_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeMillauMessageLane::outbound_latest_generated_nonce(lane) + } + } + + // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) + impl bp_message_lane::InboundLaneApi for Runtime { + fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeMillauMessageLane::inbound_latest_received_nonce(lane) + } + + fn latest_confirmed_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeMillauMessageLane::inbound_latest_confirmed_nonce(lane) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn dispatch_benchmark( diff --git a/bridges/modules/message-lane/rpc/Cargo.toml b/bridges/modules/message-lane/rpc/Cargo.toml index e9ef6c1cc6b2a..cc179f5d366c7 100644 --- a/bridges/modules/message-lane/rpc/Cargo.toml +++ b/bridges/modules/message-lane/rpc/Cargo.toml @@ -20,7 +20,9 @@ bp-message-lane = { path = "../../../primitives/message-lane" } # Substrate Dependencies +frame-support = "2.0" sc-client-api = "2.0" +sp-api = "2.0" sp-blockchain = "2.0" sp-core = "2.0" sp-runtime = "2.0" diff --git a/bridges/modules/message-lane/rpc/src/lib.rs b/bridges/modules/message-lane/rpc/src/lib.rs index 61a82eae7f2c6..bcc786f3866fc 100644 --- a/bridges/modules/message-lane/rpc/src/lib.rs +++ b/bridges/modules/message-lane/rpc/src/lib.rs @@ -18,12 +18,14 @@ use crate::error::{Error, FutureResult}; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_message_lane::{LaneId, MessageNonce, OutboundLaneApi}; use bp_runtime::InstanceId; +use frame_support::weights::Weight; use futures::{FutureExt, TryFutureExt}; use jsonrpc_core::futures::Future as _; use jsonrpc_derive::rpc; use sc_client_api::Backend as BackendT; +use sp_api::ProvideRuntimeApi; use sp_blockchain::{Error as BlockchainError, HeaderBackend}; use sp_core::{storage::StorageKey, Bytes}; use sp_runtime::{codec::Encode, generic::BlockId, traits::Block as BlockT}; @@ -54,7 +56,8 @@ pub trait Runtime: Send + Sync + 'static { /// Provides RPC methods for interacting with message-lane pallet. #[rpc] pub trait MessageLaneApi { - /// Returns proof-of-message(s) in given inclusive range. + /// Returns cumulative dispatch weight of messages in given inclusive range and their storage proof. + /// The state of outbound lane is included in the proof if `include_outbound_lane_state` is true. #[rpc(name = "messageLane_proveMessages")] fn prove_messages( &self, @@ -64,7 +67,7 @@ pub trait MessageLaneApi { end: MessageNonce, include_outbound_lane_state: bool, block: Option, - ) -> FutureResult; + ) -> FutureResult<(Weight, MessagesProof)>; /// Returns proof-of-message(s) delivery. #[rpc(name = "messageLane_proveMessagesDelivery")] @@ -77,16 +80,18 @@ pub trait MessageLaneApi { } /// Implements the MessageLaneApi trait for interacting with message lanes. -pub struct MessageLaneRpcHandler { +pub struct MessageLaneRpcHandler { + client: Arc, backend: Arc, runtime: Arc, _phantom: std::marker::PhantomData, } -impl MessageLaneRpcHandler { +impl MessageLaneRpcHandler { /// Creates new mesage lane RPC handler. - pub fn new(backend: Arc, runtime: Arc) -> Self { + pub fn new(client: Arc, backend: Arc, runtime: Arc) -> Self { Self { + client, backend, runtime, _phantom: Default::default(), @@ -94,9 +99,11 @@ impl MessageLaneRpcHandler { } } -impl MessageLaneApi for MessageLaneRpcHandler +impl MessageLaneApi for MessageLaneRpcHandler where Block: BlockT, + Client: ProvideRuntimeApi + Send + Sync + 'static, + Client::Api: OutboundLaneApi, Backend: BackendT + 'static, R: Runtime, { @@ -108,7 +115,22 @@ where end: MessageNonce, include_outbound_lane_state: bool, block: Option, - ) -> FutureResult { + ) -> FutureResult<(Weight, MessagesProof)> { + let block = unwrap_or_best(&*self.backend, block); + + let messages_dispatch_weight_result = + self.client + .runtime_api() + .messages_dispatch_weight(&BlockId::Hash(block), lane, begin, end); + let messages_dispatch_weight = match messages_dispatch_weight_result { + Ok(messages_dispatch_weight) => messages_dispatch_weight, + Err(error) => { + return Box::new(jsonrpc_core::futures::future::err( + blockchain_err(BlockchainError::Execution(Box::new(format!("{:?}", error)))).into(), + )) + } + }; + let runtime = self.runtime.clone(); let outbound_lane_data_key = if include_outbound_lane_state { Some(runtime.inbound_lane_data_key(&instance, &lane)) @@ -118,14 +140,14 @@ where Box::new( prove_keys_read( self.backend.clone(), - block, + Some(block), (begin..=end) .map(move |nonce| runtime.message_key(&instance, &lane, nonce)) .chain(outbound_lane_data_key.into_iter()), ) .boxed() .compat() - .map(serialize_storage_proof) + .map(move |proof| (messages_dispatch_weight, serialize_storage_proof(proof))) .map_err(Into::into), ) } diff --git a/bridges/modules/message-lane/src/lib.rs b/bridges/modules/message-lane/src/lib.rs index 696340c6ff50b..169270efe0b21 100644 --- a/bridges/modules/message-lane/src/lib.rs +++ b/bridges/modules/message-lane/src/lib.rs @@ -35,7 +35,7 @@ use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OutboundLaneData, + InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; use codec::{Decode, Encode}; use frame_support::{ @@ -374,6 +374,33 @@ decl_module! { } } +impl, I: Instance> Module { + /// Get payload of given outbound message. + pub fn outbound_message_payload(lane: LaneId, nonce: MessageNonce) -> Option { + OutboundMessages::::get(MessageKey { lane_id: lane, nonce }).map(|message_data| message_data.payload) + } + + /// Get nonce of latest generated message at given outbound lane. + pub fn outbound_latest_generated_nonce(lane: LaneId) -> MessageNonce { + OutboundLanes::::get(&lane).latest_generated_nonce + } + + /// Get nonce of latest confirmed message at given outbound lane. + pub fn outbound_latest_received_nonce(lane: LaneId) -> MessageNonce { + OutboundLanes::::get(&lane).latest_received_nonce + } + + /// Get nonce of latest received message at given inbound lane. + pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { + InboundLanes::::get(&lane).latest_received_nonce + } + + /// Get nonce of latest confirmed message at given inbound lane. + pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { + InboundLanes::::get(&lane).latest_confirmed_nonce + } +} + /// Creates new inbound lane object, backed by runtime storage. fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { InboundLane::new(RuntimeInboundLaneStorage { diff --git a/bridges/primitives/message-lane/src/lib.rs b/bridges/primitives/message-lane/src/lib.rs index 672ba719b97de..e7ae16135b6ed 100644 --- a/bridges/primitives/message-lane/src/lib.rs +++ b/bridges/primitives/message-lane/src/lib.rs @@ -23,7 +23,7 @@ #![allow(clippy::unnecessary_mut_passed)] use codec::{Decode, Encode}; -use frame_support::RuntimeDebug; +use frame_support::{weights::Weight, RuntimeDebug}; use sp_api::decl_runtime_apis; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; @@ -126,6 +126,8 @@ impl Default for OutboundLaneData { decl_runtime_apis! { /// Outbound message lane API. pub trait OutboundLaneApi { + /// Returns dispatch weight of all messages in given inclusive range. + fn messages_dispatch_weight(lane: LaneId, begin: MessageNonce, end: MessageNonce) -> Weight; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane.