diff --git a/state-chain/cf-integration-tests/src/authorities.rs b/state-chain/cf-integration-tests/src/authorities.rs index 8c4b43df33..fd3e46844f 100644 --- a/state-chain/cf-integration-tests/src/authorities.rs +++ b/state-chain/cf-integration-tests/src/authorities.rs @@ -12,7 +12,7 @@ use cf_traits::{AsyncResult, EpochInfo, SafeMode, VaultRotator, VaultStatus}; use pallet_cf_environment::SafeModeUpdate; use pallet_cf_validator::{CurrentRotationPhase, RotationPhase}; use state_chain_runtime::{ - chainflip::RuntimeSafeMode, Environment, EthereumVault, Flip, Runtime, Validator, + safe_mode::RuntimeSafeMode, Environment, EthereumVault, Flip, Runtime, Validator, }; // Helper function that creates a network, funds backup nodes, and have them join the auction. diff --git a/state-chain/runtime/src/chainflip.rs b/state-chain/runtime/src/chainflip.rs index a5870594b5..da72bffb9a 100644 --- a/state-chain/runtime/src/chainflip.rs +++ b/state-chain/runtime/src/chainflip.rs @@ -44,10 +44,10 @@ use cf_chains::{ }; use cf_primitives::{chains::assets, AccountRole, Asset, BasisPoints, ChannelId, EgressId}; use cf_traits::{ - impl_runtime_safe_mode, AccountRoleRegistry, BlockEmissions, BroadcastAnyChainGovKey, - Broadcaster, CallDispatchFilter, Chainflip, CommKeyBroadcaster, DepositApi, DepositHandler, - EgressApi, EpochInfo, Heartbeat, Issuance, KeyProvider, OnBroadcastReady, QualifyNode, - RewardsDistribution, RuntimeUpgrade, VaultTransitionHandler, + AccountRoleRegistry, BlockEmissions, BroadcastAnyChainGovKey, Broadcaster, Chainflip, + CommKeyBroadcaster, DepositApi, DepositHandler, EgressApi, EpochInfo, Heartbeat, Issuance, + KeyProvider, OnBroadcastReady, QualifyNode, RewardsDistribution, RuntimeUpgrade, + VaultTransitionHandler, }; use codec::{Decode, Encode}; use frame_support::{ @@ -73,21 +73,6 @@ impl Chainflip for Runtime { type AccountRoleRegistry = AccountRoles; type FundingInfo = Flip; } - -impl_runtime_safe_mode! { - RuntimeSafeMode, - pallet_cf_environment::RuntimeSafeMode, - emissions: pallet_cf_emissions::PalletSafeMode, - funding: pallet_cf_funding::PalletSafeMode, - swapping: pallet_cf_swapping::PalletSafeMode, - liquidity_provider: pallet_cf_lp::PalletSafeMode, - validator: pallet_cf_validator::PalletSafeMode, - pools: pallet_cf_pools::PalletSafeMode, - reputation: pallet_cf_reputation::PalletSafeMode, - vault: pallet_cf_vaults::PalletSafeMode, - witnesser: pallet_cf_witnesser::PalletSafeMode, - broadcast: pallet_cf_broadcast::PalletSafeMode, -} struct BackupNodeEmissions; impl RewardsDistribution for BackupNodeEmissions { @@ -623,103 +608,3 @@ impl QualifyNode<::ValidatorId> for ValidatorRoleQualifica AccountRoles::has_account_role(id, AccountRole::Validator) } } - -/// Contains permissions for different Runtime calls. -/// This is done through the SafeMode::CodeAmber of the Witnesser pallet. -/// Only calls allowed here can be dispatched with Witnesser origin. -#[derive( - codec::Encode, - codec::Decode, - codec::MaxEncodedLen, - scale_info::TypeInfo, - Default, - Copy, - Clone, - PartialEq, - Eq, - frame_support::RuntimeDebug, -)] -pub struct WitnesserCallPermission { - // Non-instantiable pallets - pub governance: bool, - pub funding: bool, - pub swapping: bool, - - // Ethereum pallets - pub ethereum_broadcast: bool, - pub ethereum_chain_tracking: bool, - pub ethereum_ingress_egress: bool, - pub ethereum_vault: bool, - - // Polkadot pallets - pub polkadot_broadcast: bool, - pub polkadot_chain_tracking: bool, - pub polkadot_ingress_egress: bool, - pub polkadot_vault: bool, - - // Bitcoin pallets - pub bitcoin_broadcast: bool, - pub bitcoin_chain_tracking: bool, - pub bitcoin_ingress_egress: bool, - pub bitcoin_vault: bool, -} - -impl WitnesserCallPermission { - pub fn allow_all() -> Self { - WitnesserCallPermission { - governance: true, - funding: true, - swapping: true, - ethereum_broadcast: true, - ethereum_chain_tracking: true, - ethereum_ingress_egress: true, - ethereum_vault: true, - polkadot_broadcast: true, - polkadot_chain_tracking: true, - polkadot_ingress_egress: true, - polkadot_vault: true, - bitcoin_broadcast: true, - bitcoin_chain_tracking: true, - bitcoin_ingress_egress: true, - bitcoin_vault: true, - } - } -} - -pub struct ChainflipCallFilter; -impl CallDispatchFilter for ChainflipCallFilter { - fn should_dispatch(call: &RuntimeCall) -> bool { - match , - >>::get() - { - pallet_cf_witnesser::PalletSafeMode::CodeGreen => true, - pallet_cf_witnesser::PalletSafeMode::CodeRed => false, - pallet_cf_witnesser::PalletSafeMode::CodeAmber(permission) => match call { - RuntimeCall::Governance(..) => permission.governance, - RuntimeCall::Funding(..) => permission.funding, - RuntimeCall::Swapping(..) => permission.swapping, - - RuntimeCall::EthereumBroadcaster(..) => permission.ethereum_broadcast, - RuntimeCall::EthereumChainTracking(..) => permission.ethereum_chain_tracking, - RuntimeCall::EthereumIngressEgress(..) => permission.ethereum_ingress_egress, - RuntimeCall::EthereumVault(..) => permission.ethereum_vault, - - RuntimeCall::PolkadotBroadcaster(..) => permission.polkadot_broadcast, - RuntimeCall::PolkadotChainTracking(..) => permission.polkadot_chain_tracking, - RuntimeCall::PolkadotIngressEgress(..) => permission.polkadot_ingress_egress, - RuntimeCall::PolkadotVault(..) => permission.polkadot_vault, - - RuntimeCall::BitcoinBroadcaster(..) => permission.bitcoin_broadcast, - RuntimeCall::BitcoinChainTracking(..) => permission.bitcoin_chain_tracking, - RuntimeCall::BitcoinIngressEgress(..) => permission.bitcoin_ingress_egress, - RuntimeCall::BitcoinVault(..) => permission.bitcoin_vault, - - _ => { - log::warn!("All witnesser calls must be controllable through `WitnesserCallPermission` during SafeMode: CodeAmber. Call: {:?}", call); - false - }, - }, - } - } -} diff --git a/state-chain/runtime/src/lib.rs b/state-chain/runtime/src/lib.rs index 79b6cfaf6c..0f0996c70f 100644 --- a/state-chain/runtime/src/lib.rs +++ b/state-chain/runtime/src/lib.rs @@ -4,6 +4,7 @@ pub mod chainflip; pub mod constants; pub mod runtime_apis; +pub mod safe_mode; #[cfg(feature = "std")] pub mod test_runner; mod weights; @@ -86,9 +87,10 @@ pub use chainflip::chain_instances::*; use chainflip::{ all_vaults_rotator::AllVaultRotator, epoch_transition::ChainflipEpochTransitions, BroadcastReadyProvider, BtcEnvironment, BtcVaultTransitionHandler, ChainAddressConverter, - ChainflipCallFilter, ChainflipHeartbeat, DotEnvironment, DotVaultTransitionHandler, - EthEnvironment, EthVaultTransitionHandler, TokenholderGovernanceBroadcaster, + ChainflipHeartbeat, DotEnvironment, DotVaultTransitionHandler, EthEnvironment, + EthVaultTransitionHandler, TokenholderGovernanceBroadcaster, }; +use safe_mode::{ChainflipCallFilter, RuntimeSafeMode, WitnesserCallPermission}; use constants::common::*; use pallet_cf_flip::{Bonder, FlipSlasher}; @@ -175,7 +177,7 @@ impl pallet_cf_validator::Config for Runtime { ); type OffenceReporter = Reputation; type Bonder = Bonder; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type ReputationResetter = Reputation; } @@ -206,7 +208,7 @@ impl pallet_cf_environment::Config for Runtime { type BitcoinVaultKeyWitnessedHandler = BitcoinVault; type BitcoinNetwork = BitcoinNetworkParam; type BitcoinFeeInfo = chainflip::BitcoinFeeGetter; - type RuntimeSafeMode = chainflip::RuntimeSafeMode; + type RuntimeSafeMode = RuntimeSafeMode; type CurrentCompatibilityVersion = CurrentCompatibilityVersion; type WeightInfo = pallet_cf_environment::weights::PalletWeight; } @@ -217,7 +219,7 @@ impl pallet_cf_swapping::Config for Runtime { type EgressHandler = chainflip::AnyChainIngressEgressHandler; type SwappingApi = LiquidityPools; type AddressConverter = ChainAddressConverter; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type WeightInfo = pallet_cf_swapping::weights::PalletWeight; } @@ -235,7 +237,7 @@ impl pallet_cf_vaults::Config for Runtime { type OffenceReporter = Reputation; type WeightInfo = pallet_cf_vaults::weights::PalletWeight; type ChainTracking = EthereumChainTracking; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type Slasher = FlipSlasher; } @@ -253,7 +255,7 @@ impl pallet_cf_vaults::Config for Runtime { type OffenceReporter = Reputation; type WeightInfo = pallet_cf_vaults::weights::PalletWeight; type ChainTracking = PolkadotChainTracking; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type Slasher = FlipSlasher; } @@ -271,7 +273,7 @@ impl pallet_cf_vaults::Config for Runtime { type OffenceReporter = Reputation; type WeightInfo = pallet_cf_vaults::weights::PalletWeight; type ChainTracking = BitcoinChainTracking; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type Slasher = FlipSlasher; } @@ -333,7 +335,7 @@ impl pallet_cf_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type LpBalance = LiquidityProvider; type NetworkFee = NetworkFee; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type WeightInfo = (); } @@ -342,7 +344,7 @@ impl pallet_cf_lp::Config for Runtime { type DepositHandler = chainflip::AnyChainIngressEgressHandler; type EgressHandler = chainflip::AnyChainIngressEgressHandler; type AddressConverter = ChainAddressConverter; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type WeightInfo = pallet_cf_lp::weights::PalletWeight; } @@ -519,8 +521,8 @@ impl pallet_cf_witnesser::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; - type SafeMode = chainflip::RuntimeSafeMode; - type CallPermission = chainflip::WitnesserCallPermission; + type SafeMode = RuntimeSafeMode; + type CallPermission = WitnesserCallPermission; type CallDispatchFilter = ChainflipCallFilter; type WeightInfo = pallet_cf_witnesser::weights::PalletWeight; } @@ -535,7 +537,7 @@ impl pallet_cf_funding::Config for Runtime { pallet_cf_threshold_signature::EnsureThresholdSigned; type RegisterRedemption = EthereumApi; type TimeSource = Timestamp; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type WeightInfo = pallet_cf_funding::weights::PalletWeight; } @@ -575,7 +577,7 @@ impl pallet_cf_emissions::Config for Runtime { type EthEnvironment = EthEnvironment; type FlipToBurn = LiquidityPools; type EgressHandler = chainflip::AnyChainIngressEgressHandler; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type WeightInfo = pallet_cf_emissions::weights::PalletWeight; } @@ -607,7 +609,7 @@ impl pallet_cf_reputation::Config for Runtime { type Slasher = FlipSlasher; type WeightInfo = pallet_cf_reputation::weights::PalletWeight; type MaximumAccruableReputation = MaximumAccruableReputation; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; } impl pallet_cf_threshold_signature::Config for Runtime { @@ -669,7 +671,7 @@ impl pallet_cf_broadcast::Config for Runtime { type BroadcastReadyProvider = BroadcastReadyProvider; type BroadcastTimeout = ConstU32<{ 10 * MINUTES }>; type WeightInfo = pallet_cf_broadcast::weights::PalletWeight; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type SafeModeBlockMargin = ConstU32<10>; type KeyProvider = EthereumVault; } @@ -691,7 +693,7 @@ impl pallet_cf_broadcast::Config for Runtime { type BroadcastReadyProvider = BroadcastReadyProvider; type BroadcastTimeout = ConstU32<{ 10 * MINUTES }>; type WeightInfo = pallet_cf_broadcast::weights::PalletWeight; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type SafeModeBlockMargin = ConstU32<10>; type KeyProvider = PolkadotVault; } @@ -713,7 +715,7 @@ impl pallet_cf_broadcast::Config for Runtime { type BroadcastReadyProvider = BroadcastReadyProvider; type BroadcastTimeout = ConstU32<{ 90 * MINUTES }>; type WeightInfo = pallet_cf_broadcast::weights::PalletWeight; - type SafeMode = chainflip::RuntimeSafeMode; + type SafeMode = RuntimeSafeMode; type SafeModeBlockMargin = ConstU32<10>; type KeyProvider = BitcoinVault; } diff --git a/state-chain/runtime/src/safe_mode.rs b/state-chain/runtime/src/safe_mode.rs new file mode 100644 index 0000000000..0e8114f5c7 --- /dev/null +++ b/state-chain/runtime/src/safe_mode.rs @@ -0,0 +1,122 @@ +//! For filtering runtime calls and other related utilities. + +use crate::{Runtime, RuntimeCall}; +use cf_traits::{impl_runtime_safe_mode, CallDispatchFilter}; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::traits::Get; +use scale_info::TypeInfo; + +impl_runtime_safe_mode! { + RuntimeSafeMode, + pallet_cf_environment::RuntimeSafeMode, + emissions: pallet_cf_emissions::PalletSafeMode, + funding: pallet_cf_funding::PalletSafeMode, + swapping: pallet_cf_swapping::PalletSafeMode, + liquidity_provider: pallet_cf_lp::PalletSafeMode, + validator: pallet_cf_validator::PalletSafeMode, + pools: pallet_cf_pools::PalletSafeMode, + reputation: pallet_cf_reputation::PalletSafeMode, + vault: pallet_cf_vaults::PalletSafeMode, + witnesser: pallet_cf_witnesser::PalletSafeMode, + broadcast: pallet_cf_broadcast::PalletSafeMode, +} + +/// Contains permissions for different Runtime calls. +/// This is done through the SafeMode::CodeAmber of the Witnesser pallet. +/// Only calls allowed here can be dispatched with Witnesser origin. +#[derive( + Encode, + Decode, + MaxEncodedLen, + TypeInfo, + Default, + Copy, + Clone, + PartialEq, + Eq, + frame_support::RuntimeDebug, +)] +pub struct WitnesserCallPermission { + // Non-instantiable pallets + pub governance: bool, + pub funding: bool, + pub swapping: bool, + + // Ethereum pallets + pub ethereum_broadcast: bool, + pub ethereum_chain_tracking: bool, + pub ethereum_ingress_egress: bool, + pub ethereum_vault: bool, + + // Polkadot pallets + pub polkadot_broadcast: bool, + pub polkadot_chain_tracking: bool, + pub polkadot_ingress_egress: bool, + pub polkadot_vault: bool, + + // Bitcoin pallets + pub bitcoin_broadcast: bool, + pub bitcoin_chain_tracking: bool, + pub bitcoin_ingress_egress: bool, + pub bitcoin_vault: bool, +} + +impl WitnesserCallPermission { + pub fn allow_all() -> Self { + WitnesserCallPermission { + governance: true, + funding: true, + swapping: true, + ethereum_broadcast: true, + ethereum_chain_tracking: true, + ethereum_ingress_egress: true, + ethereum_vault: true, + polkadot_broadcast: true, + polkadot_chain_tracking: true, + polkadot_ingress_egress: true, + polkadot_vault: true, + bitcoin_broadcast: true, + bitcoin_chain_tracking: true, + bitcoin_ingress_egress: true, + bitcoin_vault: true, + } + } +} + +pub struct ChainflipCallFilter; +impl CallDispatchFilter for ChainflipCallFilter { + fn should_dispatch(call: &RuntimeCall) -> bool { + match , + >>::get() + { + pallet_cf_witnesser::PalletSafeMode::CodeGreen => true, + pallet_cf_witnesser::PalletSafeMode::CodeRed => false, + pallet_cf_witnesser::PalletSafeMode::CodeAmber(permission) => match call { + RuntimeCall::Governance(..) => permission.governance, + RuntimeCall::Funding(..) => permission.funding, + RuntimeCall::Swapping(..) => permission.swapping, + + RuntimeCall::EthereumBroadcaster(..) => permission.ethereum_broadcast, + RuntimeCall::EthereumChainTracking(..) => permission.ethereum_chain_tracking, + RuntimeCall::EthereumIngressEgress(..) => permission.ethereum_ingress_egress, + RuntimeCall::EthereumVault(..) => permission.ethereum_vault, + + RuntimeCall::PolkadotBroadcaster(..) => permission.polkadot_broadcast, + RuntimeCall::PolkadotChainTracking(..) => permission.polkadot_chain_tracking, + RuntimeCall::PolkadotIngressEgress(..) => permission.polkadot_ingress_egress, + RuntimeCall::PolkadotVault(..) => permission.polkadot_vault, + + RuntimeCall::BitcoinBroadcaster(..) => permission.bitcoin_broadcast, + RuntimeCall::BitcoinChainTracking(..) => permission.bitcoin_chain_tracking, + RuntimeCall::BitcoinIngressEgress(..) => permission.bitcoin_ingress_egress, + RuntimeCall::BitcoinVault(..) => permission.bitcoin_vault, + + _ => { + log::warn!("All witnesser calls must be controllable through `WitnesserCallPermission` during SafeMode: CodeAmber. Call: {:?}", call); + false + }, + }, + } + } +}