diff --git a/Cargo.lock b/Cargo.lock index 9b1e74b6c..671d39be1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -632,6 +632,20 @@ dependencies = [ "sp-version 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", ] +[[package]] +name = "bp-crab-parachain" +version = "0.1.0" +dependencies = [ + "bp-darwinia-core", + "bp-messages 0.1.0", + "bp-runtime 0.1.0", + "frame-support 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", + "sp-api 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", + "sp-runtime 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", + "sp-std 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", + "sp-version 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", +] + [[package]] name = "bp-darwinia" version = "0.1.0" @@ -7254,6 +7268,28 @@ dependencies = [ "sp-runtime 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", ] +[[package]] +name = "relay-crab-parachain-client" +version = "0.1.0" +dependencies = [ + "bp-crab", + "bp-crab-parachain", + "bp-darwinia-core", + "bp-header-chain", + "bp-message-dispatch 0.1.0", + "bp-messages 0.1.0", + "bp-runtime 0.1.0", + "bridge-runtime-common", + "frame-support 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", + "pallet-bridge-dispatch", + "parity-scale-codec", + "relay-substrate-client", + "relay-utils", + "scale-info", + "sp-core 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", + "sp-runtime 4.0.0-dev (git+https://github.com/darwinia-network/substrate?branch=darwinia-v0.12.2)", +] + [[package]] name = "relay-darwinia-client" version = "0.1.0" diff --git a/bin/runtime-common/src/lanes.rs b/bin/runtime-common/src/lanes.rs index f1d681902..901950b69 100644 --- a/bin/runtime-common/src/lanes.rs +++ b/bin/runtime-common/src/lanes.rs @@ -8,3 +8,6 @@ pub const PANGORO_PANGOLIN_LANE: LaneId = *b"roli"; /// Identifier of bridge between Pangolin and Pangolin Parachain. pub const PANGOLIN_PANGOLIN_PARACHAIN_LANE: LaneId = *b"pali"; + +/// Identifier of bridge between Crab and Crab Parachain. +pub const CRAB_CRAB_PARACHAIN_LANE: LaneId = *b"pacr"; diff --git a/primitives/chain-crab-parachain/Cargo.toml b/primitives/chain-crab-parachain/Cargo.toml new file mode 100644 index 000000000..a10b65985 --- /dev/null +++ b/primitives/chain-crab-parachain/Cargo.toml @@ -0,0 +1,34 @@ +[package] +authors = ["Darwinia Network "] +description = "Primitives of Crab Parachain runtime." +edition = "2021" +license = "GPL-3.0" +name = "bp-crab-parachain" +version = "0.1.0" + +[dependencies] +# darwinia-network +bp-darwinia-core = { default-features = false, path = "../darwinia-core" } +# paritytech +bp-messages = { default-features = false, path = "../messages" } +bp-runtime = { default-features = false, path = "../runtime" } +frame-support = { default-features = false, git = "https://github.com/darwinia-network/substrate", branch = "darwinia-v0.12.2" } +sp-api = { default-features = false, git = "https://github.com/darwinia-network/substrate", branch = "darwinia-v0.12.2" } +sp-runtime = { default-features = false, git = "https://github.com/darwinia-network/substrate", branch = "darwinia-v0.12.2" } +sp-std = { default-features = false, git = "https://github.com/darwinia-network/substrate", branch = "darwinia-v0.12.2" } +sp-version = { default-features = false, git = "https://github.com/darwinia-network/substrate", branch = "darwinia-v0.12.2" } + +[features] +default = ["std"] +std = [ + # darwinia-network + "bp-darwinia-core/std", + # paritytech + "bp-messages/std", + "bp-runtime/std", + "frame-support/std", + "sp-api/std", + "sp-runtime/std", + "sp-std/std", + "sp-version/std", +] diff --git a/primitives/chain-crab-parachain/src/lib.rs b/primitives/chain-crab-parachain/src/lib.rs new file mode 100644 index 000000000..efb7b5ac1 --- /dev/null +++ b/primitives/chain-crab-parachain/src/lib.rs @@ -0,0 +1,121 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2022 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia 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. +// +// Darwinia 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 Darwinia. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +mod copy_paste_from_darwinia { + // --- darwinia-network --- + use bp_darwinia_core::*; + // --- paritytech --- + use sp_version::RuntimeVersion; + + pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: sp_runtime::create_runtime_str!("Crab Parachain"), + impl_name: sp_runtime::create_runtime_str!("Darwinia Crab Parachain"), + authoring_version: 1, + spec_version: 4, + impl_version: 1, + apis: sp_version::create_apis_vec![[]], + transaction_version: 1, + }; + + pub const EXISTENTIAL_DEPOSIT: Balance = 0; +} +pub use copy_paste_from_darwinia::*; + +pub use bp_darwinia_core::*; + +// --- paritytech --- +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use frame_support::Parameter; +use sp_std::prelude::*; + +/// CrabParachain Chain. +pub type CrabParachain = DarwiniaLike; + +/// Name of the With-CrabParachain messages pallet instance that is deployed at bridged chains. +pub const WITH_CRAB_PARACHAIN_MESSAGES_PALLET_NAME: &str = "BridgeCrabParachainMessages"; + +/// Name of the `CrabParachainFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_CRAB_PARACHAIN_HEADER_METHOD: &str = + "CrabParachainFinalityApi_best_finalized"; + +/// Name of the `ToCrabParachainOutboundLaneApi::message_details` runtime method. +pub const TO_CRAB_PARACHAIN_MESSAGE_DETAILS_METHOD: &str = + "ToCrabParachainOutboundLaneApi_message_details"; +/// Name of the `ToCrabParachainOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_CRAB_PARACHAIN_LATEST_RECEIVED_NONCE_METHOD: &str = + "ToCrabParachainOutboundLaneApi_latest_received_nonce"; +/// Name of the `ToCrabParachainOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_CRAB_PARACHAIN_LATEST_GENERATED_NONCE_METHOD: &str = + "ToCrabParachainOutboundLaneApi_latest_generated_nonce"; + +/// Name of the `FromCrabParachainInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_CRAB_PARACHAIN_LATEST_RECEIVED_NONCE_METHOD: &str = + "FromCrabParachainInboundLaneApi_latest_received_nonce"; +/// Name of the `FromCrabParachainInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_CRAB_PARACHAIN_LATEST_CONFIRMED_NONCE_METHOD: &str = + "FromCrabParachainInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromCrabParachainInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_CRAB_PARACHAIN_UNREWARDED_RELAYERS_STATE: &str = + "FromCrabParachainInboundLaneApi_unrewarded_relayers_state"; + +sp_api::decl_runtime_apis! { + /// API for querying information about the finalized CrabParachain headers. + /// + /// This API is implemented by runtimes that are bridging with the CrabParachain chain, not the + /// CrabParachain runtime itself. + pub trait CrabParachainFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + } + + /// Outbound message lane API for messages that are sent to CrabParachain chain. + /// + /// This API is implemented by runtimes that are sending messages to CrabParachain chain, not the + /// CrabParachain runtime itself. + pub trait ToCrabParachainOutboundLaneApi { + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn message_details( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by CrabParachain chain. + /// + /// This API is implemented by runtimes that are receiving messages from CrabParachain chain, not the + /// CrabParachain runtime itself. + pub trait FromCrabParachainInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; + } +} diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 2d798504b..279453603 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -115,6 +115,8 @@ pub const FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD: &str = pub const FROM_KUSAMA_UNREWARDED_RELAYERS_STATE: &str = "FromKusamaInboundLaneApi_unrewarded_relayers_state"; +pub const PARAS_PALLET_NAME: &str = "Paras"; + sp_api::decl_runtime_apis! { /// API for querying information about the finalized Kusama headers. /// diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 08890d000..22ad9168e 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -75,6 +75,9 @@ pub const PANGOLIN_CHAIN_ID: ChainId = *b"pagl"; /// Bridge-with-PangolinParachain instance id. pub const PANGOLIN_PARACHAIN_CHAIN_ID: ChainId = *b"pglp"; +/// Bridge-with-CrabParachain instance id. +pub const CRAB_PARACHAIN_CHAIN_ID: ChainId = *b"crap"; + /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch"; diff --git a/relays/client-crab-parachain/Cargo.toml b/relays/client-crab-parachain/Cargo.toml new file mode 100644 index 000000000..72864b7a4 --- /dev/null +++ b/relays/client-crab-parachain/Cargo.toml @@ -0,0 +1,29 @@ +[package] +authors = ["Darwinia Network "] +edition = "2021" +license = "GPL-3.0" +name = "relay-crab-parachain-client" +version = "0.1.0" + + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.2.0" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } +scale-info = { version = "1.0", features = ["derive"] } + +bp-header-chain = { path = "../../primitives/header-chain" } +bp-message-dispatch = { path = "../../primitives/message-dispatch" } +bp-messages = { path = "../../primitives/messages" } +bp-runtime = { path = "../../primitives/runtime" } +bridge-runtime-common = { path = "../../bin/runtime-common" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } + +bp-darwinia-core = { path = "../../primitives/darwinia-core" } +bp-crab = { path = "../../primitives/chain-crab" } +bp-crab-parachain = { path = "../../primitives/chain-crab-parachain" } + +## Substrate Dependencies +frame-support = { git = "https://github.com/darwinia-network/substrate", branch = "darwinia-v0.12.2" } +sp-core = { git = "https://github.com/darwinia-network/substrate", branch = "darwinia-v0.12.2" } +sp-runtime = { git = "https://github.com/darwinia-network/substrate", branch = "darwinia-v0.12.2" } diff --git a/relays/client-crab-parachain/src/lib.rs b/relays/client-crab-parachain/src/lib.rs new file mode 100644 index 000000000..a43e9cec5 --- /dev/null +++ b/relays/client-crab-parachain/src/lib.rs @@ -0,0 +1,140 @@ +use std::time::Duration; + +use codec::Encode; +use frame_support::weights::{IdentityFee, Weight}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; + +use bp_messages::MessageNonce; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, + UnsignedTransaction, +}; + +pub mod runtime; + +/// CrabParachain header id. +pub type HeaderId = + relay_utils::HeaderId; + +/// CrabParachain chain definition. +#[derive(Debug, Clone, Copy)] +pub struct CrabParachainChain; + +impl ChainBase for CrabParachainChain { + type BlockNumber = bp_crab_parachain::BlockNumber; + type Hash = bp_crab_parachain::Hash; + type Hasher = bp_crab_parachain::Hashing; + type Header = bp_crab_parachain::Header; + + type AccountId = bp_crab_parachain::AccountId; + type Balance = bp_crab_parachain::Balance; + type Index = bp_crab_parachain::Nonce; + type Signature = bp_crab_parachain::Signature; + + fn max_extrinsic_size() -> u32 { + bp_crab_parachain::CrabParachain::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_crab_parachain::CrabParachain::max_extrinsic_weight() + } +} + +impl Chain for CrabParachainChain { + const NAME: &'static str = "CrabParachain"; + const TOKEN_ID: Option<&'static str> = Some("polkadot"); + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_crab_parachain::BEST_FINALIZED_CRAB_PARACHAIN_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = + Duration::from_millis(bp_crab_parachain::MILLISECS_PER_BLOCK); + const STORAGE_PROOF_OVERHEAD: u32 = bp_crab_parachain::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = + bp_crab_parachain::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; + + type SignedBlock = bp_crab_parachain::SignedBlock; + type Call = crate::runtime::Call; + type WeightToFee = IdentityFee; +} + +impl ChainWithMessages for CrabParachainChain { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_crab_parachain::WITH_CRAB_PARACHAIN_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_crab_parachain::TO_CRAB_PARACHAIN_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_crab_parachain::TO_CRAB_PARACHAIN_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_crab_parachain::TO_CRAB_PARACHAIN_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_crab_parachain::FROM_CRAB_PARACHAIN_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_crab_parachain::FROM_CRAB_PARACHAIN_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_crab_parachain::FROM_CRAB_PARACHAIN_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_crab_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_crab_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_crab_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + +impl ChainWithBalances for CrabParachainChain { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + StorageKey(bp_crab_parachain::account_info_storage_key(account_id)) + } +} + +impl TransactionSignScheme for CrabParachainChain { + type Chain = CrabParachainChain; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = crate::runtime::UncheckedExtrinsic; + + fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + let raw_payload = SignedPayload::new( + param.unsigned.call.clone(), + bp_crab_parachain::SignedExtensions::new( + param.spec_version, + param.transaction_version, + param.era, + param.genesis_hash, + param.unsigned.nonce, + param.unsigned.tip, + ), + ) + .expect("SignedExtension never fails."); + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + bp_crab_parachain::UncheckedExtrinsic::new_signed( + call, + sp_runtime::MultiAddress::Id(signer.into_account()), + signature.into(), + extra, + ) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| { + let account_id: bp_crab_parachain::AccountId = + (*signer.public().as_array_ref()).into(); + *address == bp_crab_parachain::Address::from(account_id) + }) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) + } +} diff --git a/relays/client-crab-parachain/src/runtime.rs b/relays/client-crab-parachain/src/runtime.rs new file mode 100644 index 000000000..9d35a765e --- /dev/null +++ b/relays/client-crab-parachain/src/runtime.rs @@ -0,0 +1,128 @@ +use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; +use scale_info::TypeInfo; +use sp_runtime::FixedU128; + +use bp_darwinia_core::DarwiniaLike; +use bp_messages::{LaneId, UnrewardedRelayersState}; +use bp_crab_parachain::Balance; +use bp_runtime::Chain; + +/// Unchecked crab extrinsic. +pub type UncheckedExtrinsic = bp_crab_parachain::UncheckedExtrinsic; + +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// System pallet. + #[codec(index = 0)] + System(SystemCall), + /// Balances pallet. + #[codec(index = 5)] + Balances(BalancesCall), + /// Bridge pangoro grandpa pallet. + #[codec(index = 20)] + BridgeCrabGrandpa(BridgeCrabGrandpaCall), + /// Bridge pangoro messages pallet + #[codec(index = 21)] + BridgeCrabMessages(BridgeCrabMessagesCall), + /// Feemarket pallet + #[codec(index = 23)] + CrabFeemarket(FeemarketCall), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + #[codec(index = 1)] + remark(Vec), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BalancesCall { + #[codec(index = 0)] + transfer(bp_crab_parachain::Address, Compact), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeCrabGrandpaCall { + #[codec(index = 0)] + submit_finality_proof( + Box<::Header>, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeCrabMessagesCall { + #[codec(index = 2)] + update_pallet_parameter(BridgePolkadotMessagesParameter), + #[codec(index = 3)] + send_message( + LaneId, + bp_message_dispatch::MessagePayload< + bp_crab_parachain::AccountId, + bp_crab::AccountId, + bp_crab::AccountPublic, + Vec, + >, + bp_crab_parachain::Balance, + ), + #[codec(index = 5)] + receive_messages_proof( + bp_crab::AccountId, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, + u32, + Weight, + ), + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< + bp_crab::Hash, + >, + UnrewardedRelayersState, + ), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum BridgePolkadotMessagesParameter { + #[codec(index = 0)] + PolkadotToKusamaConversionRate(FixedU128), +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} + +/// Feemarket call +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum FeemarketCall { + #[codec(index = 0)] + enroll_and_lock_collateral( + bp_crab_parachain::Balance, + Option, + ), + #[codec(index = 1)] + update_locked_collateral(bp_crab_parachain::Balance), + #[codec(index = 2)] + update_relay_fee(bp_crab_parachain::Balance), + #[codec(index = 3)] + cancel_enrollment(), + #[codec(index = 4)] + set_slash_protect(bp_crab_parachain::Balance), + #[codec(index = 5)] + set_assigned_relayers_number(u32), +}