From f4fe97a75f4cb46cbcc71bc68a3f3dcc870d9058 Mon Sep 17 00:00:00 2001 From: Nisheeth Barthwal Date: Wed, 2 Aug 2023 14:24:51 +0200 Subject: [PATCH] [MOON-2519] Use moonbeam generated conviction voting weights (#2417) * enable benchmarks for conviction voting * use moonbeam runtime weights for pallet-conviction-voting * add tests --- Cargo.lock | 1 + runtime/common/Cargo.toml | 6 +- runtime/common/src/apis.rs | 11 ++ runtime/common/src/lib.rs | 1 + runtime/common/src/weights/mod.rs | 19 ++ .../src/weights/pallet_conviction_voting.rs | 183 ++++++++++++++++++ runtime/moonbase/src/governance/referenda.rs | 3 +- .../test-conviction-voting/test-delegate.ts | 102 ++++++++++ 8 files changed, 324 insertions(+), 2 deletions(-) create mode 100644 runtime/common/src/weights/mod.rs create mode 100644 runtime/common/src/weights/pallet_conviction_voting.rs create mode 100644 tests/tests/test-conviction-voting/test-delegate.ts diff --git a/Cargo.lock b/Cargo.lock index 73eff1167b..7aea5877ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6000,6 +6000,7 @@ dependencies = [ "pallet-author-slot-filter", "pallet-base-fee", "pallet-collective", + "pallet-conviction-voting", "pallet-democracy", "pallet-ethereum-xcm", "pallet-evm", diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 7dff076f0e..40a2611848 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -19,6 +19,7 @@ pallet-author-mapping = { workspace = true } pallet-ethereum-xcm = { workspace = true } pallet-migrations = { workspace = true } pallet-parachain-staking = { workspace = true } +pallet-conviction-voting = { workspace = true } pallet-randomness = { workspace = true } pallet-xcm-transactor = { workspace = true } precompile-utils = { workspace = true } @@ -74,7 +75,10 @@ std = [ "xcm-executor/std", "xcm/std", ] -runtime-benchmarks = [ "pallet-ethereum-xcm/runtime-benchmarks", "pallet-referenda/runtime-benchmarks" ] +runtime-benchmarks = [ + "pallet-ethereum-xcm/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", +] try-runtime = [ "frame-support/try-runtime", "pallet-migrations/try-runtime", diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index ddf3fa0dbc..4fad33d492 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -565,6 +565,7 @@ macro_rules! impl_runtime_apis_plus_common { use pallet_randomness::Pallet as RandomnessBench; use pallet_migrations::Pallet as MigrationsBench; use MoonbeamXcmBenchmarks::XcmGenericBenchmarks as MoonbeamXcmGenericBench; + use pallet_conviction_voting::Pallet as PalletConvictionVotingBench; let mut list = Vec::::new(); @@ -585,6 +586,7 @@ macro_rules! impl_runtime_apis_plus_common { MoonbeamXcmGenericBench:: ); list_benchmark!(list, extra, pallet_migrations, MigrationsBench::); + list_benchmark!(list, extra, pallet_conviction_voting, PalletConvictionVotingBench::); let storage_info = AllPalletsWithSystem::storage_info(); @@ -716,6 +718,7 @@ macro_rules! impl_runtime_apis_plus_common { use pallet_xcm_transactor::Pallet as XcmTransactorBench; use pallet_randomness::Pallet as RandomnessBench; use pallet_migrations::Pallet as MigrationsBench; + use pallet_conviction_voting::Pallet as PalletConvictionVotingBench; use MoonbeamXcmBenchmarks::XcmGenericBenchmarks as MoonbeamXcmGenericBench; let whitelist: Vec = vec![ @@ -842,6 +845,14 @@ macro_rules! impl_runtime_apis_plus_common { MoonbeamXcmGenericBench:: ); + add_benchmark!( + params, + batches, + pallet_conviction_voting, + PalletConvictionVotingBench:: + ); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()); } diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 4f17253801..8688e54c07 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -23,3 +23,4 @@ mod impl_on_charge_evm_transaction; mod impl_self_contained_call; mod impl_xcm_evm_runner; pub mod migrations; +pub mod weights; diff --git a/runtime/common/src/weights/mod.rs b/runtime/common/src/weights/mod.rs new file mode 100644 index 0000000000..5d44562ee8 --- /dev/null +++ b/runtime/common/src/weights/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Moonbeam common weights. + +pub mod pallet_conviction_voting; diff --git a/runtime/common/src/weights/pallet_conviction_voting.rs b/runtime/common/src/weights/pallet_conviction_voting.rs new file mode 100644 index 0000000000..8caa56a557 --- /dev/null +++ b/runtime/common/src/weights/pallet_conviction_voting.rs @@ -0,0 +1,183 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + + +//! Autogenerated weights for pallet_conviction_voting +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `nish-pc`, CPU: `AMD Ryzen 9 5900X 12-Core Processor` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --execution=wasm +// --wasm-execution=compiled +// --pallet +// pallet_conviction_voting +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --template=./benchmarking/frame-weight-template.hbs +// --json-file +// raw.json +// --output +// weights.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for pallet_conviction_voting using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl pallet_conviction_voting::weights::WeightInfo for SubstrateWeight { + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27229), added: 29704, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(119), added: 2594, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:1 w:1) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn vote_new() -> Weight { + // Proof Size summary in bytes: + // Measured: `13155` + // Estimated: `85835` + // Minimum execution time: 101_782_000 picoseconds. + Weight::from_parts(105_579_000, 85835) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27229), added: 29704, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(119), added: 2594, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn vote_existing() -> Weight { + // Proof Size summary in bytes: + // Measured: `13876` + // Estimated: `127273` + // Minimum execution time: 176_472_000 picoseconds. + Weight::from_parts(179_026_000, 127273) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27229), added: 29704, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:1) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + fn remove_vote() -> Weight { + // Proof Size summary in bytes: + // Measured: `13520` + // Estimated: `118937` + // Minimum execution time: 157_035_000 picoseconds. + Weight::from_parts(161_313_000, 118937) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27229), added: 29704, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:1 w:0) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + fn remove_other_vote() -> Weight { + // Proof Size summary in bytes: + // Measured: `12644` + // Estimated: `35071` + // Minimum execution time: 50_755_000 picoseconds. + Weight::from_parts(53_090_000, 35071) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27229), added: 29704, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:100 w:100) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(119), added: 2594, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 100]`. + fn delegate(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `7235 + r * (386 ±0)` + // Estimated: `153590 + r * (3387 ±0)` + // Minimum execution time: 48_602_000 picoseconds. + Weight::from_parts(34_823_147, 153590) + // Standard Error: 732_665 + .saturating_add(Weight::from_parts(82_938_442, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) + .saturating_add(Weight::from_parts(0, 3387).saturating_mul(r.into())) + } + /// Storage: ConvictionVoting VotingFor (r:2 w:2) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27229), added: 29704, mode: MaxEncodedLen) + /// Storage: Referenda ReferendumInfoFor (r:100 w:100) + /// Proof: Referenda ReferendumInfoFor (max_values: None, max_size: Some(912), added: 3387, mode: MaxEncodedLen) + /// Storage: Scheduler Agenda (r:2 w:2) + /// Proof: Scheduler Agenda (max_values: None, max_size: Some(38963), added: 41438, mode: MaxEncodedLen) + /// The range of component `r` is `[0, 100]`. + fn undelegate(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `7020 + r * (386 ±0)` + // Estimated: `145254 + r * (3387 ±0)` + // Minimum execution time: 40_486_000 picoseconds. + Weight::from_parts(43_021_000, 145254) + // Standard Error: 378_061 + .saturating_add(Weight::from_parts(89_418_651, 0).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) + .saturating_add(Weight::from_parts(0, 3387).saturating_mul(r.into())) + } + /// Storage: ConvictionVoting VotingFor (r:1 w:1) + /// Proof: ConvictionVoting VotingFor (max_values: None, max_size: Some(27229), added: 29704, mode: MaxEncodedLen) + /// Storage: ConvictionVoting ClassLocksFor (r:1 w:1) + /// Proof: ConvictionVoting ClassLocksFor (max_values: None, max_size: Some(119), added: 2594, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + fn unlock() -> Weight { + // Proof Size summary in bytes: + // Measured: `11936` + // Estimated: `39030` + // Minimum execution time: 85_281_000 picoseconds. + Weight::from_parts(94_197_000, 39030) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } +} diff --git a/runtime/moonbase/src/governance/referenda.rs b/runtime/moonbase/src/governance/referenda.rs index a960afda94..1cc91686bb 100644 --- a/runtime/moonbase/src/governance/referenda.rs +++ b/runtime/moonbase/src/governance/referenda.rs @@ -24,6 +24,7 @@ use super::*; use crate::currency::*; use frame_support::traits::{EitherOf, MapSuccess}; use frame_system::EnsureRootWithSuccess; +use moonbeam_runtime_common::weights as moonbeam_weights; use sp_runtime::traits::Replace; parameter_types! { @@ -31,7 +32,7 @@ parameter_types! { } impl pallet_conviction_voting::Config for Runtime { - type WeightInfo = pallet_conviction_voting::weights::SubstrateWeight; + type WeightInfo = moonbeam_weights::pallet_conviction_voting::SubstrateWeight; type RuntimeEvent = RuntimeEvent; type Currency = Balances; type Polls = Referenda; diff --git a/tests/tests/test-conviction-voting/test-delegate.ts b/tests/tests/test-conviction-voting/test-delegate.ts new file mode 100644 index 0000000000..7238247460 --- /dev/null +++ b/tests/tests/test-conviction-voting/test-delegate.ts @@ -0,0 +1,102 @@ +import "@moonbeam-network/api-augment"; + +import { expect } from "chai"; + +import { alith, generateKeyringPair } from "../../util/accounts"; +import { expectOk } from "../../util/expect"; +import { describeDevMoonbeam, DevTestContext } from "../../util/setup-dev-tests"; +import { MIN_GLMR_STAKING, GLMR } from "../../util/constants"; +import { KeyringPair } from "@substrate/txwrapper-core"; +import { chunk } from "../../util/common"; + +const debug = require("debug")("test:convictionVoting"); + +describeDevMoonbeam("Conviction Voting - delegate", (context) => { + it("should delegate at least 10 txs in a block", async () => { + const randomAccounts = await createAccounts(context, 100); + + await context.createBlock( + randomAccounts.map((account) => + context.polkadotApi.tx.convictionVoting + .delegate(1, alith.address, 1, 1000000000000000000n) + .signAsync(account) + ) + ); + + const events = await context.polkadotApi.query.system.events(); + const delegatedEvents = events.reduce((acc, event) => { + if (context.polkadotApi.events.convictionVoting.Delegated.is(event.event)) { + acc.push({ + from: event.event.data[0].toString(), + to: event.event.data[1].toString(), + }); + } + + return acc; + }, []); + + expect(delegatedEvents.length).to.be.greaterThanOrEqual(10); + }); +}); + +describeDevMoonbeam("Conviction Voting - undelegate", (context) => { + let randomAccounts = []; + + before("should delegate 50 accounts", async () => { + randomAccounts = await createAccounts(context, 50); + + for (const randomChunk of chunk(randomAccounts, 10)) { + await expectOk( + context.createBlock( + randomChunk.map((account) => + context.polkadotApi.tx.convictionVoting + .delegate(1, alith.address, 1, 1000000000000000000n) + .signAsync(account) + ) + ) + ); + } + }); + + it("should undelegate at least 10 txs in a block", async () => { + await context.createBlock( + randomAccounts.map((account) => + context.polkadotApi.tx.convictionVoting.undelegate(1).signAsync(account) + ) + ); + + const events = await context.polkadotApi.query.system.events(); + const undelegatedEvents = events.reduce((acc, event) => { + if (context.polkadotApi.events.convictionVoting.Undelegated.is(event.event)) { + acc.push({ + who: event.event.data[0].toString(), + }); + } + + return acc; + }, []); + + console.log(undelegatedEvents.length); + expect(undelegatedEvents.length).to.be.greaterThanOrEqual(10); + }); +}); + +async function createAccounts( + context: DevTestContext, + maxAccounts: number +): Promise { + const randomAccounts = new Array(Number(maxAccounts)).fill(0).map(() => generateKeyringPair()); + + let alithNonce = await context.web3.eth.getTransactionCount(alith.address); + await expectOk( + context.createBlock( + randomAccounts.map((randomCandidate) => + context.polkadotApi.tx.balances + .transfer(randomCandidate.address, MIN_GLMR_STAKING + 1n * GLMR) + .signAsync(alith, { nonce: alithNonce++ }) + ) + ) + ); + + return randomAccounts; +}