Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

Commit

Permalink
Add governance config for solo node. (#394)
Browse files Browse the repository at this point in the history
* [solo-node] add technical_committee and adjust some parameters

* [solo-node] move governance stuff to its own file.

* [solo-node] only the council may submit proposals.

* [solo-node] update the council to be five accounts

* [solo-node] remove unused import

* [solo-node] implement signer is collective member trait

* [solo-node] cleanup

* [solo-node] add alice to technical committee and remove dave

* [solo-node] fix minimal proposal deposit

* [solo-node] consistent default voting scheme

* [solo-node] fix comments

* [solo-node] fix runtime benchmarks compilation

* [solo-node] fix clippy
  • Loading branch information
clangenb authored Feb 6, 2024
1 parent 8152444 commit fe891f2
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 105 deletions.
22 changes: 18 additions & 4 deletions node/service/src/chain_spec/solo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use crate::chain_spec::{chain_spec_properties, get_well_known_accounts};
use ajuna_primitives::Balance;
use ajuna_solo_runtime::{
currency::AJUNS, AssetsConfig, AuraConfig, BalancesConfig, CouncilConfig, GrandpaConfig,
RuntimeGenesisConfig, SudoConfig, SystemConfig, VestingConfig, WASM_BINARY,
RuntimeGenesisConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, VestingConfig,
WASM_BINARY,
};
use sc_service::ChainType;

Expand Down Expand Up @@ -71,6 +72,7 @@ struct Config {
grandpa: GrandpaConfig,
sudo: SudoConfig,
council: CouncilConfig,
technical_committee: TechnicalCommitteeConfig,
balances: BalancesConfig,
assets: AssetsConfig,
vesting: VestingConfig,
Expand All @@ -95,7 +97,17 @@ fn development_config_genesis() -> RuntimeGenesisConfig {
grandpa: GrandpaConfig { authorities: grandpa_authorities, ..Default::default() },
sudo: SudoConfig { key: Some(accounts.alice.clone()) },
council: CouncilConfig {
members: vec![accounts.bob.clone(), accounts.charlie.clone(), accounts.dave.clone()],
members: vec![
accounts.alice.clone(),
accounts.bob.clone(),
accounts.charlie.clone(),
accounts.dave.clone(),
accounts.eve.clone(),
],
phantom: Default::default(),
},
technical_committee: TechnicalCommitteeConfig {
members: vec![accounts.alice.clone(), accounts.bob.clone(), accounts.charlie.clone()],
phantom: Default::default(),
},
balances: BalancesConfig {
Expand Down Expand Up @@ -161,6 +173,7 @@ fn testnet_config_genesis() -> RuntimeGenesisConfig {
},
sudo: SudoConfig { key: Some(accounts.alice.clone()) },
council: CouncilConfig::default(),
technical_committee: TechnicalCommitteeConfig::default(),
balances: BalancesConfig {
balances: vec![
(accounts.alice, INITIAL_BALANCE),
Expand All @@ -187,20 +200,21 @@ fn compose_genesis_config(config: Config) -> RuntimeGenesisConfig {
let wasm_binary = WASM_BINARY.expect(
"Development wasm binary is not available. Please rebuild with SKIP_WASM_BUILD disabled.",
);
let Config { aura, grandpa, sudo, council, balances, assets, vesting } = config;
let Config { aura, grandpa, sudo, council, technical_committee, balances, assets, vesting } =
config;
RuntimeGenesisConfig {
// overridden config
aura,
grandpa,
sudo,
council,
technical_committee,
balances,
assets,
vesting,
// default config
system: SystemConfig { code: wasm_binary.to_vec(), ..Default::default() },
transaction_payment: Default::default(),
council_membership: Default::default(),
treasury: Default::default(),
democracy: Default::default(),
awesome_avatars: Default::default(),
Expand Down
155 changes: 155 additions & 0 deletions runtime/solo/src/gov.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use crate::{
BlockWeights, OriginCaller, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, AJUNS, DAYS,
};
use ajuna_primitives::{AccountId, Balance, BlockNumber};
use frame_support::{
dispatch::RawOrigin,
parameter_types,
traits::{ConstBool, ConstU32, EitherOfDiverse, EnsureOrigin},
weights::Weight,
};
use frame_system::EnsureRoot;
use pallet_collective::{EnsureMember, EnsureProportionAtLeast, EnsureProportionMoreThan};
use sp_runtime::Perbill;
use sp_std::marker::PhantomData;

pub type EnsureRootOrMoreThanHalfCouncil = EitherOfDiverse<
EnsureRoot<AccountId>,
EnsureProportionMoreThan<AccountId, CouncilCollective, 1, 2>,
>;

pub type EnsureRootOrMoreThanHalfTechnicalCommittee = EitherOfDiverse<
EnsureRoot<AccountId>,
EnsureProportionAtLeast<AccountId, TechnicalCommitteeInstance, 1, 2>,
>;

pub type EnsureRootOrAllTechnicalCommittee = EitherOfDiverse<
EnsureRoot<AccountId>,
EnsureProportionAtLeast<AccountId, TechnicalCommitteeInstance, 1, 1>,
>;

type AccountIdFor<T> = <T as frame_system::Config>::AccountId;

/// Ensures that the signer of a transaction is a member of said collective instance.
///
/// This is fundamentally different from the `pallet_collective::EnsureMember`,
/// which checks if the referendum to be executed has been ayed by any member.
/// It is a different kind of origin.
pub struct EnsureSignerIsCollectiveMember<T, I: 'static>(PhantomData<(T, I)>);
impl<
O: Into<Result<RawOrigin<AccountIdFor<T>>, O>> + From<RawOrigin<AccountIdFor<T>>>,
T: pallet_collective::Config<I>,
I,
> EnsureOrigin<O> for EnsureSignerIsCollectiveMember<T, I>
{
type Success = AccountIdFor<T>;
fn try_origin(o: O) -> Result<Self::Success, O> {
o.into().and_then(|o| match o {
RawOrigin::Signed(a) if pallet_collective::Pallet::<T, I>::is_member(&a) => Ok(a),
r => Err(O::from(r)),
})
}

#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin() -> Result<O, ()> {
use parity_scale_codec::Decode;
use sp_runtime::traits::TrailingZeroInput;
let zero_account_id =
<AccountIdFor<T>>::decode(&mut TrailingZeroInput::zeroes()).map_err(|_| ())?;
Ok(O::from(RawOrigin::Signed(zero_account_id)))
}
}

/// Council collective instance declaration.
///
/// The council primarily serves to optimize and balance the inclusive referendum system,
/// by being allowed to propose external democracy proposals, which can be fast tracked and
/// bypass the one active referendum at a time rule.
///
/// It also controls the treasury.
type CouncilCollective = pallet_collective::Instance1;

parameter_types! {
pub CouncilMotionDuration: BlockNumber = 3 * DAYS;
pub MaxProposalWeight: Weight = Perbill::from_percent(50) * BlockWeights::get().max_block;
}

impl pallet_collective::Config<CouncilCollective> for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type Proposal = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type MotionDuration = CouncilMotionDuration;
type MaxProposals = ConstU32<100>;
type MaxMembers = ConstU32<100>;
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
type SetMembersOrigin = EnsureRootOrMoreThanHalfCouncil;
type MaxProposalWeight = MaxProposalWeight;
}

/// The technical committee primarily serves to safeguard against malicious referenda,
/// and fast track critical referenda.
pub type TechnicalCommitteeInstance = pallet_collective::Instance2;

parameter_types! {
pub const TechnicalMotionDuration: BlockNumber = 3 * DAYS;
}

impl pallet_collective::Config<TechnicalCommitteeInstance> for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type Proposal = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type MotionDuration = TechnicalMotionDuration;
type MaxProposals = ConstU32<100>;
type MaxMembers = ConstU32<100>;
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
type SetMembersOrigin = EnsureRootOrMoreThanHalfCouncil;
type MaxProposalWeight = MaxProposalWeight;
}

parameter_types! {
pub const ThreeDays: BlockNumber = 3 * DAYS;
pub const TwentyEightDays: BlockNumber = 28 * DAYS;
pub const ThirtyDays: BlockNumber = 30 * DAYS;
pub EnactmentPeriod: BlockNumber = 7 * DAYS;
pub const MinimumDeposit: Balance = AJUNS;
}

impl pallet_democracy::Config for Runtime {
type WeightInfo = pallet_democracy::weights::SubstrateWeight<Runtime>;
type RuntimeEvent = RuntimeEvent;
type Scheduler = pallet_scheduler::Pallet<Runtime>;
type Preimages = pallet_preimage::Pallet<Runtime>;
type Currency = pallet_balances::Pallet<Runtime>;
type EnactmentPeriod = EnactmentPeriod;
type LaunchPeriod = TwentyEightDays;
type VotingPeriod = TwentyEightDays;
type VoteLockingPeriod = EnactmentPeriod;
type MinimumDeposit = MinimumDeposit;
type InstantAllowed = ConstBool<true>;
type FastTrackVotingPeriod = ThreeDays;
type CooloffPeriod = TwentyEightDays;
type MaxVotes = ConstU32<100>;
type MaxProposals = ConstU32<100>;
type MaxDeposits = ConstU32<100>;
type MaxBlacklisted = ConstU32<100>;
type ExternalOrigin = EnsureRootOrMoreThanHalfCouncil;
type ExternalMajorityOrigin = EnsureRootOrMoreThanHalfCouncil;
type ExternalDefaultOrigin = EnsureRootOrMoreThanHalfCouncil;
// Initially, we want that only the council can submit proposals to
// prevent malicious proposals.
type SubmitOrigin = EnsureSignerIsCollectiveMember<Runtime, CouncilCollective>;
type FastTrackOrigin = EnsureRootOrMoreThanHalfTechnicalCommittee;
type InstantOrigin = EnsureRootOrMoreThanHalfTechnicalCommittee;
// To cancel a proposal that has passed.
type CancellationOrigin = EnsureRoot<AccountId>;
type BlacklistOrigin = EnsureRootOrMoreThanHalfCouncil;
// To cancel a proposal before it has passed, and slash its backers.
type CancelProposalOrigin = EnsureRootOrAllTechnicalCommittee;
// Any single technical committee member may veto a coming council proposal, however they can
// only do it once and it lasts only for the cooloff period.
type VetoOrigin = EnsureMember<AccountId, TechnicalCommitteeInstance>;
type PalletsOrigin = OriginCaller;
type Slash = pallet_treasury::Pallet<Runtime>;
}
95 changes: 17 additions & 78 deletions runtime/solo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));

use crate::gov::EnsureRootOrMoreThanHalfCouncil;
use frame_support::{
construct_runtime, parameter_types,
traits::{AsEnsureOriginWithArg, ConstBool, Contains},
Expand Down Expand Up @@ -58,6 +59,7 @@ use sp_version::NativeVersion;
use sp_version::RuntimeVersion;

mod consts;
mod gov;
mod impls;
mod types;

Expand All @@ -69,7 +71,6 @@ pub use consts::currency;
use consts::{currency::*, time::*};
use impls::{CreditToTreasury, OneToOneConversion};
use pallet_nfts::Call as NftsCall;
use types::governance::*;

pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
Expand All @@ -82,6 +83,12 @@ impl_opaque_keys! {
}
}

parameter_types! {
pub const OneDay: BlockNumber = DAYS;
pub const OneWeek: BlockNumber = 7 * DAYS;
pub const TwoWeeks: BlockNumber = 14 * DAYS;
}

// To learn more about runtime versioning and what each of the following value means:
// https://docs.substrate.io/v3/runtime/upgrades#runtime-versioning
#[sp_version::runtime_version]
Expand Down Expand Up @@ -300,39 +307,8 @@ parameter_types! {
pub const ZeroPercent: Permill = Permill::from_percent(0);
pub const FivePercent: Permill = Permill::from_percent(5);
pub const FiftyPercent: Permill = Permill::from_percent(50);
pub const MinimumProposalBond: Balance = 1;
pub const Fortnightly: BlockNumber = 14 * DAYS;
pub const Weekly: BlockNumber = 7 * DAYS;
pub const Daily: BlockNumber = DAYS;
pub const CouncilMaxMembers: u32 = 100;
pub MaxProposalWeight: Weight = Perbill::from_percent(50) * BlockWeights::get().max_block;
}

type CouncilCollective = pallet_collective::Instance2;
impl pallet_collective::Config<CouncilCollective> for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type Proposal = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type MotionDuration = Weekly;
type MaxProposals = frame_support::traits::ConstU32<100>;
type MaxMembers = CouncilMaxMembers;
type DefaultVote = pallet_collective::PrimeDefaultVote;
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
type SetMembersOrigin = EnsureRoot<AccountId>;
type MaxProposalWeight = MaxProposalWeight;
}

impl pallet_membership::Config<pallet_membership::Instance2> for Runtime {
type RuntimeEvent = RuntimeEvent;
type AddOrigin = EnsureRootOrMoreThanHalfCouncil;
type RemoveOrigin = EnsureRootOrMoreThanHalfCouncil;
type SwapOrigin = EnsureRootOrMoreThanHalfCouncil;
type ResetOrigin = EnsureRootOrAtLeastTwoThirdsCouncil;
type PrimeOrigin = EnsureRootOrAtLeastTwoThirdsCouncil;
type MembershipInitialized = Council;
type MembershipChanged = Council;
type MaxMembers = CouncilMaxMembers;
type WeightInfo = pallet_membership::weights::SubstrateWeight<Runtime>;
pub const MinimumProposalBond: Balance = 10 * AJUNS;
pub const MaximumProposalBond: Balance = 1000 * AJUNS;
}

impl pallet_treasury::Config for Runtime {
Expand All @@ -343,54 +319,15 @@ impl pallet_treasury::Config for Runtime {
type OnSlash = ();
type ProposalBond = FivePercent;
type ProposalBondMinimum = MinimumProposalBond;
type ProposalBondMaximum = ();
type SpendPeriod = Weekly;
type ProposalBondMaximum = MaximumProposalBond;
type SpendPeriod = OneWeek;
type Burn = ZeroPercent;
type PalletId = TreasuryPalletId;
type BurnDestination = ();
type WeightInfo = pallet_treasury::weights::SubstrateWeight<Runtime>;
type SpendFunds = ();
type SpendOrigin = frame_support::traits::NeverEnsureOrigin<Balance>;
type MaxApprovals = frame_support::traits::ConstU32<100>;
}

parameter_types! {
pub const ThirtyDays: BlockNumber = 30 * DAYS;
pub const TwentyEightDays: BlockNumber = 28 * DAYS;
pub const ThreeDays: BlockNumber = 3 * DAYS;
pub const MinimumDeposit: Balance = 1;
}

impl pallet_democracy::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type EnactmentPeriod = ThirtyDays;
type LaunchPeriod = TwentyEightDays;
type VotingPeriod = TwentyEightDays;
type VoteLockingPeriod = ThirtyDays;
type MinimumDeposit = MinimumDeposit;
type ExternalOrigin = EnsureAtLeastHalfCouncil;
type ExternalMajorityOrigin = EnsureAtLeastThreeFourthsCouncil;
type ExternalDefaultOrigin = EnsureAllCouncil;
type SubmitOrigin = EnsureSigned<AccountId>;
type FastTrackOrigin = EnsureAtLeastThreeFourthsCouncil;
type InstantOrigin = EnsureAllCouncil;
type InstantAllowed = frame_support::traits::ConstBool<true>;
type FastTrackVotingPeriod = ThreeDays;
type CancellationOrigin = EnsureAtLeastThreeFourthsCouncil;
type BlacklistOrigin = EnsureRoot<AccountId>;
type CancelProposalOrigin = EnsureAllCouncil;
type VetoOrigin = pallet_collective::EnsureMember<AccountId, CouncilCollective>;
type CooloffPeriod = TwentyEightDays;
type Slash = Treasury;
type Scheduler = Scheduler;
type PalletsOrigin = OriginCaller;
type MaxVotes = frame_support::traits::ConstU32<100>;
type WeightInfo = pallet_democracy::weights::SubstrateWeight<Runtime>;
type MaxProposals = frame_support::traits::ConstU32<100>;
type Preimages = Preimage;
type MaxDeposits = frame_support::traits::ConstU32<100>;
type MaxBlacklisted = frame_support::traits::ConstU32<100>;
type SpendOrigin = frame_support::traits::NeverEnsureOrigin<Balance>;
}

impl<LocalCall> frame_system::offchain::CreateSignedTransaction<LocalCall> for Runtime
Expand Down Expand Up @@ -700,8 +637,10 @@ construct_runtime!(
AssetTxPayment: pallet_asset_tx_payment = 6,
Assets: pallet_assets = 7,
Vesting: orml_vesting = 8,
Council: pallet_collective::<Instance2> = 9,
CouncilMembership: pallet_membership::<Instance2> = 10,
// pub type CouncilCollective = pallet_collective::Instance1;
Council: pallet_collective::<Instance1> = 9,
// pub type TechnicalCommitteeInstance = pallet_collective::Instance2;
TechnicalCommittee: pallet_collective::<Instance2> = 10,
Treasury: pallet_treasury = 11,
Democracy: pallet_democracy = 12,
Sudo: pallet_sudo = 13,
Expand Down
Loading

0 comments on commit fe891f2

Please sign in to comment.