mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-25 15:17:57 +00:00
Introduce bridge relayers pallet (#1513)
* introduce relayers pallet * add MessageDeliveryAndDispatchPaymentAdapter * plug in pallet into test runtimes * tests prototype * tests for the relayers pallet * tests for payment adapter * mint_reward_payment_procedure_actually_mints_tokens * benchmarks * remove irrelevant todo * remove redundant clone
This commit is contained in:
committed by
Bastian Köcher
parent
1e0c2a6e02
commit
7590abd1a3
@@ -20,6 +20,7 @@ bp-header-chain = { path = "../../../primitives/header-chain", default-features
|
||||
bp-messages = { path = "../../../primitives/messages", default-features = false }
|
||||
bp-millau = { path = "../../../primitives/chain-millau", default-features = false }
|
||||
bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false }
|
||||
bp-relayers = { path = "../../../primitives/relayers", default-features = false }
|
||||
bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false }
|
||||
bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false }
|
||||
bp-runtime = { path = "../../../primitives/runtime", default-features = false }
|
||||
@@ -28,6 +29,7 @@ bridge-runtime-common = { path = "../../runtime-common", default-features = fals
|
||||
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
|
||||
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
|
||||
pallet-bridge-parachains = { path = "../../../modules/parachains", default-features = false }
|
||||
pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false }
|
||||
pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
@@ -89,6 +91,7 @@ std = [
|
||||
"bp-messages/std",
|
||||
"bp-millau/std",
|
||||
"bp-polkadot-core/std",
|
||||
"bp-relayers/std",
|
||||
"bp-rialto/std",
|
||||
"bp-rialto-parachain/std",
|
||||
"bp-runtime/std",
|
||||
@@ -107,6 +110,7 @@ std = [
|
||||
"pallet-bridge-grandpa/std",
|
||||
"pallet-bridge-messages/std",
|
||||
"pallet-bridge-parachains/std",
|
||||
"pallet-bridge-relayers/std",
|
||||
"pallet-grandpa/std",
|
||||
"pallet-mmr/std",
|
||||
"pallet-randomness-collective-flip/std",
|
||||
@@ -145,6 +149,7 @@ runtime-benchmarks = [
|
||||
"libsecp256k1",
|
||||
"pallet-bridge-messages/runtime-benchmarks",
|
||||
"pallet-bridge-parachains/runtime-benchmarks",
|
||||
"pallet-bridge-relayers/runtime-benchmarks",
|
||||
"pallet-xcm/runtime-benchmarks",
|
||||
"sp-runtime/runtime-benchmarks",
|
||||
"xcm-builder/runtime-benchmarks",
|
||||
|
||||
@@ -388,6 +388,13 @@ parameter_types! {
|
||||
pub const MaxRequests: u32 = 50;
|
||||
}
|
||||
|
||||
impl pallet_bridge_relayers::Config for Runtime {
|
||||
type Event = Event;
|
||||
type Reward = Balance;
|
||||
type PaymentProcedure = bp_relayers::MintReward<pallet_balances::Pallet<Runtime>, AccountId>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
parameter_types! {
|
||||
/// Number of headers to keep in benchmarks.
|
||||
@@ -463,7 +470,12 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
|
||||
|
||||
type TargetHeaderChain = crate::rialto_messages::Rialto;
|
||||
type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier;
|
||||
type MessageDeliveryAndDispatchPayment = ();
|
||||
type MessageDeliveryAndDispatchPayment =
|
||||
pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter<
|
||||
Runtime,
|
||||
WithRialtoMessagesInstance,
|
||||
GetDeliveryConfirmationTransactionFee,
|
||||
>;
|
||||
type OnMessageAccepted = ();
|
||||
type OnDeliveryConfirmed = ();
|
||||
|
||||
@@ -494,7 +506,12 @@ impl pallet_bridge_messages::Config<WithRialtoParachainMessagesInstance> for Run
|
||||
|
||||
type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain;
|
||||
type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier;
|
||||
type MessageDeliveryAndDispatchPayment = ();
|
||||
type MessageDeliveryAndDispatchPayment =
|
||||
pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter<
|
||||
Runtime,
|
||||
WithRialtoParachainMessagesInstance,
|
||||
GetDeliveryConfirmationTransactionFee,
|
||||
>;
|
||||
type OnMessageAccepted = ();
|
||||
type OnDeliveryConfirmed = ();
|
||||
|
||||
@@ -558,6 +575,7 @@ construct_runtime!(
|
||||
MmrLeaf: pallet_beefy_mmr::{Pallet, Storage},
|
||||
|
||||
// Rialto bridge modules.
|
||||
BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event<T>},
|
||||
BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
|
||||
BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
|
||||
|
||||
@@ -937,6 +955,7 @@ impl_runtime_apis! {
|
||||
list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::<Runtime, WithRialtoMessagesInstance>);
|
||||
list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa);
|
||||
list_benchmark!(list, extra, pallet_bridge_parachains, ParachainsBench::<Runtime, WithRialtoMessagesInstance>);
|
||||
list_benchmark!(list, extra, pallet_bridge_relayers, BridgeRelayers);
|
||||
|
||||
let storage_info = AllPalletsWithSystem::storage_info();
|
||||
|
||||
@@ -1058,6 +1077,7 @@ impl_runtime_apis! {
|
||||
pallet_bridge_parachains,
|
||||
ParachainsBench::<Runtime, WithRialtoParachainsInstance>
|
||||
);
|
||||
add_benchmark!(params, batches, pallet_bridge_relayers, BridgeRelayers);
|
||||
|
||||
Ok(batches)
|
||||
}
|
||||
|
||||
@@ -19,11 +19,13 @@ serde = { version = '1.0', optional = true, features = ['derive'] }
|
||||
|
||||
bp-messages = { path = "../../../primitives/messages", default-features = false }
|
||||
bp-millau = { path = "../../../primitives/chain-millau", default-features = false }
|
||||
bp-relayers = { path = "../../../primitives/relayers", default-features = false }
|
||||
bp-runtime = { path = "../../../primitives/runtime", default-features = false }
|
||||
bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false }
|
||||
bridge-runtime-common = { path = "../../runtime-common", default-features = false }
|
||||
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
|
||||
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
|
||||
pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
## Substrate Primitive Dependencies
|
||||
@@ -89,6 +91,7 @@ runtime-benchmarks = [
|
||||
std = [
|
||||
"bp-messages/std",
|
||||
"bp-millau/std",
|
||||
"bp-relayers/std",
|
||||
"bp-runtime/std",
|
||||
"bp-rialto-parachain/std",
|
||||
"bridge-runtime-common/std",
|
||||
@@ -113,6 +116,7 @@ std = [
|
||||
"pallet-balances/std",
|
||||
"pallet-bridge-grandpa/std",
|
||||
"pallet-bridge-messages/std",
|
||||
"pallet-bridge-relayers/std",
|
||||
"pallet-randomness-collective-flip/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-sudo/std",
|
||||
|
||||
@@ -474,6 +474,13 @@ impl pallet_aura::Config for Runtime {
|
||||
type MaxAuthorities = MaxAuthorities;
|
||||
}
|
||||
|
||||
impl pallet_bridge_relayers::Config for Runtime {
|
||||
type Event = Event;
|
||||
type Reward = Balance;
|
||||
type PaymentProcedure = bp_relayers::MintReward<pallet_balances::Pallet<Runtime>, AccountId>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
/// This is a pretty unscientific cap.
|
||||
///
|
||||
@@ -530,7 +537,12 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
|
||||
|
||||
type TargetHeaderChain = crate::millau_messages::Millau;
|
||||
type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier;
|
||||
type MessageDeliveryAndDispatchPayment = ();
|
||||
type MessageDeliveryAndDispatchPayment =
|
||||
pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter<
|
||||
Runtime,
|
||||
WithMillauMessagesInstance,
|
||||
GetDeliveryConfirmationTransactionFee,
|
||||
>;
|
||||
type OnMessageAccepted = ();
|
||||
type OnDeliveryConfirmed = ();
|
||||
|
||||
@@ -567,6 +579,7 @@ construct_runtime!(
|
||||
DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
|
||||
|
||||
// Millau bridge modules.
|
||||
BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event<T>},
|
||||
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
|
||||
BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
|
||||
}
|
||||
|
||||
@@ -19,11 +19,13 @@ serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||
bp-header-chain = { path = "../../../primitives/header-chain", default-features = false }
|
||||
bp-messages = { path = "../../../primitives/messages", default-features = false }
|
||||
bp-millau = { path = "../../../primitives/chain-millau", default-features = false }
|
||||
bp-relayers = { path = "../../../primitives/relayers", default-features = false }
|
||||
bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false }
|
||||
bp-runtime = { path = "../../../primitives/runtime", default-features = false }
|
||||
bridge-runtime-common = { path = "../../runtime-common", default-features = false }
|
||||
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
|
||||
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
|
||||
pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false }
|
||||
pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
@@ -89,6 +91,7 @@ std = [
|
||||
"bp-header-chain/std",
|
||||
"bp-messages/std",
|
||||
"bp-millau/std",
|
||||
"bp-relayers/std",
|
||||
"bp-rialto/std",
|
||||
"bp-runtime/std",
|
||||
"bridge-runtime-common/std",
|
||||
@@ -106,6 +109,7 @@ std = [
|
||||
"pallet-beefy-mmr/std",
|
||||
"pallet-bridge-grandpa/std",
|
||||
"pallet-bridge-messages/std",
|
||||
"pallet-bridge-relayers/std",
|
||||
"pallet-grandpa/std",
|
||||
"pallet-mmr/std",
|
||||
"pallet-xcm/std",
|
||||
|
||||
@@ -389,6 +389,13 @@ impl pallet_authority_discovery::Config for Runtime {
|
||||
type MaxAuthorities = MaxAuthorities;
|
||||
}
|
||||
|
||||
impl pallet_bridge_relayers::Config for Runtime {
|
||||
type Event = Event;
|
||||
type Reward = Balance;
|
||||
type PaymentProcedure = bp_relayers::MintReward<pallet_balances::Pallet<Runtime>, AccountId>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
/// This is a pretty unscientific cap.
|
||||
///
|
||||
@@ -447,7 +454,12 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
|
||||
|
||||
type TargetHeaderChain = crate::millau_messages::Millau;
|
||||
type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier;
|
||||
type MessageDeliveryAndDispatchPayment = ();
|
||||
type MessageDeliveryAndDispatchPayment =
|
||||
pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter<
|
||||
Runtime,
|
||||
WithMillauMessagesInstance,
|
||||
GetDeliveryConfirmationTransactionFee,
|
||||
>;
|
||||
type OnMessageAccepted = ();
|
||||
type OnDeliveryConfirmed = ();
|
||||
|
||||
@@ -484,6 +496,7 @@ construct_runtime!(
|
||||
MmrLeaf: pallet_beefy_mmr::{Pallet, Storage},
|
||||
|
||||
// Millau bridge modules.
|
||||
BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event<T>},
|
||||
BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
|
||||
BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#![allow(clippy::all)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{
|
||||
traits::Get,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Autogenerated weights for `pallet_bridge_messages`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2022-07-07, STEPS: 50, REPEAT: 20
|
||||
//! DATE: 2022-07-20, STEPS: 50, REPEAT: 20
|
||||
//! LOW RANGE: [], HIGH RANGE: []
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled
|
||||
//! CHAIN: Some("dev"), DB CACHE: 1024
|
||||
@@ -40,6 +40,7 @@
|
||||
#![allow(clippy::all)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{
|
||||
traits::Get,
|
||||
@@ -69,22 +70,22 @@ pub trait WeightInfo {
|
||||
pub struct MillauWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for MillauWeight<T> {
|
||||
fn send_minimal_message_worst_case() -> Weight {
|
||||
(37_948_000 as Weight)
|
||||
(38_822_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(10 as Weight))
|
||||
}
|
||||
fn send_1_kb_message_worst_case() -> Weight {
|
||||
(39_158_000 as Weight)
|
||||
(39_799_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(10 as Weight))
|
||||
}
|
||||
fn send_16_kb_message_worst_case() -> Weight {
|
||||
(48_698_000 as Weight)
|
||||
(47_772_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(10 as Weight))
|
||||
}
|
||||
fn maximal_increase_message_fee() -> Weight {
|
||||
(2_919_864_000 as Weight)
|
||||
(3_081_804_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
@@ -95,71 +96,71 @@ impl<T: frame_system::Config> WeightInfo for MillauWeight<T> {
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn receive_single_message_proof() -> Weight {
|
||||
(25_992_000 as Weight)
|
||||
(26_523_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_two_messages_proof() -> Weight {
|
||||
(37_016_000 as Weight)
|
||||
(39_278_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
|
||||
(31_589_000 as Weight)
|
||||
(32_416_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_single_message_proof_1_kb() -> Weight {
|
||||
(25_962_000 as Weight)
|
||||
(27_078_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn receive_single_message_proof_16_kb() -> Weight {
|
||||
(74_385_000 as Weight)
|
||||
(78_235_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn receive_single_prepaid_message_proof() -> Weight {
|
||||
(26_159_000 as Weight)
|
||||
(27_635_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_delivery_proof_for_single_message() -> Weight {
|
||||
(27_590_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
(34_576_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
|
||||
(27_354_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
(37_318_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(6 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
|
||||
(27_652_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(1 as Weight))
|
||||
(41_245_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(7 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
fn send_minimal_message_worst_case() -> Weight {
|
||||
(37_948_000 as Weight)
|
||||
(38_822_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(10 as Weight))
|
||||
}
|
||||
fn send_1_kb_message_worst_case() -> Weight {
|
||||
(39_158_000 as Weight)
|
||||
(39_799_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(10 as Weight))
|
||||
}
|
||||
fn send_16_kb_message_worst_case() -> Weight {
|
||||
(48_698_000 as Weight)
|
||||
(47_772_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(10 as Weight))
|
||||
}
|
||||
fn maximal_increase_message_fee() -> Weight {
|
||||
(2_919_864_000 as Weight)
|
||||
(3_081_804_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
@@ -170,48 +171,48 @@ impl WeightInfo for () {
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn receive_single_message_proof() -> Weight {
|
||||
(25_992_000 as Weight)
|
||||
(26_523_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_two_messages_proof() -> Weight {
|
||||
(37_016_000 as Weight)
|
||||
(39_278_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_single_message_proof_with_outbound_lane_state() -> Weight {
|
||||
(31_589_000 as Weight)
|
||||
(32_416_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_single_message_proof_1_kb() -> Weight {
|
||||
(25_962_000 as Weight)
|
||||
(27_078_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn receive_single_message_proof_16_kb() -> Weight {
|
||||
(74_385_000 as Weight)
|
||||
(78_235_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
}
|
||||
fn receive_single_prepaid_message_proof() -> Weight {
|
||||
(26_159_000 as Weight)
|
||||
(27_635_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_delivery_proof_for_single_message() -> Weight {
|
||||
(27_590_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
(34_576_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight {
|
||||
(27_354_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
(37_318_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(6 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight {
|
||||
(27_652_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
|
||||
(41_245_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#![allow(clippy::all)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{
|
||||
traits::Get,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
[package]
|
||||
name = "pallet-bridge-relayers"
|
||||
description = "Module used to store relayer rewards and coordinate relayers set."
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false }
|
||||
log = { version = "0.4.14", default-features = false }
|
||||
num-traits = { version = "0.2", default-features = false }
|
||||
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
|
||||
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
bp-messages = { path = "../../primitives/messages", default-features = false }
|
||||
bp-relayers = { path = "../../primitives/relayers", default-features = false }
|
||||
pallet-bridge-messages = { path = "../messages", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
bp-runtime = { path = "../../primitives/runtime" }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"bp-messages/std",
|
||||
"bp-relayers/std",
|
||||
"codec/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
"log/std",
|
||||
"num-traits/std",
|
||||
"pallet-bridge-messages/std",
|
||||
"scale-info/std",
|
||||
"serde",
|
||||
"sp-arithmetic/std",
|
||||
"sp-std/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"frame-benchmarking/runtime-benchmarks",
|
||||
]
|
||||
@@ -0,0 +1,40 @@
|
||||
// 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/>.
|
||||
|
||||
//! Benchmarks for the relayers Pallet.
|
||||
|
||||
#![cfg(feature = "runtime-benchmarks")]
|
||||
|
||||
use crate::*;
|
||||
|
||||
use frame_benchmarking::{benchmarks, whitelisted_caller};
|
||||
use frame_system::RawOrigin;
|
||||
|
||||
/// Reward amount that is (hopefully) is larger than existential deposit across all chains.
|
||||
const REWARD_AMOUNT: u32 = u32::MAX;
|
||||
|
||||
benchmarks! {
|
||||
// Benchmark `claim_rewards` call.
|
||||
claim_rewards {
|
||||
let relayer: T::AccountId = whitelisted_caller();
|
||||
RelayerRewards::<T>::insert(&relayer, T::Reward::from(REWARD_AMOUNT));
|
||||
}: _(RawOrigin::Signed(relayer))
|
||||
verify {
|
||||
// we can't check anything here, because `PaymentProcedure` is responsible for
|
||||
// payment logic, so we assume that if call has succeeded, the procedure has
|
||||
// also completed successfully
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
// 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/>.
|
||||
|
||||
//! Runtime module that is used to store relayer rewards and (in the future) to
|
||||
//! coordinate relations between relayers.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use bp_relayers::PaymentProcedure;
|
||||
use sp_arithmetic::traits::AtLeast32BitUnsigned;
|
||||
use sp_std::marker::PhantomData;
|
||||
use weights::WeightInfo;
|
||||
|
||||
pub use pallet::*;
|
||||
pub use payment_adapter::MessageDeliveryAndDispatchPaymentAdapter;
|
||||
|
||||
mod benchmarking;
|
||||
mod mock;
|
||||
mod payment_adapter;
|
||||
|
||||
pub mod weights;
|
||||
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
use frame_support::pallet_prelude::*;
|
||||
use frame_system::pallet_prelude::*;
|
||||
|
||||
#[pallet::config]
|
||||
pub trait Config: frame_system::Config {
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
|
||||
/// Type of relayer reward.
|
||||
type Reward: AtLeast32BitUnsigned + Copy + Parameter + MaxEncodedLen;
|
||||
/// Pay rewards adapter.
|
||||
type PaymentProcedure: PaymentProcedure<Self::AccountId, Self::Reward>;
|
||||
/// Pallet call weights.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::generate_store(pub(super) trait Store)]
|
||||
pub struct Pallet<T>(PhantomData<T>);
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Claim accumulated rewards.
|
||||
#[pallet::weight(T::WeightInfo::claim_rewards())]
|
||||
pub fn claim_rewards(origin: OriginFor<T>) -> DispatchResult {
|
||||
let relayer = ensure_signed(origin)?;
|
||||
|
||||
RelayerRewards::<T>::try_mutate_exists(&relayer, |maybe_reward| -> DispatchResult {
|
||||
let reward = maybe_reward.take().ok_or(Error::<T>::NoRewardForRelayer)?;
|
||||
T::PaymentProcedure::pay_reward(&relayer, reward).map_err(|e| {
|
||||
log::trace!(
|
||||
target: "runtime::bridge-relayers",
|
||||
"Failed to pay rewards to {:?}: {:?}",
|
||||
relayer,
|
||||
e,
|
||||
);
|
||||
Error::<T>::FailedToPayReward
|
||||
})?;
|
||||
|
||||
Self::deposit_event(Event::<T>::RewardPaid { relayer: relayer.clone(), reward });
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::event]
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
/// Reward has been paid to the relayer.
|
||||
RewardPaid {
|
||||
/// Relayer account that has been rewarded.
|
||||
relayer: T::AccountId,
|
||||
/// Reward amount.
|
||||
reward: T::Reward,
|
||||
},
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
pub enum Error<T> {
|
||||
/// No reward can be claimed by given relayer.
|
||||
NoRewardForRelayer,
|
||||
/// Reward payment procedure has failed.
|
||||
FailedToPayReward,
|
||||
}
|
||||
|
||||
/// Map of the relayer => accumulated reward.
|
||||
#[pallet::storage]
|
||||
pub type RelayerRewards<T: Config> =
|
||||
StorageMap<_, Blake2_128Concat, T::AccountId, T::Reward, OptionQuery>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use mock::*;
|
||||
|
||||
use frame_support::{assert_noop, assert_ok, traits::fungible::Inspect};
|
||||
use sp_runtime::DispatchError;
|
||||
|
||||
#[test]
|
||||
fn root_cant_claim_anything() {
|
||||
run_test(|| {
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::claim_rewards(Origin::root()),
|
||||
DispatchError::BadOrigin,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relayer_cant_claim_if_no_reward_exists() {
|
||||
run_test(|| {
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::claim_rewards(Origin::signed(REGULAR_RELAYER)),
|
||||
Error::<TestRuntime>::NoRewardForRelayer,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relayer_cant_claim_if_payment_procedure_fails() {
|
||||
run_test(|| {
|
||||
RelayerRewards::<TestRuntime>::insert(FAILING_RELAYER, 100);
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::claim_rewards(Origin::signed(FAILING_RELAYER)),
|
||||
Error::<TestRuntime>::FailedToPayReward,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relayer_can_claim_reward() {
|
||||
run_test(|| {
|
||||
RelayerRewards::<TestRuntime>::insert(REGULAR_RELAYER, 100);
|
||||
assert_ok!(Pallet::<TestRuntime>::claim_rewards(Origin::signed(REGULAR_RELAYER)));
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(REGULAR_RELAYER), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mint_reward_payment_procedure_actually_mints_tokens() {
|
||||
type Balances = pallet_balances::Pallet<TestRuntime>;
|
||||
|
||||
run_test(|| {
|
||||
assert_eq!(Balances::balance(&1), 0);
|
||||
assert_eq!(Balances::total_issuance(), 0);
|
||||
bp_relayers::MintReward::<Balances, AccountId>::pay_reward(&1, 100).unwrap();
|
||||
assert_eq!(Balances::balance(&1), 100);
|
||||
assert_eq!(Balances::total_issuance(), 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// 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/>.
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use crate as pallet_bridge_relayers;
|
||||
|
||||
use bp_messages::{source_chain::ForbidOutboundMessages, target_chain::ForbidInboundMessages};
|
||||
use bp_relayers::PaymentProcedure;
|
||||
use frame_support::{parameter_types, weights::RuntimeDbWeight};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
testing::Header as SubstrateHeader,
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
};
|
||||
|
||||
pub type AccountId = u64;
|
||||
pub type Balance = u64;
|
||||
|
||||
type Block = frame_system::mocking::MockBlock<TestRuntime>;
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
|
||||
|
||||
frame_support::construct_runtime! {
|
||||
pub enum TestRuntime where
|
||||
Block = Block,
|
||||
NodeBlock = Block,
|
||||
UncheckedExtrinsic = UncheckedExtrinsic,
|
||||
{
|
||||
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
|
||||
Balances: pallet_balances::{Pallet, Event<T>},
|
||||
Messages: pallet_bridge_messages::{Pallet, Event<T>},
|
||||
Relayers: pallet_bridge_relayers::{Pallet, Call, Event<T>},
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 };
|
||||
}
|
||||
|
||||
impl frame_system::Config for TestRuntime {
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type Call = Call;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = AccountId;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = SubstrateHeader;
|
||||
type Event = Event;
|
||||
type BlockHashCount = frame_support::traits::ConstU64<250>;
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = pallet_balances::AccountData<Balance>;
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type BaseCallFilter = frame_support::traits::Everything;
|
||||
type SystemWeightInfo = ();
|
||||
type BlockWeights = ();
|
||||
type BlockLength = ();
|
||||
type DbWeight = DbWeight;
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = frame_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
impl pallet_balances::Config for TestRuntime {
|
||||
type MaxLocks = ();
|
||||
type Balance = Balance;
|
||||
type DustRemoval = ();
|
||||
type Event = Event;
|
||||
type ExistentialDeposit = frame_support::traits::ConstU64<1>;
|
||||
type AccountStore = frame_system::Pallet<TestRuntime>;
|
||||
type WeightInfo = ();
|
||||
type MaxReserves = ();
|
||||
type ReserveIdentifier = ();
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const TestBridgedChainId: bp_runtime::ChainId = *b"test";
|
||||
}
|
||||
|
||||
// we're not testing messages pallet here, so values in this config might be crazy
|
||||
impl pallet_bridge_messages::Config for TestRuntime {
|
||||
type Event = Event;
|
||||
type WeightInfo = ();
|
||||
type Parameter = ();
|
||||
type MaxMessagesToPruneAtOnce = frame_support::traits::ConstU64<0>;
|
||||
type MaxUnrewardedRelayerEntriesAtInboundLane = frame_support::traits::ConstU64<8>;
|
||||
type MaxUnconfirmedMessagesAtInboundLane = frame_support::traits::ConstU64<8>;
|
||||
|
||||
type MaximalOutboundPayloadSize = frame_support::traits::ConstU32<1024>;
|
||||
type OutboundPayload = ();
|
||||
type OutboundMessageFee = Balance;
|
||||
|
||||
type InboundPayload = ();
|
||||
type InboundMessageFee = Balance;
|
||||
type InboundRelayer = AccountId;
|
||||
|
||||
type TargetHeaderChain = ForbidOutboundMessages;
|
||||
type LaneMessageVerifier = ForbidOutboundMessages;
|
||||
type MessageDeliveryAndDispatchPayment = ();
|
||||
type OnMessageAccepted = ();
|
||||
type OnDeliveryConfirmed = ();
|
||||
|
||||
type SourceHeaderChain = ForbidInboundMessages;
|
||||
type MessageDispatch = ForbidInboundMessages;
|
||||
type BridgedChainId = TestBridgedChainId;
|
||||
}
|
||||
|
||||
impl pallet_bridge_relayers::Config for TestRuntime {
|
||||
type Event = Event;
|
||||
type Reward = Balance;
|
||||
type PaymentProcedure = TestPaymentProcedure;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
/// Regular relayer that may receive rewards.
|
||||
pub const REGULAR_RELAYER: AccountId = 1;
|
||||
|
||||
/// Relayer that can't receive rewards.
|
||||
pub const FAILING_RELAYER: AccountId = 2;
|
||||
|
||||
/// Payment procedure that rejects payments to the `FAILING_RELAYER`.
|
||||
pub struct TestPaymentProcedure;
|
||||
|
||||
impl PaymentProcedure<AccountId, Balance> for TestPaymentProcedure {
|
||||
type Error = ();
|
||||
|
||||
fn pay_reward(relayer: &AccountId, _reward: Balance) -> Result<(), Self::Error> {
|
||||
match *relayer {
|
||||
FAILING_RELAYER => Err(()),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Run pallet test.
|
||||
pub fn run_test<T>(test: impl FnOnce() -> T) -> T {
|
||||
let t = frame_system::GenesisConfig::default().build_storage::<TestRuntime>().unwrap();
|
||||
let mut ext = sp_io::TestExternalities::new(t);
|
||||
ext.execute_with(test)
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
// 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/>.
|
||||
|
||||
//! Code that allows relayers pallet to be used as a delivery+dispatch payment mechanism
|
||||
//! for the messages pallet.
|
||||
|
||||
use crate::{Config, RelayerRewards};
|
||||
|
||||
use bp_messages::source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards};
|
||||
use frame_support::traits::Get;
|
||||
use sp_arithmetic::traits::{Bounded, Saturating, Zero};
|
||||
use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive};
|
||||
|
||||
/// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism
|
||||
/// for the messages pallet.
|
||||
pub struct MessageDeliveryAndDispatchPaymentAdapter<T, MessagesInstance, GetConfirmationFee>(
|
||||
PhantomData<(T, MessagesInstance, GetConfirmationFee)>,
|
||||
);
|
||||
|
||||
impl<T, MessagesInstance, GetConfirmationFee>
|
||||
MessageDeliveryAndDispatchPayment<T::Origin, T::AccountId, T::Reward>
|
||||
for MessageDeliveryAndDispatchPaymentAdapter<T, MessagesInstance, GetConfirmationFee>
|
||||
where
|
||||
T: Config + pallet_bridge_messages::Config<MessagesInstance, OutboundMessageFee = T::Reward>,
|
||||
MessagesInstance: 'static,
|
||||
GetConfirmationFee: Get<T::Reward>,
|
||||
{
|
||||
type Error = &'static str;
|
||||
|
||||
fn pay_delivery_and_dispatch_fee(
|
||||
_submitter: &T::Origin,
|
||||
_fee: &T::Reward,
|
||||
) -> Result<(), Self::Error> {
|
||||
// nothing shall happen here, because XCM deals with fee payment (planned to be burnt?
|
||||
// or transferred to the treasury?)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pay_relayers_rewards(
|
||||
lane_id: bp_messages::LaneId,
|
||||
messages_relayers: VecDeque<bp_messages::UnrewardedRelayer<T::AccountId>>,
|
||||
confirmation_relayer: &T::AccountId,
|
||||
received_range: &RangeInclusive<bp_messages::MessageNonce>,
|
||||
) {
|
||||
let relayers_rewards = pallet_bridge_messages::calc_relayers_rewards::<T, MessagesInstance>(
|
||||
lane_id,
|
||||
messages_relayers,
|
||||
received_range,
|
||||
);
|
||||
if !relayers_rewards.is_empty() {
|
||||
schedule_relayers_rewards::<T>(
|
||||
confirmation_relayer,
|
||||
relayers_rewards,
|
||||
GetConfirmationFee::get(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update rewards to given relayers, optionally rewarding confirmation relayer.
|
||||
fn schedule_relayers_rewards<T: Config>(
|
||||
confirmation_relayer: &T::AccountId,
|
||||
relayers_rewards: RelayersRewards<T::AccountId, T::Reward>,
|
||||
confirmation_fee: T::Reward,
|
||||
) {
|
||||
// reward every relayer except `confirmation_relayer`
|
||||
let mut confirmation_relayer_reward = T::Reward::zero();
|
||||
for (relayer, reward) in relayers_rewards {
|
||||
let mut relayer_reward = reward.reward;
|
||||
|
||||
if relayer != *confirmation_relayer {
|
||||
// If delivery confirmation is submitted by other relayer, let's deduct confirmation fee
|
||||
// from relayer reward.
|
||||
//
|
||||
// If confirmation fee has been increased (or if it was the only component of message
|
||||
// fee), then messages relayer may receive zero reward.
|
||||
let mut confirmation_reward = T::Reward::try_from(reward.messages)
|
||||
.unwrap_or_else(|_| Bounded::max_value())
|
||||
.saturating_mul(confirmation_fee);
|
||||
if confirmation_reward > relayer_reward {
|
||||
confirmation_reward = relayer_reward;
|
||||
}
|
||||
relayer_reward = relayer_reward.saturating_sub(confirmation_reward);
|
||||
confirmation_relayer_reward =
|
||||
confirmation_relayer_reward.saturating_add(confirmation_reward);
|
||||
} else {
|
||||
// If delivery confirmation is submitted by this relayer, let's add confirmation fee
|
||||
// from other relayers to this relayer reward.
|
||||
confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(reward.reward);
|
||||
continue
|
||||
}
|
||||
|
||||
schedule_relayer_reward::<T>(&relayer, relayer_reward);
|
||||
}
|
||||
|
||||
// finally - pay reward to confirmation relayer
|
||||
schedule_relayer_reward::<T>(confirmation_relayer, confirmation_relayer_reward);
|
||||
}
|
||||
|
||||
/// Remember that the reward shall be paid to the relayer.
|
||||
fn schedule_relayer_reward<T: Config>(relayer: &T::AccountId, reward: T::Reward) {
|
||||
if reward.is_zero() {
|
||||
return
|
||||
}
|
||||
|
||||
RelayerRewards::<T>::mutate(relayer, |old_reward: &mut Option<T::Reward>| {
|
||||
let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward);
|
||||
log::trace!(
|
||||
target: "T::bridge-relayers",
|
||||
"Relayer {:?} can now claim reward: {:?}",
|
||||
relayer,
|
||||
new_reward,
|
||||
);
|
||||
*old_reward = Some(new_reward);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::*;
|
||||
|
||||
const RELAYER_1: AccountId = 1;
|
||||
const RELAYER_2: AccountId = 2;
|
||||
const RELAYER_3: AccountId = 3;
|
||||
|
||||
fn relayers_rewards() -> RelayersRewards<AccountId, Balance> {
|
||||
vec![
|
||||
(RELAYER_1, bp_messages::source_chain::RelayerRewards { reward: 100, messages: 2 }),
|
||||
(RELAYER_2, bp_messages::source_chain::RelayerRewards { reward: 100, messages: 3 }),
|
||||
]
|
||||
.into_iter()
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() {
|
||||
run_test(|| {
|
||||
schedule_relayers_rewards::<TestRuntime>(&RELAYER_2, relayers_rewards(), 10);
|
||||
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(&RELAYER_1), Some(80));
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(&RELAYER_2), Some(120));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() {
|
||||
run_test(|| {
|
||||
schedule_relayers_rewards::<TestRuntime>(&RELAYER_3, relayers_rewards(), 10);
|
||||
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(&RELAYER_1), Some(80));
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(&RELAYER_2), Some(70));
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(&RELAYER_3), Some(50));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() {
|
||||
run_test(|| {
|
||||
schedule_relayers_rewards::<TestRuntime>(&RELAYER_3, relayers_rewards(), 1000);
|
||||
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(&RELAYER_1), None);
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(&RELAYER_2), None);
|
||||
assert_eq!(RelayerRewards::<TestRuntime>::get(&RELAYER_3), Some(200));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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/>.
|
||||
|
||||
//! Autogenerated weights for `pallet_bridge_relayers`
|
||||
//!
|
||||
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
|
||||
//! DATE: 2022-07-20, STEPS: 50, REPEAT: 20
|
||||
//! LOW RANGE: [], HIGH RANGE: []
|
||||
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled
|
||||
//! CHAIN: Some("dev"), DB CACHE: 1024
|
||||
|
||||
// Executed Command:
|
||||
// target/release/millau-bridge-node
|
||||
// benchmark
|
||||
// pallet
|
||||
// --chain=dev
|
||||
// --steps=50
|
||||
// --repeat=20
|
||||
// --pallet=pallet_bridge_relayers
|
||||
// --extrinsic=*
|
||||
// --execution=wasm
|
||||
// --wasm-execution=Compiled
|
||||
// --heap-pages=4096
|
||||
// --output=./modules/relayers/src/weights.rs
|
||||
// --template=./.maintain/millau-weight-template.hbs
|
||||
|
||||
#![allow(clippy::all)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use frame_support::{
|
||||
traits::Get,
|
||||
weights::{constants::RocksDbWeight, Weight},
|
||||
};
|
||||
use sp_std::marker::PhantomData;
|
||||
|
||||
/// Weight functions needed for `pallet_bridge_relayers`.
|
||||
pub trait WeightInfo {
|
||||
fn claim_rewards() -> Weight;
|
||||
}
|
||||
|
||||
/// Weights for `pallet_bridge_relayers` using the Millau node and recommended hardware.
|
||||
pub struct MillauWeight<T>(PhantomData<T>);
|
||||
impl<T: frame_system::Config> WeightInfo for MillauWeight<T> {
|
||||
fn claim_rewards() -> Weight {
|
||||
(38_435_000 as Weight)
|
||||
.saturating_add(T::DbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(T::DbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility and tests
|
||||
impl WeightInfo for () {
|
||||
fn claim_rewards() -> Weight {
|
||||
(38_435_000 as Weight)
|
||||
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
|
||||
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
[package]
|
||||
name = "bp-relayers"
|
||||
description = "Primitives of relayers module."
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
||||
|
||||
[dependencies]
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
#bp-runtime = { path = "../runtime", default-features = false }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
#frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
#sp-core = { 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 }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.4"
|
||||
hex-literal = "0.3"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
# "bp-runtime/std",
|
||||
"frame-support/std",
|
||||
# "frame-system/std",
|
||||
# "scale-info/std",
|
||||
# "serde",
|
||||
# "sp-core/std",
|
||||
"sp-runtime/std",
|
||||
"sp-std/std",
|
||||
]
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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/>.
|
||||
|
||||
//! Primitives of messages module.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use sp_std::{fmt::Debug, marker::PhantomData};
|
||||
|
||||
/// Reward payment procedure.
|
||||
pub trait PaymentProcedure<Relayer, Reward> {
|
||||
/// Error that may be returned by the procedure.
|
||||
type Error: Debug;
|
||||
|
||||
/// Pay reward to the relayer.
|
||||
fn pay_reward(relayer: &Relayer, reward: Reward) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
/// Reward payment procedure that is simply minting given amount of tokens.
|
||||
pub struct MintReward<T, Relayer>(PhantomData<(T, Relayer)>);
|
||||
|
||||
impl<T, Relayer> PaymentProcedure<Relayer, T::Balance> for MintReward<T, Relayer>
|
||||
where
|
||||
T: frame_support::traits::fungible::Mutate<Relayer>,
|
||||
{
|
||||
type Error = sp_runtime::DispatchError;
|
||||
|
||||
fn pay_reward(relayer: &Relayer, reward: T::Balance) -> Result<(), Self::Error> {
|
||||
T::mint_into(relayer, reward)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user