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
@@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies]
parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] }
smallvec = "1.6"
# Bridge Dependencies
bp-header-chain = { path = "../header-chain", default-features = false }
@@ -16,6 +17,7 @@ bp-polkadot-core = { path = "../polkadot-core", default-features = false }
bp-runtime = { path = "../runtime", default-features = false }
# Substrate Based Dependencies
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
@@ -28,6 +30,7 @@ std = [
"bp-messages/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"frame-support/std",
"parity-scale-codec/std",
"sp-api/std",
"sp-runtime/std",
@@ -22,6 +22,7 @@
use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState};
use bp_runtime::Chain;
use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial};
use sp_std::prelude::*;
use sp_version::RuntimeVersion;
@@ -43,6 +44,23 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
transaction_version: 0,
};
// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo.
pub struct WeightToFee;
impl WeightToFeePolynomial for WeightToFee {
type Balance = Balance;
fn polynomial() -> WeightToFeeCoefficients<Balance> {
const CENTS: Balance = 1_000_000_000_000 / 100;
let p = CENTS;
let q = 10 * Balance::from(ExtrinsicBaseWeight::get());
smallvec::smallvec![WeightToFeeCoefficient {
degree: 1,
negative: false,
coeff_frac: Perbill::from_rational(p % q, q),
coeff_integer: p / q,
}]
}
}
/// Rococo Runtime `Call` enum.
///
/// The enum represents a subset of possible `Call`s we can send to Rococo chain.
+2 -2
View File
@@ -13,13 +13,13 @@ parity-scale-codec = { version = "2.0.0", default-features = false, features = [
bp-header-chain = { path = "../header-chain", default-features = false }
bp-messages = { path = "../messages", default-features = false }
bp-polkadot-core = { path = "../polkadot-core", default-features = false }
bp-rococo = { path = "../chain-rococo", default-features = false }
bp-runtime = { path = "../runtime", default-features = false }
# Substrate Based Dependencies
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
[features]
default = ["std"]
@@ -28,9 +28,9 @@ std = [
"bp-messages/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"bp-rococo/std",
"parity-scale-codec/std",
"sp-api/std",
"sp-runtime/std",
"sp-std/std",
"sp-version/std",
]
+2 -12
View File
@@ -23,26 +23,16 @@
use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState};
use bp_runtime::Chain;
use sp_std::prelude::*;
use sp_version::RuntimeVersion;
pub use bp_polkadot_core::*;
// Rococo runtime = Wococo runtime
pub use bp_rococo::{WeightToFee, VERSION};
/// Wococo Chain
pub type Wococo = PolkadotLike;
pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic<Call>;
// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: sp_version::create_runtime_str!("rococo"),
impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"),
authoring_version: 0,
spec_version: 9004,
impl_version: 0,
apis: sp_version::create_apis_vec![[]],
transaction_version: 0,
};
/// Wococo Runtime `Call` enum.
///
/// The enum represents a subset of possible `Call`s we can send to Rococo chain.
+4 -4
View File
@@ -22,7 +22,7 @@ use frame_support::{
dispatch::Dispatchable,
parameter_types,
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND},
constants::{BlockExecutionWeight, WEIGHT_PER_SECOND},
DispatchClass, Weight,
},
Blake2_128Concat, RuntimeDebug, StorageHasher, Twox128,
@@ -33,13 +33,13 @@ use sp_core::Hasher as HasherT;
use sp_runtime::{
generic,
traits::{BlakeTwo256, IdentifyAccount, Verify},
MultiAddress, MultiSignature, OpaqueExtrinsic, Perbill,
MultiAddress, MultiSignature, OpaqueExtrinsic,
};
use sp_std::prelude::Vec;
// Re-export's to avoid extra substrate dependencies in chain-specific crates.
pub use frame_support::Parameter;
pub use sp_runtime::traits::Convert;
pub use frame_support::{weights::constants::ExtrinsicBaseWeight, Parameter};
pub use sp_runtime::{traits::Convert, Perbill};
/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at
/// Polkadot-like chain. This mostly depends on number of entries in the storage trie.
+2 -1
View File
@@ -59,5 +59,6 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dev-dependencies]
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
hex-literal = "0.3"
pallet-bridge-grandpa = { path = "../../modules/grandpa" }
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -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;