diff --git a/bridges/bin/millau/runtime/Cargo.toml b/bridges/bin/millau/runtime/Cargo.toml index 80858b2e31eb5d899f6150e0f0435fcf408e799d..33bdcca35cf761732320259c03a74c4aabdc1d9a 100644 --- a/bridges/bin/millau/runtime/Cargo.toml +++ b/bridges/bin/millau/runtime/Cargo.toml @@ -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", diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 4ee80e9e124d311bb9b598966bcf458d62c3595e..36ce83049d1c5ba52d1cafa791d7ad5736181d49 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -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) } diff --git a/bridges/bin/rialto-parachain/runtime/Cargo.toml b/bridges/bin/rialto-parachain/runtime/Cargo.toml index ac1c1cf3d568d29af3972f3525fc4779ea601e62..6c3d838196a42cb228e2b954b1703f2f83758175 100644 --- a/bridges/bin/rialto-parachain/runtime/Cargo.toml +++ b/bridges/bin/rialto-parachain/runtime/Cargo.toml @@ -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", diff --git a/bridges/bin/rialto-parachain/runtime/src/lib.rs b/bridges/bin/rialto-parachain/runtime/src/lib.rs index f2463b5e06f517ccf6e8f5a539c211e9405c82ec..c52504c1950e50e468fce26fa5651636a817639d 100644 --- a/bridges/bin/rialto-parachain/runtime/src/lib.rs +++ b/bridges/bin/rialto-parachain/runtime/src/lib.rs @@ -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>}, } diff --git a/bridges/bin/rialto/runtime/Cargo.toml b/bridges/bin/rialto/runtime/Cargo.toml index ff3eb703ff35876a22992f8b5b962a322860c657..a29560a65d9a0dc8baca434c849a948bb49cf0d2 100644 --- a/bridges/bin/rialto/runtime/Cargo.toml +++ b/bridges/bin/rialto/runtime/Cargo.toml @@ -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", diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index e06fdffe889099fd89a902b76a372f12fda92bf9..f0bc0982e69cb16af2d60de4cfe97b801753e8d3 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -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>}, diff --git a/bridges/modules/grandpa/src/weights.rs b/bridges/modules/grandpa/src/weights.rs index d17fee6ceda86bb21509b543f32571f1380bf4be..f23a2ac190397427ea390113e1f396029b877b71 100644 --- a/bridges/modules/grandpa/src/weights.rs +++ b/bridges/modules/grandpa/src/weights.rs @@ -40,6 +40,7 @@ #![allow(clippy::all)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{ traits::Get, diff --git a/bridges/modules/messages/src/weights.rs b/bridges/modules/messages/src/weights.rs index 6db9ad5c44279f8ece61a40b9c9eee801ed61f11..3f9ea8bbb16d53d5af76f6948e019981cc9babbe 100644 --- a/bridges/modules/messages/src/weights.rs +++ b/bridges/modules/messages/src/weights.rs @@ -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)) } } diff --git a/bridges/modules/parachains/src/weights.rs b/bridges/modules/parachains/src/weights.rs index bf7384b814689b308fbdf8eb37071b8653c6e1a7..b96e24752d5128ed49764958e78ac9c71ca94d9f 100644 --- a/bridges/modules/parachains/src/weights.rs +++ b/bridges/modules/parachains/src/weights.rs @@ -40,6 +40,7 @@ #![allow(clippy::all)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{ traits::Get, diff --git a/bridges/modules/relayers/Cargo.toml b/bridges/modules/relayers/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..ef689f55918b27c571979b044b2e35035dcacf81 --- /dev/null +++ b/bridges/modules/relayers/Cargo.toml @@ -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", +] diff --git a/bridges/modules/relayers/src/benchmarking.rs b/bridges/modules/relayers/src/benchmarking.rs new file mode 100644 index 0000000000000000000000000000000000000000..706454e0497dd908332c2878c0224fa1ec14b137 --- /dev/null +++ b/bridges/modules/relayers/src/benchmarking.rs @@ -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 + } +} diff --git a/bridges/modules/relayers/src/lib.rs b/bridges/modules/relayers/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..596dd89f31339f3596bd0a2c0463b066e4802fec --- /dev/null +++ b/bridges/modules/relayers/src/lib.rs @@ -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); + }); + } +} diff --git a/bridges/modules/relayers/src/mock.rs b/bridges/modules/relayers/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..2ceabc6621fb3dd8e66a146f8eb5094a61c4bc55 --- /dev/null +++ b/bridges/modules/relayers/src/mock.rs @@ -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) +} diff --git a/bridges/modules/relayers/src/payment_adapter.rs b/bridges/modules/relayers/src/payment_adapter.rs new file mode 100644 index 0000000000000000000000000000000000000000..6aa1248959dca5eab76a414c51a39f83dc9f24ae --- /dev/null +++ b/bridges/modules/relayers/src/payment_adapter.rs @@ -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)); + }); + } +} diff --git a/bridges/modules/relayers/src/weights.rs b/bridges/modules/relayers/src/weights.rs new file mode 100644 index 0000000000000000000000000000000000000000..fd7efe940d45537e0ba5f31ebce169124d2de476 --- /dev/null +++ b/bridges/modules/relayers/src/weights.rs @@ -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)) + } +} diff --git a/bridges/primitives/relayers/Cargo.toml b/bridges/primitives/relayers/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..0d6d020a0997bd315b373c5fa2d39439e89382bb --- /dev/null +++ b/bridges/primitives/relayers/Cargo.toml @@ -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", +] diff --git a/bridges/primitives/relayers/src/lib.rs b/bridges/primitives/relayers/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d1c82d612e2e93b545cc2ec9bf8eef8b006243a3 --- /dev/null +++ b/bridges/primitives/relayers/src/lib.rs @@ -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) + } +}