Newer
Older
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Bridges Common is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
//! Message delivery loop. Designed to work with messages pallet.
//!
//! Single relay instance delivers messages of single lane in single direction.
//! To serve two-way lane, you would need two instances of relay.
//! To serve N two-way lanes, you would need N*2 instances of relay.
//!
//! Please keep in mind that the best header in this file is actually best
//! finalized header. I.e. when talking about headers in lane context, we
//! only care about finalized headers.
use std::{collections::BTreeMap, fmt::Debug, future::Future, ops::RangeInclusive, time::Duration};
use async_trait::async_trait;
use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt};
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight};
Svyatoslav Nikolsky
committed
use bp_runtime::messages::DispatchFeePayment;
interval, metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient,
retry_backoff, FailedClient, TransactionTracker,
use crate::{
message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf},
message_race_delivery::run as run_message_delivery_race,
message_race_receiving::run as run_message_receiving_race,
metrics::MessageLaneLoopMetrics,
relay_strategy::RelayStrategy,
};
/// Message lane loop configuration params.
#[derive(Debug, Clone)]
/// Id of lane this loop is servicing.
pub lane: LaneId,
/// Interval at which we ask target node about its updates.
pub source_tick: Duration,
/// Interval at which we ask target node about its updates.
pub target_tick: Duration,
/// Delay between moments when connection error happens and our reconnect attempt.
pub reconnect_delay: Duration,
/// Message delivery race parameters.
pub delivery_params: MessageDeliveryParams<Strategy>,
Svyatoslav Nikolsky
committed
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelayerMode {
/// The relayer doesn't care about rewards.
Altruistic,
/// The relayer will deliver all messages and confirmations as long as he's not losing any
/// funds.
Svyatoslav Nikolsky
committed
Rational,
/// Message delivery race parameters.
#[derive(Debug, Clone)]
pub struct MessageDeliveryParams<Strategy: RelayStrategy> {
/// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number
/// of entries in the `InboundLaneData::relayers` set, all new messages will be rejected until
/// reward payment will be proved (by including outbound lane state to the message delivery
/// transaction).
pub max_unrewarded_relayer_entries_at_target: MessageNonce,
/// Message delivery race will stop delivering messages if there are
/// `max_unconfirmed_nonces_at_target` unconfirmed nonces on the target node. The race would
/// continue once they're confirmed by the receiving race.
pub max_unconfirmed_nonces_at_target: MessageNonce,
/// Maximal number of relayed messages in single delivery transaction.
pub max_messages_in_single_batch: MessageNonce,
/// Maximal cumulative dispatch weight of relayed messages in single delivery transaction.
pub max_messages_weight_in_single_batch: Weight,
/// Maximal cumulative size of relayed messages in single delivery transaction.
pub max_messages_size_in_single_batch: u32,
/// Relay strategy
pub relay_strategy: Strategy,
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MessageDetails<SourceChainBalance> {
/// Message dispatch weight.
pub dispatch_weight: Weight,
/// Message size (number of bytes in encoded payload).
pub size: u32,
/// The relayer reward paid in the source chain tokens.
pub reward: SourceChainBalance,
Svyatoslav Nikolsky
committed
/// Where the fee for dispatching message is paid?
pub dispatch_fee_payment: DispatchFeePayment,
pub type MessageDetailsMap<SourceChainBalance> =
BTreeMap<MessageNonce, MessageDetails<SourceChainBalance>>;
/// Message delivery race proof parameters.
Svyatoslav Nikolsky
committed
#[derive(Debug, PartialEq, Eq)]
pub struct MessageProofParameters {
/// Include outbound lane state proof?
pub outbound_state_proof_required: bool,
/// Cumulative dispatch weight of messages that we're building proof for.
pub dispatch_weight: Weight,
/// Artifacts of submitting nonces proof.
pub struct NoncesSubmitArtifacts<T> {
/// Submitted nonces range.
pub nonces: RangeInclusive<MessageNonce>,
/// Submitted transaction tracker.
pub tx_tracker: T,
}
pub trait SourceClient<P: MessageLane>: RelayClient {
/// Transaction tracker to track submitted transactions.
type TransactionTracker: TransactionTracker<HeaderId = SourceHeaderIdOf<P>>;
/// Returns state of the client.
async fn state(&self) -> Result<SourceClientState<P>, Self::Error>;
/// Get nonce of instance of latest generated message.
async fn latest_generated_nonce(
&self,
id: SourceHeaderIdOf<P>,
) -> Result<(SourceHeaderIdOf<P>, MessageNonce), Self::Error>;
/// Get nonce of the latest message, which receiving has been confirmed by the target chain.
async fn latest_confirmed_received_nonce(
&self,
id: SourceHeaderIdOf<P>,
) -> Result<(SourceHeaderIdOf<P>, MessageNonce), Self::Error>;
/// Returns mapping of message nonces, generated on this client, to their weights.
/// Some messages may be missing from returned map, if corresponding messages were pruned at
/// the source chain.
async fn generated_message_details(
&self,
id: SourceHeaderIdOf<P>,
nonces: RangeInclusive<MessageNonce>,
) -> Result<MessageDetailsMap<P::SourceChainBalance>, Self::Error>;
/// Prove messages in inclusive range [begin; end].
async fn prove_messages(
&self,
id: SourceHeaderIdOf<P>,
nonces: RangeInclusive<MessageNonce>,
proof_parameters: MessageProofParameters,
) -> Result<(SourceHeaderIdOf<P>, RangeInclusive<MessageNonce>, P::MessagesProof), Self::Error>;
/// Submit messages receiving proof.
async fn submit_messages_receiving_proof(
&self,
generated_at_block: TargetHeaderIdOf<P>,
proof: P::MessagesReceivingProof,
) -> Result<Self::TransactionTracker, Self::Error>;
/// We need given finalized target header on source to continue synchronization.
async fn require_target_header_on_source(&self, id: TargetHeaderIdOf<P>);
/// Estimate cost of single message confirmation transaction in source chain tokens.
async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance;
}
/// Target client trait.
pub trait TargetClient<P: MessageLane>: RelayClient {
/// Transaction tracker to track submitted transactions.
type TransactionTracker: TransactionTracker<HeaderId = TargetHeaderIdOf<P>>;
/// Returns state of the client.
async fn state(&self) -> Result<TargetClientState<P>, Self::Error>;
/// Get nonce of latest received message.
async fn latest_received_nonce(
&self,
id: TargetHeaderIdOf<P>,
) -> Result<(TargetHeaderIdOf<P>, MessageNonce), Self::Error>;
/// Get nonce of the latest confirmed message.
async fn latest_confirmed_received_nonce(
&self,
id: TargetHeaderIdOf<P>,
) -> Result<(TargetHeaderIdOf<P>, MessageNonce), Self::Error>;
Loading full blame...