diff --git a/Cargo.toml b/Cargo.toml index 74f04609..cd650b86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,6 @@ substrate-frame-rpc-system = { version = "15.0.0", default-features = false } pallet-aura = { version = "14.0.0", default-features = false } pallet-balances = { version = "15.0.0", default-features = false } pallet-grandpa = { version = "15.0.0", default-features = false } -pallet-im-online = { version = "14.0.0", default-features = false } pallet-randomness-collective-flip = { version = "15.0.0", default-features = false } pallet-session = { version = "15.0.0", default-features = false } pallet-sudo = { version = "15.0.0", default-features = false } diff --git a/gn-client/examples/guild/main.rs b/gn-client/examples/guild/main.rs index c47ce2d0..cbbe0aa1 100644 --- a/gn-client/examples/guild/main.rs +++ b/gn-client/examples/guild/main.rs @@ -2,7 +2,7 @@ mod common; mod fund; mod join; mod key; -mod register; +mod sudo; mod token; use gn_client::tx; @@ -20,9 +20,13 @@ enum Example { Join, Key(Key), Token, - Register { + Sudo { #[structopt(long, short)] - operator: Option, + pallet: String, + #[structopt(long, short)] + method: String, + #[structopt(long, short)] + account: Option, }, } @@ -79,8 +83,19 @@ async fn main() { key::generate(&curve, password.as_deref()) } Example::Key(Key::Rotate) => key::rotate(api).await, - Example::Register { operator } => { - register::register(api, signer, operator.as_deref()).await + Example::Sudo { + pallet, + method, + account, + } => { + sudo::sudo( + api, + signer, + &pallet.to_lowercase(), + &method.to_lowercase(), + account.as_deref(), + ) + .await } Example::Token => token::token(api, signer).await, } diff --git a/gn-client/examples/guild/register.rs b/gn-client/examples/guild/register.rs deleted file mode 100644 index 966a7e78..00000000 --- a/gn-client/examples/guild/register.rs +++ /dev/null @@ -1,21 +0,0 @@ -use gn_client::{ - tx::{self, Signer}, - AccountId, Api, -}; - -use std::str::FromStr; -use std::sync::Arc; - -pub async fn register(api: Api, root: Arc, maybe_operator: Option<&str>) { - let account_id = if let Some(operator) = maybe_operator { - AccountId::from_str(operator).expect("invalid operator id string") - } else { - root.account_id().clone() - }; - - let payload = tx::register_operator(&account_id); - tx::send_tx_in_block(api, &tx::sudo(payload), root) - .await - .unwrap(); - println!("{account_id} registered as operator"); -} diff --git a/gn-client/examples/guild/sudo.rs b/gn-client/examples/guild/sudo.rs new file mode 100644 index 00000000..3358be16 --- /dev/null +++ b/gn-client/examples/guild/sudo.rs @@ -0,0 +1,34 @@ +use gn_client::{ + tx::{self, Signer}, + AccountId, Api, +}; + +use std::str::FromStr; +use std::sync::Arc; + +pub async fn sudo( + api: Api, + root: Arc, + pallet: &str, + method: &str, + maybe_operator: Option<&str>, +) { + let account_id = if let Some(operator) = maybe_operator { + AccountId::from_str(operator).expect("invalid operator id string") + } else { + root.account_id().clone() + }; + + let payload = match (pallet, method) { + ("oracle", "register") => tx::register_operator(&account_id), + ("oracle", "deregister") => tx::deregister_operator(&account_id), + ("validator", "add") => tx::add_validator(&account_id), + ("validator", "remove") => tx::remove_validator(&account_id), + _ => unimplemented!(), + }; + + tx::send_tx_in_block(api, &tx::sudo(payload), root) + .await + .unwrap(); + println!("{pallet} {method} {account_id} submitted successfully"); +} diff --git a/gn-client/src/tx/mod.rs b/gn-client/src/tx/mod.rs index 26713872..6164c33a 100644 --- a/gn-client/src/tx/mod.rs +++ b/gn-client/src/tx/mod.rs @@ -39,12 +39,6 @@ pub fn sudo<'a>(call: DynamicTxPayload<'_>) -> DynamicTxPayload<'a> { subxt::dynamic::tx("Sudo", "sudo", vec![("call", call.into_value())]) } -pub fn fund_account(account: &AccountId, amount: u128) -> impl TxPayload { - runtime::tx() - .balances() - .transfer(MultiAddress::Id(account.clone()), amount) -} - pub fn register_operator<'a>(operator: &AccountId) -> DynamicTxPayload<'a> { subxt::dynamic::tx( "Oracle", @@ -53,6 +47,36 @@ pub fn register_operator<'a>(operator: &AccountId) -> DynamicTxPayload<'a> { ) } +pub fn deregister_operator<'a>(operator: &AccountId) -> DynamicTxPayload<'a> { + subxt::dynamic::tx( + "Oracle", + "deregister_operator", + vec![("operator", Value::from_bytes(operator))], + ) +} + +pub fn add_validator<'a>(validator: &AccountId) -> DynamicTxPayload<'a> { + subxt::dynamic::tx( + "ValidatorManager", + "add_validator", + vec![("validator_id", Value::from_bytes(validator))], + ) +} + +pub fn remove_validator<'a>(validator: &AccountId) -> DynamicTxPayload<'a> { + subxt::dynamic::tx( + "ValidatorManager", + "remove_validator", + vec![("validator_id", Value::from_bytes(validator))], + ) +} + +pub fn fund_account(account: &AccountId, amount: u128) -> impl TxPayload { + runtime::tx() + .balances() + .transfer(MultiAddress::Id(account.clone()), amount) +} + pub fn activate_operator() -> impl TxPayload { runtime::tx().oracle().activate_operator() } diff --git a/gn-node/Cargo.toml b/gn-node/Cargo.toml index e33c4541..1fc2ec15 100644 --- a/gn-node/Cargo.toml +++ b/gn-node/Cargo.toml @@ -41,7 +41,6 @@ frame-system = { workspace = true, optional = true } substrate-frame-rpc-system = { workspace = true } # substrate pallets -pallet-im-online = { workspace = true } pallet-transaction-payment = { workspace = true, optional = true } pallet-transaction-payment-rpc = { workspace = true } diff --git a/gn-node/src/chain_spec.rs b/gn-node/src/chain_spec.rs index 3377c11d..d49868c7 100644 --- a/gn-node/src/chain_spec.rs +++ b/gn-node/src/chain_spec.rs @@ -1,8 +1,7 @@ use gn_runtime::{ - AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, ImOnlineConfig, - SessionConfig, Signature, SudoConfig, SystemConfig, ValidatorManagerConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, SessionConfig, Signature, + SudoConfig, SystemConfig, ValidatorManagerConfig, WASM_BINARY, }; -use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sc_service::ChainType; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -36,7 +35,6 @@ struct AuthorityKeys { account_id: AccountId, aura_id: AuraId, grandpa_id: GrandpaId, - im_online_id: ImOnlineId, } impl AuthorityKeys { @@ -45,7 +43,6 @@ impl AuthorityKeys { account_id: get_account_id_from_seed::(seed), aura_id: get_from_seed::(seed), grandpa_id: get_from_seed::(seed), - im_online_id: get_from_seed::(seed), } } @@ -53,7 +50,6 @@ impl AuthorityKeys { gn_runtime::opaque::SessionKeys { aura: self.aura_id.clone(), grandpa: self.grandpa_id.clone(), - im_online: self.im_online_id.clone(), } } } @@ -192,7 +188,6 @@ fn testnet_genesis( grandpa: GrandpaConfig { authorities: vec![], }, - im_online: ImOnlineConfig { keys: vec![] }, sudo: SudoConfig { // Assign network admin rights. key: Some(root_key), diff --git a/gn-pallets/pallet-validator-manager/src/lib.rs b/gn-pallets/pallet-validator-manager/src/lib.rs index 5e84e2eb..68acfa7b 100644 --- a/gn-pallets/pallet-validator-manager/src/lib.rs +++ b/gn-pallets/pallet-validator-manager/src/lib.rs @@ -16,6 +16,7 @@ #![deny(clippy::dbg_macro)] #![deny(unused_crate_dependencies)] +pub mod migration; #[cfg(test)] mod mock; #[cfg(test)] @@ -238,6 +239,7 @@ impl Pallet { fn unapprove_validator(validator_id: T::AccountId) -> DispatchResult { let mut approved_set = >::get(); approved_set.retain(|v| *v != validator_id); + >::set(approved_set); Ok(()) } diff --git a/gn-pallets/pallet-validator-manager/src/migration.rs b/gn-pallets/pallet-validator-manager/src/migration.rs new file mode 100644 index 00000000..4ee34011 --- /dev/null +++ b/gn-pallets/pallet-validator-manager/src/migration.rs @@ -0,0 +1,15 @@ +use super::*; + +pub fn on_runtime_upgrade() { + let validators = Validators::::get(); + log::info!("# validators: {}", validators.len()); + log::info!( + "# approved validators: {}", + ApprovedValidators::::get().len() + ); + ApprovedValidators::::set(validators); + log::info!( + "# approved validators post-migration: {}", + ApprovedValidators::::get().len() + ); +} diff --git a/gn-pallets/pallet-validator-manager/src/test.rs b/gn-pallets/pallet-validator-manager/src/test.rs index 71f8aca1..f00036db 100644 --- a/gn-pallets/pallet-validator-manager/src/test.rs +++ b/gn-pallets/pallet-validator-manager/src/test.rs @@ -12,8 +12,8 @@ fn simple_setup_should_work() { authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)] ); - assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64]); - assert_eq!(Session::validators(), vec![1, 2, 3]); + assert_eq!(ValidatorSet::validators(), &[1, 2, 3]); + assert_eq!(Session::validators(), &[1, 2, 3]); }); } @@ -21,7 +21,8 @@ fn simple_setup_should_work() { fn add_validator_updates_validators_list() { new_test_ext().execute_with(|| { assert_ok!(ValidatorSet::add_validator(RuntimeOrigin::root(), 4)); - assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]) + assert_eq!(ValidatorSet::validators(), &[1, 2, 3, 4]); + assert_eq!(ValidatorSet::approved_validators(), &[1, 2, 3, 4]); }); } @@ -29,7 +30,12 @@ fn add_validator_updates_validators_list() { fn remove_validator_updates_validators_list() { new_test_ext().execute_with(|| { assert_ok!(ValidatorSet::remove_validator(RuntimeOrigin::root(), 2)); - assert_eq!(ValidatorSet::validators(), vec![1u64, 3u64]); + assert_eq!(ValidatorSet::validators(), &[1, 3]); + assert_eq!(ValidatorSet::approved_validators(), &[1, 3]); + // add again + assert_ok!(ValidatorSet::add_validator(RuntimeOrigin::root(), 2)); + assert_eq!(ValidatorSet::validators(), &[1, 3, 2]); + assert_eq!(ValidatorSet::approved_validators(), &[1, 3, 2]); }); } @@ -57,7 +63,7 @@ fn remove_validator_fails_with_invalid_origin() { fn duplicate_check() { new_test_ext().execute_with(|| { assert_ok!(ValidatorSet::add_validator(RuntimeOrigin::root(), 4)); - assert_eq!(ValidatorSet::validators(), vec![1u64, 2u64, 3u64, 4u64]); + assert_eq!(ValidatorSet::validators(), &[1, 2, 3, 4]); assert_noop!( ValidatorSet::add_validator(RuntimeOrigin::root(), 4), Error::::Duplicate diff --git a/gn-runtime/Cargo.toml b/gn-runtime/Cargo.toml index faefe93c..da22ccb2 100644 --- a/gn-runtime/Cargo.toml +++ b/gn-runtime/Cargo.toml @@ -35,7 +35,6 @@ std = [ "pallet-balances/std", "pallet-grandpa/std", "pallet-guild/std", - "pallet-im-online/std", "pallet-oracle/std", "pallet-randomness-collective-flip/std", "pallet-session/std", @@ -64,7 +63,6 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-grandpa/try-runtime", "pallet-guild/try-runtime", - "pallet-im-online/try-runtime", "pallet-oracle/try-runtime", "pallet-randomness-collective-flip/try-runtime", "pallet-sudo/try-runtime", @@ -81,7 +79,6 @@ pallet-validator-manager = { version = "0.0.0-alpha", path = "../gn-pallets/pall # general hex-literal = { version = "0.3.4", optional = true } -log = { version = "0.4.17", default-features = false } parity-scale-codec = { workspace = true, features = ["derive"] } scale-info = { workspace = true, features = ["derive"] } @@ -98,7 +95,6 @@ frame-try-runtime = { workspace = true, optional = true } pallet-aura = { workspace = true } pallet-balances = { workspace = true } pallet-grandpa = { workspace = true } -pallet-im-online = { workspace = true } pallet-randomness-collective-flip = { workspace = true } pallet-session = { workspace = true } pallet-sudo = { workspace = true } diff --git a/gn-runtime/src/lib.rs b/gn-runtime/src/lib.rs index fb7be047..21ffdc49 100644 --- a/gn-runtime/src/lib.rs +++ b/gn-runtime/src/lib.rs @@ -14,8 +14,6 @@ pub use pallet_balances::Call as BalancesCall; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; -use pallet_im_online::sr25519::AuthorityId as ImOnlineId; -use parity_scale_codec::Encode; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -26,7 +24,7 @@ use sp_runtime::{ Verify, }, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiSignature, SaturatedConversion, + ApplyExtrinsicResult, MultiSignature, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -34,9 +32,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use frame_support::{ - construct_runtime, - pallet_prelude::TransactionPriority, - parameter_types, + construct_runtime, parameter_types, traits::{ConstU32, ConstU64, ConstU8, KeyOwnerProofSystem}, weights::{ constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, @@ -83,7 +79,6 @@ pub mod opaque { pub struct SessionKeys { pub aura: Aura, pub grandpa: Grandpa, - pub im_online: ImOnline, } } } @@ -150,11 +145,6 @@ parameter_types! { pub const MinAuthorities: u32 = 2; pub const Period: u32 = 2 * MINUTES; pub const Offset: u32 = 0; - - pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); - pub const MaxKeys: u32 = 10_000; - pub const MaxPeerInHeartbeats: u32 = 10_000; - pub const MaxPeerDataEncodingSize: u32 = 1_000; } // Configure FRAME pallets to include in runtime. @@ -213,73 +203,6 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} -impl frame_system::offchain::CreateSignedTransaction> for Runtime { - fn create_transaction>( - call: RuntimeCall, - public: ::Signer, - account: AccountId, - nonce: Index, - ) -> Option<( - RuntimeCall, - ::SignaturePayload, - )> { - let tip = 0; - let period = BlockHashCount::get() - .checked_next_power_of_two() - .map(|c| c / 2) - .unwrap_or(2) as u64; - let current_block = System::block_number() - .saturated_into::() - .saturating_sub(1); - let era = generic::Era::mortal(period, current_block); - let extra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(era), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - ); - let raw_payload = SignedPayload::new(call, extra) - .map_err(|e| { - log::warn!("Unable to create signed payload: {:?}", e); - }) - .ok()?; - let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; - let address = account; - let (call, extra, _) = raw_payload.deconstruct(); - Some(( - call, - (sp_runtime::MultiAddress::Id(address), signature, extra), - )) - } -} - -impl frame_system::offchain::SigningTypes for Runtime { - type Public = ::Signer; - type Signature = Signature; -} - -impl pallet_im_online::Config for Runtime { - type AuthorityId = ImOnlineId; - type RuntimeEvent = RuntimeEvent; - type NextSessionRotation = pallet_session::PeriodicSessions; - type ValidatorSet = ValidatorManager; - type ReportUnresponsiveness = ValidatorManager; - type UnsignedPriority = ImOnlineUnsignedPriority; - type WeightInfo = pallet_im_online::weights::SubstrateWeight; - type MaxKeys = MaxKeys; - type MaxPeerInHeartbeats = MaxPeerInHeartbeats; - type MaxPeerDataEncodingSize = MaxPeerDataEncodingSize; -} - -impl frame_system::offchain::SendTransactionTypes> for Runtime { - type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = RuntimeCall; -} - impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type DisabledValidators = (); @@ -392,7 +315,6 @@ construct_runtime!( Timestamp: pallet_timestamp, ValidatorManager: pallet_validator_manager, Session: pallet_session, - ImOnline: pallet_im_online, Aura: pallet_aura, Grandpa: pallet_grandpa, @@ -432,8 +354,41 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, + // TODO remove this after migration + vm_upgrade::Upgrade, >; +// TODO remove this after migration (validator manager pallet) +mod vm_upgrade { + use super::*; + use frame_support::traits::OnRuntimeUpgrade; + + pub struct Upgrade; + impl OnRuntimeUpgrade for Upgrade { + fn on_runtime_upgrade() -> Weight { + pallet_validator_manager::migration::on_runtime_upgrade::(); + BlockWeights::get().max_block + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + assert!(!ValidatorManager::validators().is_empty(), "invalid state"); + Ok(Vec::new()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_state: Vec) -> Result<(), &'static str> { + assert!(!ValidatorManager::validators().is_empty(), "invalid state"); + assert_eq!( + ValidatorManager::validators(), + ValidatorManager::approved_validators(), + "migration failed" + ); + Ok(()) + } + } +} + #[cfg(feature = "runtime-benchmarks")] #[macro_use] extern crate frame_benchmarking; @@ -635,7 +590,9 @@ impl_runtime_apis! { } } - #[cfg(all(feature = "try-runtime", feature = "std"))] + + + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to diff --git a/integr_test.py b/integr_test.py index 46f8d553..4946c166 100644 --- a/integr_test.py +++ b/integr_test.py @@ -74,7 +74,7 @@ def run_tests(*commands, timeout=300): def main(): try: node = start_node() - command = "cargo run --release --example guild -- register" + command = "cargo run --release --example guild -- sudo --pallet oracle --method register" run_tests(command, timeout=90) oracle = start_oracle() oracle_monitor = Thread(target=monitor_oracle, args=(oracle, node,))