From 41ce5b17384c343878896366920666404563fc3a Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Sun, 2 Jun 2024 19:58:29 -0400 Subject: [PATCH] Use the serai_abi::Call in the actual Transaction type We prior required they had the same encoding, yet this ensures they do by making them one and the same. This does require an large, ugly, From/TryInto block which is deemed preferable for moving this more and more into syntax (from semantics). Further improvements (notably re: Extra) is possible, and this already lets us strip some members from the Call enum. --- Cargo.lock | 1 + coordinator/src/tributary/scanner.rs | 8 +- substrate/abi/Cargo.toml | 50 ++- substrate/abi/src/babe.rs | 2 +- substrate/abi/src/coins.rs | 15 +- substrate/abi/src/dex.rs | 6 +- substrate/abi/src/grandpa.rs | 9 +- substrate/abi/src/in_instructions.rs | 6 +- substrate/abi/src/lib.rs | 27 +- substrate/abi/src/signals.rs | 6 +- substrate/abi/src/system.rs | 1 - substrate/abi/src/timestamp.rs | 8 +- substrate/abi/src/tx.rs | 183 +++++++++ substrate/abi/src/validator_sets.rs | 10 +- substrate/client/src/serai/mod.rs | 13 +- substrate/client/src/serai/validator_sets.rs | 5 +- .../client/tests/common/validator_sets.rs | 7 +- substrate/primitives/src/lib.rs | 3 - substrate/primitives/src/tx.rs | 124 ------ substrate/runtime/Cargo.toml | 3 + substrate/runtime/src/abi.rs | 363 ++++++++++++++++++ substrate/runtime/src/lib.rs | 36 +- substrate/validator-sets/pallet/src/lib.rs | 2 +- 23 files changed, 677 insertions(+), 211 deletions(-) create mode 100644 substrate/abi/src/tx.rs delete mode 100644 substrate/primitives/src/tx.rs create mode 100644 substrate/runtime/src/abi.rs diff --git a/Cargo.lock b/Cargo.lock index 0fc295479..e5cdebfbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8195,6 +8195,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "scale-info", + "serai-abi", "serai-coins-pallet", "serai-dex-pallet", "serai-in-instructions-pallet", diff --git a/coordinator/src/tributary/scanner.rs b/coordinator/src/tributary/scanner.rs index 25c8b5c20..9b56e0a0f 100644 --- a/coordinator/src/tributary/scanner.rs +++ b/coordinator/src/tributary/scanner.rs @@ -133,7 +133,13 @@ mod impl_pst_for_serai { key_pair: KeyPair, signature: Signature, ) { - let tx = SeraiValidatorSets::set_keys(set.network, removed, key_pair, signature); + // TODO: BoundedVec as an arg to avoid this expect + let tx = SeraiValidatorSets::set_keys( + set.network, + removed.try_into().expect("removing more than allowed"), + key_pair, + signature, + ); async fn check(serai: SeraiValidatorSets<'_>, set: ValidatorSet, (): ()) -> bool { if matches!(serai.keys(set).await, Ok(Some(_))) { log::info!("another coordinator set key pair for {:?}", set); diff --git a/substrate/abi/Cargo.toml b/substrate/abi/Cargo.toml index 3aac979ac..547761d88 100644 --- a/substrate/abi/Cargo.toml +++ b/substrate/abi/Cargo.toml @@ -16,27 +16,48 @@ rustdoc-args = ["--cfg", "docsrs"] workspace = true [dependencies] -scale = { package = "parity-scale-codec", version = "3", features = ["derive"] } -scale-info = { version = "2", features = ["derive"] } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2", default-features = false, features = ["derive"] } -borsh = { version = "1", features = ["derive", "de_strict_order"], optional = true } -serde = { version = "1", features = ["derive", "alloc"], optional = true } +borsh = { version = "1", default-features = false, features = ["derive", "de_strict_order"], optional = true } +serde = { version = "1", default-features = false, features = ["derive", "alloc"], optional = true } -sp-core = { git = "https://github.com/serai-dex/substrate" } -sp-runtime = { git = "https://github.com/serai-dex/substrate" } +sp-core = { git = "https://github.com/serai-dex/substrate", default-features = false } +sp-runtime = { git = "https://github.com/serai-dex/substrate", default-features = false } -sp-consensus-babe = { git = "https://github.com/serai-dex/substrate" } -sp-consensus-grandpa = { git = "https://github.com/serai-dex/substrate" } +sp-consensus-babe = { git = "https://github.com/serai-dex/substrate", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/serai-dex/substrate", default-features = false } -serai-primitives = { path = "../primitives", version = "0.1" } -serai-coins-primitives = { path = "../coins/primitives", version = "0.1" } -serai-validator-sets-primitives = { path = "../validator-sets/primitives", version = "0.1" } -serai-in-instructions-primitives = { path = "../in-instructions/primitives", version = "0.1" } -serai-signals-primitives = { path = "../signals/primitives", version = "0.1" } +frame-support = { git = "https://github.com/serai-dex/substrate", default-features = false } -frame-support = { git = "https://github.com/serai-dex/substrate" } +serai-primitives = { path = "../primitives", version = "0.1", default-features = false } +serai-coins-primitives = { path = "../coins/primitives", version = "0.1", default-features = false } +serai-validator-sets-primitives = { path = "../validator-sets/primitives", version = "0.1", default-features = false } +serai-in-instructions-primitives = { path = "../in-instructions/primitives", version = "0.1", default-features = false } +serai-signals-primitives = { path = "../signals/primitives", version = "0.1", default-features = false } [features] +std = [ + "scale/std", + "scale-info/std", + + "borsh?/std", + "serde?/std", + + "sp-core/std", + "sp-runtime/std", + + "sp-consensus-babe/std", + "sp-consensus-grandpa/std", + + "frame-support/std", + + "serai-primitives/std", + "serai-coins-primitives/std", + "serai-validator-sets-primitives/std", + "serai-in-instructions-primitives/std", + "serai-signals-primitives/std", +] borsh = [ "dep:borsh", "serai-primitives/borsh", @@ -53,3 +74,4 @@ serde = [ "serai-in-instructions-primitives/serde", "serai-signals-primitives/serde", ] +default = ["std"] diff --git a/substrate/abi/src/babe.rs b/substrate/abi/src/babe.rs index 29bbee9ce..9bba63d90 100644 --- a/substrate/abi/src/babe.rs +++ b/substrate/abi/src/babe.rs @@ -4,7 +4,7 @@ use serai_primitives::{Header, SeraiAddress}; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] pub struct ReportEquivocation { - pub equivocation_proof: Box>, + pub equivocation_proof: alloc::boxed::Box>, pub key_owner_proof: SeraiAddress, } diff --git a/substrate/abi/src/coins.rs b/substrate/abi/src/coins.rs index c3fa2dada..56255b0a8 100644 --- a/substrate/abi/src/coins.rs +++ b/substrate/abi/src/coins.rs @@ -5,7 +5,8 @@ use primitives::OutInstructionWithBalance; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { transfer { to: SeraiAddress, balance: Balance }, burn { balance: Balance }, @@ -14,7 +15,17 @@ pub enum Call { #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] +pub enum LiquidityTokensCall { + transfer { to: SeraiAddress, balance: Balance }, + burn { balance: Balance }, +} + +#[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { Mint { to: SeraiAddress, balance: Balance }, Burn { from: SeraiAddress, balance: Balance }, diff --git a/substrate/abi/src/dex.rs b/substrate/abi/src/dex.rs index 5136e9740..2daa62f07 100644 --- a/substrate/abi/src/dex.rs +++ b/substrate/abi/src/dex.rs @@ -6,7 +6,8 @@ type PoolId = Coin; type MaxSwapPathLength = sp_core::ConstU32<3>; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { add_liquidity { coin: Coin, @@ -38,7 +39,8 @@ pub enum Call { } #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { PoolCreated { pool_id: PoolId, diff --git a/substrate/abi/src/grandpa.rs b/substrate/abi/src/grandpa.rs index 54de8182a..ead8dfc21 100644 --- a/substrate/abi/src/grandpa.rs +++ b/substrate/abi/src/grandpa.rs @@ -1,10 +1,11 @@ +use sp_core::{ConstU32, bounded::BoundedVec}; use sp_consensus_grandpa::EquivocationProof; use serai_primitives::{BlockNumber, SeraiAddress}; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] pub struct ReportEquivocation { - pub equivocation_proof: Box>, + pub equivocation_proof: alloc::boxed::Box>, pub key_owner_proof: SeraiAddress, } @@ -15,10 +16,10 @@ pub enum Call { } #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { - NewAuthorities { authority_set: Vec<(SeraiAddress, u64)> }, + NewAuthorities { authority_set: BoundedVec<(SeraiAddress, u64), ConstU32<0>> }, // TODO: Remove these Paused, Resumed, diff --git a/substrate/abi/src/in_instructions.rs b/substrate/abi/src/in_instructions.rs index 1e5d1bb54..d3ab5ca3d 100644 --- a/substrate/abi/src/in_instructions.rs +++ b/substrate/abi/src/in_instructions.rs @@ -5,14 +5,16 @@ use primitives::SignedBatch; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { execute_batch { batch: SignedBatch }, } #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { Batch { network: NetworkId, id: u32, block: BlockHash, instructions_hash: [u8; 32] }, InstructionFailure { network: NetworkId, id: u32, index: u32 }, diff --git a/substrate/abi/src/lib.rs b/substrate/abi/src/lib.rs index 2e873f4c3..2670bef78 100644 --- a/substrate/abi/src/lib.rs +++ b/substrate/abi/src/lib.rs @@ -1,5 +1,12 @@ +#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(not(feature = "std"), no_std)] #![allow(non_camel_case_types)] +extern crate alloc; + +pub use serai_primitives as primitives; + pub mod system; pub mod timestamp; @@ -14,15 +21,13 @@ pub mod signals; pub mod babe; pub mod grandpa; -pub use serai_primitives as primitives; +pub mod tx; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] pub enum Call { - System, Timestamp(timestamp::Call), - TransactionPayment, Coins(coins::Call), - LiquidityTokens(coins::Call), + LiquidityTokens(coins::LiquidityTokensCall), Dex(dex::Call), ValidatorSets(validator_sets::Call), InInstructions(in_instructions::Call), @@ -53,16 +58,20 @@ pub enum Event { } #[derive(Clone, Copy, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub struct Extra { pub era: sp_runtime::generic::Era, - pub nonce: scale::Compact, - pub tip: scale::Compact, + #[codec(compact)] + pub nonce: u32, + #[codec(compact)] + pub tip: u64, } #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub struct SignedPayloadExtra { pub spec_version: u32, pub tx_version: u32, @@ -70,4 +79,4 @@ pub struct SignedPayloadExtra { pub mortality_checkpoint: [u8; 32], } -pub type Transaction = primitives::Transaction; +pub type Transaction = tx::Transaction; diff --git a/substrate/abi/src/signals.rs b/substrate/abi/src/signals.rs index 2c8dd5450..6a77672f2 100644 --- a/substrate/abi/src/signals.rs +++ b/substrate/abi/src/signals.rs @@ -7,7 +7,8 @@ use primitives::SignalId; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { register_retirement_signal { in_favor_of: [u8; 32] }, revoke_retirement_signal { retirement_signal_id: [u8; 32] }, @@ -18,7 +19,8 @@ pub enum Call { #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { RetirementSignalRegistered { signal_id: [u8; 32], diff --git a/substrate/abi/src/system.rs b/substrate/abi/src/system.rs index bb67c91c6..d025e767f 100644 --- a/substrate/abi/src/system.rs +++ b/substrate/abi/src/system.rs @@ -3,7 +3,6 @@ use frame_support::dispatch::{DispatchInfo, DispatchError}; use serai_primitives::SeraiAddress; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Event { ExtrinsicSuccess { dispatch_info: DispatchInfo }, ExtrinsicFailed { dispatch_error: DispatchError, dispatch_info: DispatchInfo }, diff --git a/substrate/abi/src/timestamp.rs b/substrate/abi/src/timestamp.rs index c6e7d8cdb..af7639289 100644 --- a/substrate/abi/src/timestamp.rs +++ b/substrate/abi/src/timestamp.rs @@ -1,5 +1,9 @@ #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { - set { now: scale::Compact }, + set { + #[codec(compact)] + now: u64, + }, } diff --git a/substrate/abi/src/tx.rs b/substrate/abi/src/tx.rs new file mode 100644 index 000000000..6c61535b8 --- /dev/null +++ b/substrate/abi/src/tx.rs @@ -0,0 +1,183 @@ +use scale::Encode; + +use sp_core::sr25519::{Public, Signature}; +use sp_runtime::traits::Verify; + +use serai_primitives::SeraiAddress; + +use frame_support::dispatch::GetDispatchInfo; + +pub trait TransactionMember: + Clone + PartialEq + Eq + core::fmt::Debug + scale::Encode + scale::Decode + scale_info::TypeInfo +{ +} +impl< + T: Clone + + PartialEq + + Eq + + core::fmt::Debug + + scale::Encode + + scale::Decode + + scale_info::TypeInfo, + > TransactionMember for T +{ +} + +type TransactionEncodeAs<'a, Extra> = + (&'a crate::Call, &'a Option<(SeraiAddress, Signature, Extra)>); +type TransactionDecodeAs = (crate::Call, Option<(SeraiAddress, Signature, Extra)>); + +// We use our own Transaction struct, over UncheckedExtrinsic, for more control, a bit more +// simplicity, and in order to be immune to https://github.com/paritytech/polkadot-sdk/issues/2947 +#[allow(private_bounds)] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Transaction< + Call: 'static + TransactionMember + From, + Extra: 'static + TransactionMember, +> { + call: crate::Call, + mapped_call: Call, + signature: Option<(SeraiAddress, Signature, Extra)>, +} + +impl, Extra: 'static + TransactionMember> + Transaction +{ + pub fn new(call: crate::Call, signature: Option<(SeraiAddress, Signature, Extra)>) -> Self { + Self { call: call.clone(), mapped_call: call.into(), signature } + } + + pub fn call(&self) -> &crate::Call { + &self.call + } +} + +impl, Extra: 'static + TransactionMember> + scale::Encode for Transaction +{ + fn using_encoded R>(&self, f: F) -> R { + let tx: TransactionEncodeAs = (&self.call, &self.signature); + tx.using_encoded(f) + } +} +impl, Extra: 'static + TransactionMember> + scale::Decode for Transaction +{ + fn decode(input: &mut I) -> Result { + let (call, signature) = TransactionDecodeAs::decode(input)?; + let mapped_call = Call::from(call.clone()); + Ok(Self { call, mapped_call, signature }) + } +} +impl, Extra: 'static + TransactionMember> + scale_info::TypeInfo for Transaction +{ + type Identity = TransactionDecodeAs; + + // Define the type info as the info of the type equivalent to what we encode as + fn type_info() -> scale_info::Type { + TransactionDecodeAs::::type_info() + } +} + +#[cfg(feature = "serde")] +mod _serde { + use scale::Encode; + use serde::{ser::*, de::*}; + use super::*; + impl, Extra: 'static + TransactionMember> + Serialize for Transaction + { + fn serialize(&self, serializer: S) -> Result { + let encoded = self.encode(); + serializer.serialize_bytes(&encoded) + } + } + #[cfg(feature = "std")] + impl< + 'a, + Call: 'static + TransactionMember + From, + Extra: 'static + TransactionMember, + > Deserialize<'a> for Transaction + { + fn deserialize>(de: D) -> Result { + let bytes = sp_core::bytes::deserialize(de)?; + ::decode(&mut &bytes[..]) + .map_err(|e| serde::de::Error::custom(format!("invalid transaction: {e}"))) + } + } +} + +impl< + Call: 'static + TransactionMember + From + TryInto, + Extra: 'static + TransactionMember, + > sp_runtime::traits::Extrinsic for Transaction +{ + type Call = Call; + type SignaturePayload = (SeraiAddress, Signature, Extra); + fn is_signed(&self) -> Option { + Some(self.signature.is_some()) + } + fn new(call: Call, signature: Option) -> Option { + Some(Self { call: call.clone().try_into().ok()?, mapped_call: call, signature }) + } +} + +impl< + Call: 'static + TransactionMember + From + TryInto, + Extra: 'static + TransactionMember, + > frame_support::traits::ExtrinsicCall for Transaction +{ + fn call(&self) -> &Call { + &self.mapped_call + } +} + +impl< + Call: 'static + TransactionMember + From, + Extra: 'static + TransactionMember + sp_runtime::traits::SignedExtension, + > sp_runtime::traits::ExtrinsicMetadata for Transaction +{ + type SignedExtensions = Extra; + + const VERSION: u8 = 0; +} + +impl< + Call: 'static + TransactionMember + From + GetDispatchInfo, + Extra: 'static + TransactionMember, + > GetDispatchInfo for Transaction +{ + fn get_dispatch_info(&self) -> frame_support::dispatch::DispatchInfo { + self.mapped_call.get_dispatch_info() + } +} + +impl< + Call: 'static + TransactionMember + From, + Extra: 'static + TransactionMember + sp_runtime::traits::SignedExtension, + > sp_runtime::traits::BlindCheckable for Transaction +{ + type Checked = sp_runtime::generic::CheckedExtrinsic; + + fn check( + self, + ) -> Result { + Ok(match self.signature { + Some((signer, signature, extra)) => { + if !signature.verify( + (&self.call, &extra, extra.additional_signed()?).encode().as_slice(), + &signer.into(), + ) { + Err(sp_runtime::transaction_validity::InvalidTransaction::BadProof)? + } + + sp_runtime::generic::CheckedExtrinsic { + signed: Some((signer.into(), extra)), + function: self.mapped_call, + } + } + None => sp_runtime::generic::CheckedExtrinsic { signed: None, function: self.mapped_call }, + }) + } +} diff --git a/substrate/abi/src/validator_sets.rs b/substrate/abi/src/validator_sets.rs index 1630f8aca..1e1e33591 100644 --- a/substrate/abi/src/validator_sets.rs +++ b/substrate/abi/src/validator_sets.rs @@ -1,4 +1,4 @@ -use sp_core::{ConstU32, bounded_vec::BoundedVec}; +use sp_core::{ConstU32, bounded::BoundedVec}; pub use serai_validator_sets_primitives as primitives; @@ -6,11 +6,12 @@ use serai_primitives::*; use serai_validator_sets_primitives::*; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { set_keys { network: NetworkId, - removed_participants: Vec, + removed_participants: BoundedVec>, key_pair: KeyPair, signature: Signature, }, @@ -35,7 +36,8 @@ pub enum Call { #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { NewSet { set: ValidatorSet, diff --git a/substrate/client/src/serai/mod.rs b/substrate/client/src/serai/mod.rs index 1347fc058..524213994 100644 --- a/substrate/client/src/serai/mod.rs +++ b/substrate/client/src/serai/mod.rs @@ -3,7 +3,7 @@ use thiserror::Error; use async_lock::RwLock; use simple_request::{hyper, Request, Client}; -use scale::{Compact, Decode, Encode}; +use scale::{Decode, Encode}; use serde::{Serialize, Deserialize, de::DeserializeOwned}; pub use sp_core::{ @@ -43,8 +43,8 @@ impl Block { /// Returns the time of this block, set by its producer, in milliseconds since the epoch. pub fn time(&self) -> Result { for transaction in &self.transactions { - if let Call::Timestamp(timestamp::Call::set { now }) = &transaction.call { - return Ok(u64::from(*now)); + if let Call::Timestamp(timestamp::Call::set { now }) = transaction.call() { + return Ok(*now); } } Err(SeraiError::InvalidNode("no time was present in block".to_string())) @@ -162,15 +162,14 @@ impl Serai { } fn unsigned(call: Call) -> Transaction { - Transaction { call, signature: None } + Transaction::new(call, None) } pub fn sign(&self, signer: &Pair, call: Call, nonce: u32, tip: u64) -> Transaction { const SPEC_VERSION: u32 = 1; const TX_VERSION: u32 = 1; - let extra = - Extra { era: sp_runtime::generic::Era::Immortal, nonce: Compact(nonce), tip: Compact(tip) }; + let extra = Extra { era: sp_runtime::generic::Era::Immortal, nonce, tip }; let signature_payload = ( &call, &extra, @@ -184,7 +183,7 @@ impl Serai { .encode(); let signature = signer.sign(&signature_payload); - Transaction { call, signature: Some((signer.public().into(), signature, extra)) } + Transaction::new(call, Some((signer.public().into(), signature, extra))) } pub async fn publish(&self, tx: &Transaction) -> Result<(), SeraiError> { diff --git a/substrate/client/src/serai/validator_sets.rs b/substrate/client/src/serai/validator_sets.rs index c4e296441..959f8ee60 100644 --- a/substrate/client/src/serai/validator_sets.rs +++ b/substrate/client/src/serai/validator_sets.rs @@ -180,7 +180,10 @@ impl<'a> SeraiValidatorSets<'a> { pub fn set_keys( network: NetworkId, - removed_participants: Vec, + removed_participants: sp_runtime::BoundedVec< + SeraiAddress, + sp_core::ConstU32<{ primitives::MAX_KEY_SHARES_PER_SET / 3 }>, + >, key_pair: KeyPair, signature: Signature, ) -> Transaction { diff --git a/substrate/client/tests/common/validator_sets.rs b/substrate/client/tests/common/validator_sets.rs index b7257a1ce..7924d05c4 100644 --- a/substrate/client/tests/common/validator_sets.rs +++ b/substrate/client/tests/common/validator_sets.rs @@ -51,7 +51,12 @@ pub async fn set_keys(serai: &Serai, set: ValidatorSet, key_pair: KeyPair) -> [u // Set the key pair let block = publish_tx( serai, - &SeraiValidatorSets::set_keys(set.network, vec![], key_pair.clone(), Signature(sig.to_bytes())), + &SeraiValidatorSets::set_keys( + set.network, + vec![].try_into().unwrap(), + key_pair.clone(), + Signature(sig.to_bytes()), + ), ) .await; diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 970cf46e4..2af36e22d 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -37,9 +37,6 @@ pub use balance::*; mod account; pub use account::*; -mod tx; -pub use tx::*; - pub type BlockNumber = u64; pub type Header = sp_runtime::generic::Header; diff --git a/substrate/primitives/src/tx.rs b/substrate/primitives/src/tx.rs deleted file mode 100644 index b97ec3a2f..000000000 --- a/substrate/primitives/src/tx.rs +++ /dev/null @@ -1,124 +0,0 @@ -use scale::Encode; - -use sp_core::sr25519::{Public, Signature}; -use sp_runtime::traits::Verify; - -use crate::SeraiAddress; - -trait TransactionMember: - Clone + PartialEq + Eq + core::fmt::Debug + scale::Encode + scale::Decode + scale_info::TypeInfo -{ -} -impl< - T: Clone - + PartialEq - + Eq - + core::fmt::Debug - + scale::Encode - + scale::Decode - + scale_info::TypeInfo, - > TransactionMember for T -{ -} - -// We use our own Transaction struct, over UncheckedExtrinsic, for more control, a bit more -// simplicity, and in order to be immune to https://github.com/paritytech/polkadot-sdk/issues/2947 -#[allow(private_bounds)] -#[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -pub struct Transaction { - pub call: Call, - pub signature: Option<(SeraiAddress, Signature, Extra)>, -} - -#[cfg(feature = "serde")] -mod _serde { - use scale::Encode; - use serde::{ser::*, de::*}; - use super::*; - impl Serialize for Transaction { - fn serialize(&self, serializer: S) -> Result { - let encoded = self.encode(); - serializer.serialize_bytes(&encoded) - } - } - #[cfg(feature = "std")] - impl<'a, Call: TransactionMember, Extra: TransactionMember> Deserialize<'a> - for Transaction - { - fn deserialize>(de: D) -> Result { - let bytes = sp_core::bytes::deserialize(de)?; - scale::Decode::decode(&mut &bytes[..]) - .map_err(|e| serde::de::Error::custom(format!("invalid transaction: {e}"))) - } - } -} - -impl sp_runtime::traits::Extrinsic - for Transaction -{ - type Call = Call; - type SignaturePayload = (SeraiAddress, Signature, Extra); - fn is_signed(&self) -> Option { - Some(self.signature.is_some()) - } - fn new(call: Call, signature: Option) -> Option { - Some(Self { call, signature }) - } -} - -impl frame_support::traits::ExtrinsicCall - for Transaction -{ - fn call(&self) -> &Call { - &self.call - } -} - -impl sp_runtime::traits::ExtrinsicMetadata - for Transaction -where - Extra: sp_runtime::traits::SignedExtension, -{ - type SignedExtensions = Extra; - - const VERSION: u8 = 0; -} - -impl frame_support::dispatch::GetDispatchInfo - for Transaction -where - Call: frame_support::dispatch::GetDispatchInfo, -{ - fn get_dispatch_info(&self) -> frame_support::dispatch::DispatchInfo { - self.call.get_dispatch_info() - } -} - -impl sp_runtime::traits::BlindCheckable - for Transaction -where - Extra: sp_runtime::traits::SignedExtension, -{ - type Checked = sp_runtime::generic::CheckedExtrinsic; - - fn check( - self, - ) -> Result { - Ok(match self.signature { - Some((signer, signature, extra)) => { - if !signature.verify( - (&self.call, &extra, extra.additional_signed()?).encode().as_slice(), - &signer.into(), - ) { - Err(sp_runtime::transaction_validity::InvalidTransaction::BadProof)? - } - - sp_runtime::generic::CheckedExtrinsic { - signed: Some((signer.into(), extra)), - function: self.call, - } - } - None => sp_runtime::generic::CheckedExtrinsic { signed: None, function: self.call }, - }) - } -} diff --git a/substrate/runtime/Cargo.toml b/substrate/runtime/Cargo.toml index e4b7d639e..54869f6df 100644 --- a/substrate/runtime/Cargo.toml +++ b/substrate/runtime/Cargo.toml @@ -49,6 +49,7 @@ frame-executive = { git = "https://github.com/serai-dex/substrate", default-feat frame-benchmarking = { git = "https://github.com/serai-dex/substrate", default-features = false, optional = true } serai-primitives = { path = "../primitives", default-features = false } +serai-abi = { path = "../abi", default-features = false, features = ["serde"] } pallet-timestamp = { git = "https://github.com/serai-dex/substrate", default-features = false } pallet-authorship = { git = "https://github.com/serai-dex/substrate", default-features = false } @@ -102,6 +103,8 @@ std = [ "frame-executive/std", "serai-primitives/std", + "serai-abi/std", + "serai-abi/serde", "pallet-timestamp/std", "pallet-authorship/std", diff --git a/substrate/runtime/src/abi.rs b/substrate/runtime/src/abi.rs new file mode 100644 index 000000000..45c2aa334 --- /dev/null +++ b/substrate/runtime/src/abi.rs @@ -0,0 +1,363 @@ +use core::marker::PhantomData; + +use scale::{Encode, Decode}; + +use serai_abi::Call; + +use crate::{ + Vec, + primitives::{PublicKey, SeraiAddress}, + timestamp, coins, dex, + validator_sets::{self, MembershipProof}, + in_instructions, signals, babe, grandpa, RuntimeCall, +}; + +impl From for RuntimeCall { + fn from(call: Call) -> RuntimeCall { + match call { + Call::Timestamp(serai_abi::timestamp::Call::set { now }) => { + RuntimeCall::Timestamp(timestamp::Call::set { now }) + } + Call::Coins(coins) => match coins { + serai_abi::coins::Call::transfer { to, balance } => { + RuntimeCall::Coins(coins::Call::transfer { to: to.into(), balance }) + } + serai_abi::coins::Call::burn { balance } => { + RuntimeCall::Coins(coins::Call::burn { balance }) + } + serai_abi::coins::Call::burn_with_instruction { instruction } => { + RuntimeCall::Coins(coins::Call::burn_with_instruction { instruction }) + } + }, + Call::LiquidityTokens(lt) => match lt { + serai_abi::coins::LiquidityTokensCall::transfer { to, balance } => { + RuntimeCall::LiquidityTokens(coins::Call::transfer { to: to.into(), balance }) + } + serai_abi::coins::LiquidityTokensCall::burn { balance } => { + RuntimeCall::LiquidityTokens(coins::Call::burn { balance }) + } + }, + Call::Dex(dex) => match dex { + serai_abi::dex::Call::add_liquidity { + coin, + coin_desired, + sri_desired, + coin_min, + sri_min, + mint_to, + } => RuntimeCall::Dex(dex::Call::add_liquidity { + coin, + coin_desired, + sri_desired, + coin_min, + sri_min, + mint_to: mint_to.into(), + }), + serai_abi::dex::Call::remove_liquidity { + coin, + lp_token_burn, + coin_min_receive, + sri_min_receive, + withdraw_to, + } => RuntimeCall::Dex(dex::Call::remove_liquidity { + coin, + lp_token_burn, + coin_min_receive, + sri_min_receive, + withdraw_to: withdraw_to.into(), + }), + serai_abi::dex::Call::swap_exact_tokens_for_tokens { + path, + amount_in, + amount_out_min, + send_to, + } => RuntimeCall::Dex(dex::Call::swap_exact_tokens_for_tokens { + path, + amount_in, + amount_out_min, + send_to: send_to.into(), + }), + serai_abi::dex::Call::swap_tokens_for_exact_tokens { + path, + amount_out, + amount_in_max, + send_to, + } => RuntimeCall::Dex(dex::Call::swap_tokens_for_exact_tokens { + path, + amount_out, + amount_in_max, + send_to: send_to.into(), + }), + }, + Call::ValidatorSets(vs) => match vs { + serai_abi::validator_sets::Call::set_keys { + network, + removed_participants, + key_pair, + signature, + } => RuntimeCall::ValidatorSets(validator_sets::Call::set_keys { + network, + removed_participants: <_>::try_from( + removed_participants.into_iter().map(PublicKey::from).collect::>(), + ) + .unwrap(), + key_pair, + signature, + }), + serai_abi::validator_sets::Call::report_slashes { network, slashes, signature } => { + RuntimeCall::ValidatorSets(validator_sets::Call::report_slashes { + network, + slashes: <_>::try_from( + slashes + .into_iter() + .map(|(addr, slash)| (PublicKey::from(addr), slash)) + .collect::>(), + ) + .unwrap(), + signature, + }) + } + serai_abi::validator_sets::Call::allocate { network, amount } => { + RuntimeCall::ValidatorSets(validator_sets::Call::allocate { network, amount }) + } + serai_abi::validator_sets::Call::deallocate { network, amount } => { + RuntimeCall::ValidatorSets(validator_sets::Call::deallocate { network, amount }) + } + serai_abi::validator_sets::Call::claim_deallocation { network, session } => { + RuntimeCall::ValidatorSets(validator_sets::Call::claim_deallocation { network, session }) + } + }, + Call::InInstructions(ii) => match ii { + serai_abi::in_instructions::Call::execute_batch { batch } => { + RuntimeCall::InInstructions(in_instructions::Call::execute_batch { batch }) + } + }, + Call::Signals(signals) => match signals { + serai_abi::signals::Call::register_retirement_signal { in_favor_of } => { + RuntimeCall::Signals(signals::Call::register_retirement_signal { in_favor_of }) + } + serai_abi::signals::Call::revoke_retirement_signal { retirement_signal_id } => { + RuntimeCall::Signals(signals::Call::revoke_retirement_signal { retirement_signal_id }) + } + serai_abi::signals::Call::favor { signal_id, for_network } => { + RuntimeCall::Signals(signals::Call::favor { signal_id, for_network }) + } + serai_abi::signals::Call::revoke_favor { signal_id, for_network } => { + RuntimeCall::Signals(signals::Call::revoke_favor { signal_id, for_network }) + } + serai_abi::signals::Call::stand_against { signal_id, for_network } => { + RuntimeCall::Signals(signals::Call::stand_against { signal_id, for_network }) + } + }, + Call::Babe(babe) => match babe { + serai_abi::babe::Call::report_equivocation(report) => { + RuntimeCall::Babe(babe::Call::report_equivocation { + // TODO: Find a better way to go from Proof<[u8; 32]> to Proof + equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) + .unwrap(), + key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), + }) + } + serai_abi::babe::Call::report_equivocation_unsigned(report) => { + RuntimeCall::Babe(babe::Call::report_equivocation_unsigned { + // TODO: Find a better way to go from Proof<[u8; 32]> to Proof + equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) + .unwrap(), + key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), + }) + } + }, + Call::Grandpa(grandpa) => match grandpa { + serai_abi::grandpa::Call::report_equivocation(report) => { + RuntimeCall::Grandpa(grandpa::Call::report_equivocation { + // TODO: Find a better way to go from Proof<[u8; 32]> to Proof + equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) + .unwrap(), + key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), + }) + } + serai_abi::grandpa::Call::report_equivocation_unsigned(report) => { + RuntimeCall::Grandpa(grandpa::Call::report_equivocation_unsigned { + // TODO: Find a better way to go from Proof<[u8; 32]> to Proof + equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) + .unwrap(), + key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), + }) + } + }, + } + } +} + +impl TryInto for RuntimeCall { + type Error = (); + + fn try_into(self) -> Result { + Ok(match self { + RuntimeCall::Timestamp(timestamp::Call::set { now }) => { + Call::Timestamp(serai_abi::timestamp::Call::set { now }) + } + RuntimeCall::Coins(call) => Call::Coins(match call { + coins::Call::transfer { to, balance } => { + serai_abi::coins::Call::transfer { to: to.into(), balance } + } + coins::Call::burn { balance } => serai_abi::coins::Call::burn { balance }, + coins::Call::burn_with_instruction { instruction } => { + serai_abi::coins::Call::burn_with_instruction { instruction } + } + _ => Err(())?, + }), + RuntimeCall::LiquidityTokens(call) => Call::LiquidityTokens(match call { + coins::Call::transfer { to, balance } => { + serai_abi::coins::LiquidityTokensCall::transfer { to: to.into(), balance } + } + coins::Call::burn { balance } => serai_abi::coins::LiquidityTokensCall::burn { balance }, + _ => Err(())?, + }), + RuntimeCall::Dex(call) => Call::Dex(match call { + dex::Call::add_liquidity { + coin, + coin_desired, + sri_desired, + coin_min, + sri_min, + mint_to, + } => serai_abi::dex::Call::add_liquidity { + coin, + coin_desired, + sri_desired, + coin_min, + sri_min, + mint_to: mint_to.into(), + }, + dex::Call::remove_liquidity { + coin, + lp_token_burn, + coin_min_receive, + sri_min_receive, + withdraw_to, + } => serai_abi::dex::Call::remove_liquidity { + coin, + lp_token_burn, + coin_min_receive, + sri_min_receive, + withdraw_to: withdraw_to.into(), + }, + dex::Call::swap_exact_tokens_for_tokens { path, amount_in, amount_out_min, send_to } => { + serai_abi::dex::Call::swap_exact_tokens_for_tokens { + path, + amount_in, + amount_out_min, + send_to: send_to.into(), + } + } + dex::Call::swap_tokens_for_exact_tokens { path, amount_out, amount_in_max, send_to } => { + serai_abi::dex::Call::swap_tokens_for_exact_tokens { + path, + amount_out, + amount_in_max, + send_to: send_to.into(), + } + } + _ => Err(())?, + }), + RuntimeCall::ValidatorSets(call) => Call::ValidatorSets(match call { + validator_sets::Call::set_keys { network, removed_participants, key_pair, signature } => { + serai_abi::validator_sets::Call::set_keys { + network, + removed_participants: <_>::try_from( + removed_participants.into_iter().map(SeraiAddress::from).collect::>(), + ) + .unwrap(), + key_pair, + signature, + } + } + validator_sets::Call::report_slashes { network, slashes, signature } => { + serai_abi::validator_sets::Call::report_slashes { + network, + slashes: <_>::try_from( + slashes + .into_iter() + .map(|(addr, slash)| (SeraiAddress::from(addr), slash)) + .collect::>(), + ) + .unwrap(), + signature, + } + } + validator_sets::Call::allocate { network, amount } => { + serai_abi::validator_sets::Call::allocate { network, amount } + } + validator_sets::Call::deallocate { network, amount } => { + serai_abi::validator_sets::Call::deallocate { network, amount } + } + validator_sets::Call::claim_deallocation { network, session } => { + serai_abi::validator_sets::Call::claim_deallocation { network, session } + } + _ => Err(())?, + }), + RuntimeCall::InInstructions(call) => Call::InInstructions(match call { + in_instructions::Call::execute_batch { batch } => { + serai_abi::in_instructions::Call::execute_batch { batch } + } + _ => Err(())?, + }), + RuntimeCall::Signals(call) => Call::Signals(match call { + signals::Call::register_retirement_signal { in_favor_of } => { + serai_abi::signals::Call::register_retirement_signal { in_favor_of } + } + signals::Call::revoke_retirement_signal { retirement_signal_id } => { + serai_abi::signals::Call::revoke_retirement_signal { retirement_signal_id } + } + signals::Call::favor { signal_id, for_network } => { + serai_abi::signals::Call::favor { signal_id, for_network } + } + signals::Call::revoke_favor { signal_id, for_network } => { + serai_abi::signals::Call::revoke_favor { signal_id, for_network } + } + signals::Call::stand_against { signal_id, for_network } => { + serai_abi::signals::Call::stand_against { signal_id, for_network } + } + _ => Err(())?, + }), + RuntimeCall::Babe(call) => Call::Babe(match call { + babe::Call::report_equivocation { equivocation_proof, key_owner_proof } => { + serai_abi::babe::Call::report_equivocation(serai_abi::babe::ReportEquivocation { + // TODO: Find a better way to go from Proof to Proof<[u8; 32]> + equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), + key_owner_proof: key_owner_proof.0.into(), + }) + } + babe::Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } => { + serai_abi::babe::Call::report_equivocation_unsigned(serai_abi::babe::ReportEquivocation { + // TODO: Find a better way to go from Proof to Proof<[u8; 32]> + equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), + key_owner_proof: key_owner_proof.0.into(), + }) + } + _ => Err(())?, + }), + RuntimeCall::Grandpa(call) => Call::Grandpa(match call { + grandpa::Call::report_equivocation { equivocation_proof, key_owner_proof } => { + serai_abi::grandpa::Call::report_equivocation(serai_abi::grandpa::ReportEquivocation { + // TODO: Find a better way to go from Proof to Proof<[u8; 32]> + equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), + key_owner_proof: key_owner_proof.0.into(), + }) + } + grandpa::Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } => { + serai_abi::grandpa::Call::report_equivocation_unsigned( + serai_abi::grandpa::ReportEquivocation { + // TODO: Find a better way to go from Proof to Proof<[u8; 32]> + equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), + key_owner_proof: key_owner_proof.0.into(), + }, + ) + } + _ => Err(())?, + }), + _ => Err(())?, + }) + } +} diff --git a/substrate/runtime/src/lib.rs b/substrate/runtime/src/lib.rs index 9a534a725..bef2c062a 100644 --- a/substrate/runtime/src/lib.rs +++ b/substrate/runtime/src/lib.rs @@ -64,6 +64,8 @@ use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use babe::AuthorityId as BabeId; use grandpa::AuthorityId as GrandpaId; +mod abi; + /// Nonce of a transaction in the chain, for a given account. pub type Nonce = u32; @@ -81,7 +83,7 @@ pub type SignedExtra = ( transaction_payment::ChargeTransactionPayment, ); -pub type Transaction = serai_primitives::Transaction; +pub type Transaction = serai_abi::tx::Transaction; pub type Block = generic::Block; pub type BlockId = generic::BlockId; @@ -161,35 +163,9 @@ parameter_types! { pub struct CallFilter; impl Contains for CallFilter { fn contains(call: &RuntimeCall) -> bool { - match call { - RuntimeCall::Timestamp(call) => match call { - timestamp::Call::set { .. } => true, - timestamp::Call::__Ignore(_, _) => false, - }, - - // All of these pallets are our own, and all of their written calls are intended to be called - RuntimeCall::Coins(call) => !matches!(call, coins::Call::__Ignore(_, _)), - RuntimeCall::LiquidityTokens(call) => match call { - coins::Call::transfer { .. } | coins::Call::burn { .. } => true, - coins::Call::burn_with_instruction { .. } | coins::Call::__Ignore(_, _) => false, - }, - RuntimeCall::Dex(call) => !matches!(call, dex::Call::__Ignore(_, _)), - RuntimeCall::ValidatorSets(call) => !matches!(call, validator_sets::Call::__Ignore(_, _)), - RuntimeCall::InInstructions(call) => !matches!(call, in_instructions::Call::__Ignore(_, _)), - RuntimeCall::Signals(call) => !matches!(call, signals::Call::__Ignore(_, _)), - - RuntimeCall::Babe(call) => match call { - babe::Call::report_equivocation { .. } | - babe::Call::report_equivocation_unsigned { .. } => true, - babe::Call::plan_config_change { .. } | babe::Call::__Ignore(_, _) => false, - }, - - RuntimeCall::Grandpa(call) => match call { - grandpa::Call::report_equivocation { .. } | - grandpa::Call::report_equivocation_unsigned { .. } => true, - grandpa::Call::note_stalled { .. } | grandpa::Call::__Ignore(_, _) => false, - }, - } + // If the call is defined in our ABI, it's allowed + let call: Result = call.clone().try_into(); + call.is_ok() } } diff --git a/substrate/validator-sets/pallet/src/lib.rs b/substrate/validator-sets/pallet/src/lib.rs index c852c4ce2..6ea89764d 100644 --- a/substrate/validator-sets/pallet/src/lib.rs +++ b/substrate/validator-sets/pallet/src/lib.rs @@ -873,7 +873,7 @@ pub mod pallet { pub fn set_keys( origin: OriginFor, network: NetworkId, - removed_participants: Vec, + removed_participants: BoundedVec>, key_pair: KeyPair, signature: Signature, ) -> DispatchResult {