Rococo <> Wococo relayer balance guard (#998)

* relayer balance guards in Rococo <> Wococo

* removed printlns

* update constant

* update constant

* start balance guard for Wococo -> Rococo

* Update relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs

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

* Update relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Co-authored-by: Tomasz Drwięga <tomasz@parity.io>
This commit is contained in:
Svyatoslav Nikolsky
2021-06-14 22:21:58 +03:00
committed by Bastian Köcher
parent ec8412b6d0
commit f321b07606
10 changed files with 99 additions and 36 deletions
@@ -16,12 +16,13 @@
//! Rococo-to-Wococo headers sync entrypoint.
use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY;
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use bp_header_chain::justification::GrandpaJustification;
use codec::Encode;
use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader};
use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_substrate_client::{Chain, TransactionSignScheme};
use relay_utils::metrics::MetricsParams;
use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo};
use sp_core::{Bytes, Pair};
@@ -38,11 +39,16 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo {
crate::chains::add_polkadot_kusama_price_metrics::<Self>(params)
}
fn start_relay_guards(target_client: &Client<Self::TargetChain>) {
fn start_relay_guards(&self) {
relay_substrate_client::guard::abort_on_spec_version_change(
target_client.clone(),
self.target_client.clone(),
bp_wococo::VERSION.spec_version,
)
);
relay_substrate_client::guard::abort_when_account_balance_decreased(
self.target_client.clone(),
self.transactions_author(),
MAXIMAL_BALANCE_DECREASE_PER_DAY,
);
}
fn transactions_author(&self) -> bp_wococo::AccountId {
@@ -21,11 +21,18 @@ use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityT
use bp_header_chain::justification::GrandpaJustification;
use codec::Encode;
use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams};
use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_substrate_client::{Chain, TransactionSignScheme};
use relay_utils::metrics::MetricsParams;
use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo};
use sp_core::{Bytes, Pair};
/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat
/// relay as gone wild.
///
/// See `maximal_balance_decrease_per_day_is_sane` test for details.
/// Note that this is in plancks, so this corresponds to `1500 UNITS`.
pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_rococo::Balance = 1_500_000_000_000_000;
/// Wococo-to-Rococo finality sync pipeline.
pub(crate) type WococoFinalityToRococo = SubstrateFinalityToSubstrate<Wococo, Rococo, RococoSigningParams>;
@@ -38,11 +45,16 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
crate::chains::add_polkadot_kusama_price_metrics::<Self>(params)
}
fn start_relay_guards(target_client: &Client<Self::TargetChain>) {
fn start_relay_guards(&self) {
relay_substrate_client::guard::abort_on_spec_version_change(
target_client.clone(),
self.target_client.clone(),
bp_rococo::VERSION.spec_version,
)
);
relay_substrate_client::guard::abort_when_account_balance_decreased(
self.target_client.clone(),
self.transactions_author(),
MAXIMAL_BALANCE_DECREASE_PER_DAY,
);
}
fn transactions_author(&self) -> bp_rococo::AccountId {
@@ -65,3 +77,41 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
Bytes(transaction.encode())
}
}
#[cfg(test)]
mod tests {
use super::*;
use frame_support::weights::WeightToFeePolynomial;
use pallet_bridge_grandpa::weights::WeightInfo;
#[test]
fn maximal_balance_decrease_per_day_is_sane() {
// Rococo/Wococo GRANDPA pallet weights. They're now using Rialto weights => using `RialtoWeight` is justified.
//
// Using Rialto runtime this is slightly incorrect, because `DbWeight` of Rococo/Wococo runtime may differ
// from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is the same.
type RococoGrandpaPalletWeights = pallet_bridge_grandpa::weights::RialtoWeight<rialto_runtime::Runtime>;
// The following formula shall not be treated as super-accurate - guard is to protect from mad relays,
// not to protect from over-average loses.
//
// Worst case: we're submitting proof for every source header. Since we submit every header, the number of
// headers in ancestry proof is near to 0 (let's round up to 2). And the number of authorities is 1024,
// which is (now) larger than on any existing chain => normally there'll be ~1024*2/3+1 commits.
const AVG_VOTES_ANCESTRIES_LEN: u32 = 2;
const AVG_PRECOMMITS_LEN: u32 = 1024 * 2 / 3 + 1;
let number_of_source_headers_per_day: bp_wococo::Balance = bp_wococo::DAYS as _;
let single_source_header_submit_call_weight =
RococoGrandpaPalletWeights::submit_finality_proof(AVG_VOTES_ANCESTRIES_LEN, AVG_PRECOMMITS_LEN);
// for simplicity - add extra weight for base tx fee + fee that is paid for the tx size + adjusted fee
let single_source_header_submit_tx_weight = single_source_header_submit_call_weight * 3 / 2;
let single_source_header_tx_cost = bp_rococo::WeightToFee::calc(&single_source_header_submit_tx_weight);
let maximal_expected_decrease = single_source_header_tx_cost * number_of_source_headers_per_day;
assert!(
MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_expected_decrease,
"Maximal expected loss per day {} is larger than hardcoded {}",
maximal_expected_decrease,
MAXIMAL_BALANCE_DECREASE_PER_DAY,
);
}
}
@@ -97,15 +97,10 @@ impl RelayHeaders {
let target_client = self.target.to_client::<Target>().await?;
let target_sign = self.target_sign.to_keypair::<Target>()?;
let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?;
Finality::start_relay_guards(&target_client);
let finality = Finality::new(target_client.clone(), target_sign);
finality.start_relay_guards();
crate::finality_pipeline::run(
Finality::new(target_client.clone(), target_sign),
source_client,
target_client,
metrics_params,
)
.await
crate::finality_pipeline::run(finality, source_client, target_client, metrics_params).await
})
}
}
@@ -51,7 +51,7 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline {
/// Different finality bridges may have different set of guards - e.g. on ephemeral chains we
/// don't need version guards, on test chains we don't care that much about relayer account
/// balance, ... So the implementation is left to the specific bridges.
fn start_relay_guards(_target_client: &Client<Self::TargetChain>) {}
fn start_relay_guards(&self) {}
/// Returns id of account that we're using to sign transactions at target chain.
fn transactions_author(&self) -> <Self::TargetChain as Chain>::AccountId;