From 8cc3457a25e0ca85ebae8cf8e127ceefccb246a4 Mon Sep 17 00:00:00 2001 From: peg Date: Wed, 14 Aug 2024 11:09:59 +0200 Subject: [PATCH] Attempt to write mock runtime --- Cargo.lock | 13 ++ pallets/attestation/Cargo.toml | 31 ++- pallets/attestation/src/lib.rs | 17 +- pallets/attestation/src/mock.rs | 365 +++++++++++++++++++++++++++++++ pallets/attestation/src/tests.rs | 25 +++ 5 files changed, 440 insertions(+), 11 deletions(-) create mode 100644 pallets/attestation/src/mock.rs create mode 100644 pallets/attestation/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index b2d002013..05549676e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6671,12 +6671,25 @@ name = "pallet-attestation" version = "0.1.0" dependencies = [ "entropy-shared", + "frame-election-provider-support", "frame-support 29.0.2", "frame-system", "log", + "pallet-bags-list", + "pallet-balances", + "pallet-parameters", + "pallet-session", + "pallet-staking", "pallet-staking-extension", + "pallet-staking-reward-curve", + "pallet-timestamp", "parity-scale-codec", "scale-info", + "sp-core 29.0.0", + "sp-io 31.0.0", + "sp-npos-elections", + "sp-runtime 32.0.0", + "sp-staking 27.0.0", "tdx-quote", ] diff --git a/pallets/attestation/Cargo.toml b/pallets/attestation/Cargo.toml index 23f921709..fd60fb04c 100644 --- a/pallets/attestation/Cargo.toml +++ b/pallets/attestation/Cargo.toml @@ -9,17 +9,32 @@ edition ='2021' publish =false [dependencies] -codec ={ package="parity-scale-codec", version="3.6.3", default-features=false, features=["derive"] } -scale-info ={ version="2.11", default-features=false, features=["derive"] } -log ={ version="0.4.22", default-features=false } -frame-support={ version="29.0.0", default-features=false } -frame-system ={ version="29.0.0", default-features=false } -tdx-quote ={ git="https://github.com/entropyxyz/tdx-quote" } +codec ={ package="parity-scale-codec", version="3.6.3", default-features=false, features=["derive"] } +scale-info ={ version="2.11", default-features=false, features=["derive"] } +log ={ version="0.4.22", default-features=false } +frame-support ={ version="29.0.0", default-features=false } +frame-system ={ version="29.0.0", default-features=false } +sp-io ={ version="31.0.0", default-features=false } +sp-core ={ version="29.0.0", default-features=false } +sp-runtime ={ version="32.0.0", default-features=false } +pallet-session={ version="29.0.0", default-features=false } +pallet-staking={ version="29.0.0", default-features=false } +sp-staking ={ version="27.0.0", default-features=false } entropy-shared={ version="0.2.0", path="../../crates/shared", features=[ "wasm-no-std", ], default-features=false } +pallet-parameters={ version="0.2.0", path="../parameters", default-features=false } pallet-staking-extension={ version="0.2.0", path="../staking", default-features=false } +tdx-quote={ git="https://github.com/entropyxyz/tdx-quote" } + +[dev-dependencies] +pallet-balances ={ version="29.0.0", default-features=false } +pallet-bags-list ={ version="28.0.0", default-features=false } +pallet-timestamp ={ version="28.0.0", default-features=false } +sp-npos-elections ={ version="27.0.0", default-features=false } +frame-election-provider-support={ version="29.0.0", default-features=false } +pallet-staking-reward-curve ={ version="11.0.0" } [features] default=['std'] @@ -30,5 +45,9 @@ std=[ 'frame-system/std', 'log/std', 'pallet-staking-extension/std', + 'pallet-balances/std', + 'sp-io/std', + "sp-runtime/std", + "pallet-parameters/std", ] try-runtime=['frame-support/try-runtime'] diff --git a/pallets/attestation/src/lib.rs b/pallets/attestation/src/lib.rs index 92237c685..5f5ed0bdb 100644 --- a/pallets/attestation/src/lib.rs +++ b/pallets/attestation/src/lib.rs @@ -23,11 +23,11 @@ pub use pallet::*; // pub mod weights; -// #[cfg(test)] -// mod mock; +#[cfg(test)] +mod mock; -// #[cfg(test)] -// mod tests; +#[cfg(test)] +mod tests; #[frame_support::pallet] pub mod pallet { @@ -42,7 +42,14 @@ pub mod pallet { pub struct Pallet(_); #[pallet::config] - pub trait Config: frame_system::Config + pallet_staking_extension::Config { + pub trait Config: + frame_system::Config + + pallet_staking_extension::Config + + pallet_session::Config + + frame_system::Config + + pallet_staking_extension::Config + + pallet_parameters::Config + { /// The overarching event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; } diff --git a/pallets/attestation/src/mock.rs b/pallets/attestation/src/mock.rs new file mode 100644 index 000000000..ae5625981 --- /dev/null +++ b/pallets/attestation/src/mock.rs @@ -0,0 +1,365 @@ +// Copyright (C) 2023 Entropy Cryptography Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +use frame_election_provider_support::{ + bounds::{ElectionBounds, ElectionBoundsBuilder}, + onchain, SequentialPhragmen, VoteWeight, +}; +use frame_support::{ + derive_impl, parameter_types, + traits::{ConstU32, OneSessionHandler, Randomness}, +}; +use frame_system as system; +use frame_system::EnsureRoot; +use pallet_session::historical as pallet_session_historical; +use sp_core::H256; +use sp_runtime::{ + curve::PiecewiseLinear, + testing::{TestXt, UintAuthorityId}, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, + BuildStorage, Perbill, +}; +use sp_staking::{EraIndex, SessionIndex}; +use std::cell::RefCell; + +use crate as pallet_attestation; + +const NULL_ARR: [u8; 32] = [0; 32]; +type Block = frame_system::mocking::MockBlock; +type BlockNumber = u64; +type AccountId = u64; +type Balance = u64; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test + { + Attestation: pallet_attestation, + System: frame_system, + Balances: pallet_balances, + // Authorship: pallet_authorship, + Timestamp: pallet_timestamp, + Staking: pallet_staking_extension, + FrameStaking: pallet_staking, + Session: pallet_session, + Historical: pallet_session_historical, + BagsList: pallet_bags_list, + Parameters: pallet_parameters, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl system::Config for Test { + type AccountData = pallet_balances::AccountData; + type AccountId = u64; + type BaseCallFilter = frame_support::traits::Everything; + type Block = Block; + type BlockHashCount = BlockHashCount; + type BlockLength = (); + type BlockWeights = (); + type DbWeight = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type Lookup = IdentityLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; + type Nonce = u64; + type OnKilledAccount = (); + type OnNewAccount = (); + type OnSetCode = (); + type PalletInfo = PalletInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SS58Prefix = SS58Prefix; + type SystemWeightInfo = (); + type Version = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = 3; +} + +impl pallet_timestamp::Config for Test { + type MinimumPeriod = MinimumPeriod; + type Moment = u64; + type OnTimestampSet = (); + type WeightInfo = (); +} + +parameter_types! { + pub const ExistentialDeposit: Balance = 10; + pub const MaxLocks: u32 = 5; +} +impl pallet_balances::Config for Test { + type AccountStore = System; + type Balance = Balance; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type FreezeIdentifier = (); + type MaxFreezes = (); + + type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = RuntimeFreezeReason; + type WeightInfo = (); +} + +pub struct OtherSessionHandler; +impl OneSessionHandler for OtherSessionHandler { + type Key = UintAuthorityId; + + fn on_genesis_session<'a, I>(_: I) + where + I: Iterator + 'a, + AccountId: 'a, + { + } + + fn on_new_session<'a, I>(_: bool, _: I, _: I) + where + I: Iterator + 'a, + AccountId: 'a, + { + } + + fn on_disabled(_validator_index: u32) {} +} + +impl sp_runtime::BoundToRuntimeAppPublic for OtherSessionHandler { + type Public = UintAuthorityId; +} + +parameter_types! { + pub const Period: BlockNumber = 5; + pub const Offset: BlockNumber = 0; +} + +sp_runtime::impl_opaque_keys! { + pub struct SessionKeys { + pub other: OtherSessionHandler, + } +} + +parameter_types! { + pub static ElectionsBounds: ElectionBounds = ElectionBoundsBuilder::default().build(); +} + +pub struct OnChainSeqPhragmen; +impl onchain::Config for OnChainSeqPhragmen { + type DataProvider = FrameStaking; + type MaxWinners = ConstU32<100>; + type Solver = SequentialPhragmen; + type System = Test; + type Bounds = ElectionsBounds; + type WeightInfo = (); +} + +pallet_staking_reward_curve::build! { + const REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000u64, + max_inflation: 0_100_000, + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} +parameter_types! { + pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &REWARD_CURVE; + + pub const MaxKeys: u32 = 10_000; + pub const MaxPeerInHeartbeats: u32 = 10_000; + pub const MaxPeerDataEncodingSize: u32 = 1_000; +} + +impl frame_system::offchain::SendTransactionTypes for Test +where + RuntimeCall: From, +{ + type Extrinsic = TestXt; + type OverarchingCall = RuntimeCall; +} + +const THRESHOLDS: [sp_npos_elections::VoteWeight; 9] = + [10, 20, 30, 40, 50, 60, 1_000, 2_000, 10_000]; + +parameter_types! { + pub static BagThresholds: &'static [sp_npos_elections::VoteWeight] = &THRESHOLDS; +} + +impl pallet_bags_list::Config for Test { + type BagThresholds = BagThresholds; + type RuntimeEvent = RuntimeEvent; + type Score = VoteWeight; + type ScoreProvider = FrameStaking; + type WeightInfo = (); +} + +parameter_types! { + pub const SessionsPerEra: SessionIndex = 2; + pub const BondingDuration: EraIndex = 0; + pub const SlashDeferDuration: EraIndex = 0; + pub const AttestationPeriod: u64 = 100; + pub const ElectionLookahead: u64 = 0; + pub const StakingUnsignedPriority: u64 = u64::MAX / 2; + pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); +} + +pub struct StakingBenchmarkingConfig; +impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig { + type MaxNominators = ConstU32<1000>; + type MaxValidators = ConstU32<1000>; +} + +impl pallet_staking::Config for Test { + type AdminOrigin = frame_system::EnsureRoot; + type BenchmarkingConfig = StakingBenchmarkingConfig; + type BondingDuration = BondingDuration; + type Currency = Balances; + type CurrencyBalance = Balance; + type CurrencyToVote = (); + type ElectionProvider = onchain::OnChainExecution; + type EraPayout = pallet_staking::ConvertCurve; + type EventListeners = (); + type GenesisElectionProvider = Self::ElectionProvider; + type HistoryDepth = ConstU32<84>; + type MaxExposurePageSize = ConstU32<64>; + type MaxControllersInDeprecationBatch = ConstU32<100>; + type MaxUnlockingChunks = ConstU32<32>; + type NextNewSession = Session; + type NominationsQuota = pallet_staking::FixedNominationsQuota<16>; + type OffendingValidatorsThreshold = OffendingValidatorsThreshold; + type Reward = (); + type RewardRemainder = (); + type RuntimeEvent = RuntimeEvent; + type SessionInterface = Self; + type SessionsPerEra = SessionsPerEra; + type Slash = (); + type SlashDeferDuration = SlashDeferDuration; + type TargetList = pallet_staking::UseValidatorsMap; + type UnixTime = pallet_timestamp::Pallet; + type VoterList = BagsList; + type WeightInfo = (); +} + +impl pallet_session::Config for Test { + type Keys = UintAuthorityId; + type NextSessionRotation = pallet_session::PeriodicSessions; + type RuntimeEvent = RuntimeEvent; + type SessionHandler = (OtherSessionHandler,); + type SessionManager = pallet_session::historical::NoteHistoricalRoot; + type ShouldEndSession = pallet_session::PeriodicSessions; + type ValidatorId = AccountId; + type ValidatorIdOf = ConvertInto; + type WeightInfo = (); +} + +impl pallet_session::historical::Config for Test { + type FullIdentification = pallet_staking::Exposure; + type FullIdentificationOf = pallet_staking::ExposureOf; +} + +thread_local! { + pub static LAST_RANDOM: RefCell> = RefCell::new(None); +} + +pub struct TestPastRandomness; +impl Randomness for TestPastRandomness { + fn random(_subject: &[u8]) -> (H256, u64) { + LAST_RANDOM.with(|p| { + if let Some((output, known_since)) = &*p.borrow() { + (*output, *known_since) + } else { + (H256::zero(), frame_system::Pallet::::block_number()) + } + }) + } +} +parameter_types! { + pub const MaxEndpointLength: u32 = 3; +} +impl pallet_staking_extension::Config for Test { + type Currency = Balances; + type MaxEndpointLength = MaxEndpointLength; + type Randomness = TestPastRandomness; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + +parameter_types! { + pub const UncleGenerations: u64 = 0; +} + +// Author of block is always 11 +// pub struct Author11; +// impl FindAuthor for Author11 { +// fn find_author<'a, I>(_digests: I) -> Option +// where +// I: 'a + IntoIterator, +// { +// Some(11) +// } +// } + +// impl pallet_authorship::Config for Test { +// type EventHandler = (); +// type FindAuthor = Author11; +// } + +parameter_types! { + pub const MaxProgramHashes: u32 = 5u32; + pub const KeyVersionNumber: u8 = 1; +} + +// impl pallet_registry::Config for Test { +// type RuntimeEvent = RuntimeEvent; +// type MaxProgramHashes = MaxProgramHashes; +// type KeyVersionNumber = KeyVersionNumber; +// type WeightInfo = (); +// } + +parameter_types! { + pub const MaxBytecodeLength: u32 = 3; + pub const ProgramDepositPerByte: u32 = 5; + pub const MaxOwnedPrograms: u32 = 5; +} + +// impl pallet_programs::Config for Test { +// type Currency = Balances; +// type MaxBytecodeLength = MaxBytecodeLength; +// type ProgramDepositPerByte = ProgramDepositPerByte; +// type MaxOwnedPrograms = MaxOwnedPrograms; +// type RuntimeEvent = RuntimeEvent; +// type WeightInfo = (); +// } + +impl pallet_parameters::Config for Test { + type RuntimeEvent = RuntimeEvent; + type UpdateOrigin = EnsureRoot; + type WeightInfo = (); +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + system::GenesisConfig::::default().build_storage().unwrap().into() +} diff --git a/pallets/attestation/src/tests.rs b/pallets/attestation/src/tests.rs new file mode 100644 index 000000000..32967852f --- /dev/null +++ b/pallets/attestation/src/tests.rs @@ -0,0 +1,25 @@ +// Copyright (C) 2023 Entropy Cryptography Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// use frame_support::{assert_noop, assert_ok, traits::Currency}; +// use pallet_balances::Error as BalancesError; +// use sp_runtime::traits::Hash; +// +use crate::mock::*; + +#[test] +fn attest() { + new_test_ext().execute_with(|| {}) +}