Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement proposal type petition #400

Merged
merged 13 commits into from
Aug 26, 2024
Merged
31 changes: 20 additions & 11 deletions communities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ pub mod pallet {
///
/// May only be called from `T::TrustableForNonDestructiveAction`.
#[pallet::call_index(0)]
#[pallet::weight((<T as Config>::WeightInfo::new_community(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::new_community(), DispatchClass::Normal, Pays::Yes)
)]
Comment on lines +95 to +96
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, weird fmt.

pub fn new_community(
origin: OriginFor<T>,
location: Location,
Expand Down Expand Up @@ -168,7 +169,8 @@ pub mod pallet {
///
/// Todo: Replace `T::CommunityMaster` with community governance: #137.
#[pallet::call_index(1)]
#[pallet::weight((<T as Config>::WeightInfo::add_location(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::add_location(), DispatchClass::Normal, Pays::Yes)
)]
pub fn add_location(
origin: OriginFor<T>,
cid: CommunityIdentifier,
Expand All @@ -189,7 +191,8 @@ pub mod pallet {
///
/// Todo: Replace `T::CommunityMaster` with community governance: #137.
#[pallet::call_index(2)]
#[pallet::weight((<T as Config>::WeightInfo::remove_location(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::remove_location(), DispatchClass::Normal, Pays::Yes)
)]
pub fn remove_location(
origin: OriginFor<T>,
cid: CommunityIdentifier,
Expand All @@ -208,7 +211,8 @@ pub mod pallet {
///
/// May only be called from `T::CommunityMaster`.
#[pallet::call_index(3)]
#[pallet::weight((<T as Config>::WeightInfo::update_community_metadata(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::update_community_metadata(), DispatchClass::Normal, Pays::Yes)
)]
pub fn update_community_metadata(
origin: OriginFor<T>,
cid: CommunityIdentifier,
Expand All @@ -219,7 +223,8 @@ pub mod pallet {
}

#[pallet::call_index(4)]
#[pallet::weight((<T as Config>::WeightInfo::update_demurrage(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::update_demurrage(), DispatchClass::Normal, Pays::Yes)
)]
pub fn update_demurrage(
origin: OriginFor<T>,
cid: CommunityIdentifier,
Expand All @@ -230,7 +235,8 @@ pub mod pallet {
}

#[pallet::call_index(5)]
#[pallet::weight((<T as Config>::WeightInfo::update_nominal_income(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::update_nominal_income(), DispatchClass::Normal, Pays::Yes)
)]
pub fn update_nominal_income(
origin: OriginFor<T>,
cid: CommunityIdentifier,
Expand All @@ -241,7 +247,8 @@ pub mod pallet {
}

#[pallet::call_index(6)]
#[pallet::weight((<T as Config>::WeightInfo::set_min_solar_trip_time_s(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::set_min_solar_trip_time_s(), DispatchClass::Normal, Pays::Yes)
)]
pub fn set_min_solar_trip_time_s(
origin: OriginFor<T>,
min_solar_trip_time_s: MinSolarTripTimeType,
Expand All @@ -254,7 +261,8 @@ pub mod pallet {
}

#[pallet::call_index(7)]
#[pallet::weight((<T as Config>::WeightInfo::set_max_speed_mps(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::set_max_speed_mps(), DispatchClass::Normal, Pays::Yes)
)]
pub fn set_max_speed_mps(
origin: OriginFor<T>,
max_speed_mps: MaxSpeedMpsType,
Expand All @@ -267,7 +275,8 @@ pub mod pallet {
}

#[pallet::call_index(8)]
#[pallet::weight((<T as Config>::WeightInfo::purge_community(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::purge_community(), DispatchClass::Normal, Pays::Yes)
)]
pub fn purge_community(
origin: OriginFor<T>,
cid: CommunityIdentifier,
Expand Down Expand Up @@ -726,7 +735,7 @@ impl<T: Config> Pallet<T> {
let dateline_proxy = Location { lat: location.lat, lon: DATELINE_LON };
if Self::haversine_distance(location, &dateline_proxy) < DATELINE_DISTANCE_M {
warn!(target: LOG, "location too close to dateline: {:?}", location);
return Err(<Error<T>>::MinimumDistanceViolationToDateLine)?
return Err(<Error<T>>::MinimumDistanceViolationToDateLine)?;
}

let nearby_locations = Self::get_nearby_locations(location)?;
Expand Down Expand Up @@ -765,7 +774,7 @@ impl<T: Config> Pallet<T> {
if pallet_encointer_balances::Balance::<T>::contains_key(cid, account.clone()) {
balances.push((
cid,
<pallet_encointer_balances::Pallet<T>>::balance_entry(cid, &account.clone()),
<pallet_encointer_balances::Pallet<T>>::balance_entry(cid, account.clone()),
));
}
}
Expand Down
20 changes: 8 additions & 12 deletions communities/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ mod v0 {
pub type IpfsCid = UnboundedPalletString;

#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde_derive", serde(rename_all = "camelCase"))]
pub struct UnboundedCommunityMetadata {
/// utf8 encoded name
pub name: UnboundedPalletString,
Expand Down Expand Up @@ -105,8 +103,6 @@ pub mod v1 {
#[derive(
Encode, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen,
)]
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde_derive", serde(rename_all = "camelCase"))]
pub struct CommunityMetadataV1 {
/// utf8 encoded name
pub name: PalletString,
Expand Down Expand Up @@ -245,7 +241,7 @@ pub mod v2 {
target: TARGET,
"skipping on_runtime_upgrade: executed on wrong storage version."
);
return T::DbWeight::get().reads(1)
return T::DbWeight::get().reads(1);
}
if onchain_version == StorageVersion::new(0) {
CommunityMetadata::<T>::translate::<UnboundedCommunityMetadata, _>(
Expand Down Expand Up @@ -434,13 +430,13 @@ mod test {
// Check that all values got migrated.

assert_eq!(
crate::CommunityIdentifiers::<TestRuntime>::get(),
BoundedVec::<
CommunityIdentifier,
<TestRuntime as Config>::MaxCommunityIdentifiers,
>::try_from(cids)
.unwrap()
);
crate::CommunityIdentifiers::<TestRuntime>::get(),
BoundedVec::<
CommunityIdentifier,
<TestRuntime as Config>::MaxCommunityIdentifiers,
>::try_from(cids)
.unwrap()
);

assert_eq!(
crate::CommunityIdentifiersByGeohash::<TestRuntime>::get(
Expand Down
7 changes: 6 additions & 1 deletion democracy/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ benchmarks! {

submit_proposal {
let zoran = account("zoran", 1, 1);
let proposal_action = ProposalAction::SetInactivityTimeout(8);
let cid = CommunityIdentifier::default();
// worst case is petition
let proposal_action = ProposalAction::Petition(Some(cid), PalletString::try_from("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".as_bytes().to_vec()).unwrap());
assert!(<Proposals<T>>::iter().next().is_none());
}: _(RawOrigin::Signed(zoran), proposal_action)
verify {
Expand Down
24 changes: 17 additions & 7 deletions democracy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

use encointer_primitives::{
ceremonies::ReputationCountType,
common::PalletString,
democracy::{Proposal, ProposalAction, ProposalIdType, ReputationVec},
fixed::{transcendental::sqrt, types::U64F64},
scheduler::{CeremonyIndexType, CeremonyPhaseType},
Expand Down Expand Up @@ -144,6 +145,10 @@ pub mod pallet {
proposal_id: ProposalIdType,
reason: DispatchErrorWithPostInfo,
},
PetitionApproved {
cid: Option<CommunityIdentifier>,
text: PalletString,
},
}

#[pallet::error]
Expand Down Expand Up @@ -227,13 +232,14 @@ pub mod pallet {
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight((<T as Config>::WeightInfo::submit_proposal(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::submit_proposal(), DispatchClass::Normal, Pays::Yes)
)]
pub fn submit_proposal(
origin: OriginFor<T>,
proposal_action: ProposalAction,
) -> DispatchResultWithPostInfo {
if Self::enactment_queue(proposal_action.clone().get_identifier()).is_some() {
return Err(Error::<T>::ProposalWaitingForEnactment.into())
return Err(Error::<T>::ProposalWaitingForEnactment.into());
}
let _sender = ensure_signed(origin)?;
let cindex = <pallet_encointer_scheduler::Pallet<T>>::current_ceremony_index();
Expand Down Expand Up @@ -313,7 +319,8 @@ pub mod pallet {
}

#[pallet::call_index(2)]
#[pallet::weight((<T as Config>::WeightInfo::update_proposal_state(), DispatchClass::Normal, Pays::Yes))]
#[pallet::weight((<T as Config>::WeightInfo::update_proposal_state(), DispatchClass::Normal, Pays::Yes)
)]
pub fn update_proposal_state(
origin: OriginFor<T>,
proposal_id: ProposalIdType,
Expand Down Expand Up @@ -383,12 +390,12 @@ pub mod pallet {

for community_ceremony in reputations {
if !Self::voting_cindexes(proposal.start_cindex)?.contains(&community_ceremony.1) {
continue
continue;
}

if let Some(cid) = maybe_cid {
if community_ceremony.0 != cid {
continue
continue;
}
}

Expand All @@ -401,7 +408,7 @@ pub mod pallet {
)
.is_err()
{
continue
continue;
}

eligible_reputation_count += 1;
Expand Down Expand Up @@ -531,7 +538,7 @@ pub mod pallet {

let turnout_permill = (tally.turnout * 1000).checked_div(electorate).unwrap_or(0);
if turnout_permill < T::MinTurnout::get() {
return Ok(false)
return Ok(false);
}

Self::positive_turnout_bias(electorate, tally.turnout, tally.ayes)
Expand Down Expand Up @@ -560,6 +567,9 @@ pub mod pallet {
ProposalAction::SetInactivityTimeout(inactivity_timeout) => {
CeremoniesPallet::<T>::do_set_inactivity_timeout(inactivity_timeout)?;
},
ProposalAction::Petition(maybe_cid, petition) => {
Self::deposit_event(Event::PetitionApproved { cid: maybe_cid, text: petition });
},
};

proposal.state = ProposalState::Enacted;
Expand Down
38 changes: 37 additions & 1 deletion democracy/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use test_utils::{
};

fn create_cid() -> CommunityIdentifier {
return register_test_community::<TestRuntime>(None, 0.0, 0.0)
return register_test_community::<TestRuntime>(None, 0.0, 0.0);
}

fn alice() -> AccountId {
Expand Down Expand Up @@ -959,6 +959,42 @@ fn enact_set_inactivity_timeout_works() {
});
}

#[test]
fn enact_petition_works() {
new_test_ext().execute_with(|| {
System::set_block_number(System::block_number() + 1); // this is needed to assert events

let cid = create_cid();
let alice = alice();
let petition_text = PalletString::try_from("freedom for all".as_bytes().to_vec()).unwrap();
let proposal_action = ProposalAction::Petition(Some(cid), petition_text.clone());
assert_ok!(EncointerDemocracy::submit_proposal(
RuntimeOrigin::signed(alice.clone()),
proposal_action.clone()
));

// directly inject the proposal into the enactment queue
EnactmentQueue::<TestRuntime>::insert(proposal_action.clone().get_identifier(), 1);

run_to_next_phase();
// first assigning phase after proposal lifetime ended

assert_eq!(EncointerDemocracy::proposals(1).unwrap().state, ProposalState::Enacted);
assert_eq!(EncointerDemocracy::enactment_queue(proposal_action.get_identifier()), None);

match event_at_index::<TestRuntime>(get_num_events::<TestRuntime>() - 3).unwrap() {
mock::RuntimeEvent::EncointerDemocracy(Event::PetitionApproved {
cid: maybe_cid,
text,
}) => {
assert_eq!(maybe_cid, Some(cid));
assert_eq!(text, petition_text);
},
_ => panic!("Wrong event"),
};
});
}

#[test]
fn enactment_error_fires_event() {
new_test_ext().execute_with(|| {
Expand Down
8 changes: 7 additions & 1 deletion primitives/src/democracy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ use crate::{
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;

use crate::{ceremonies::ReputationCountType, scheduler::CeremonyIndexType};
use crate::{ceremonies::ReputationCountType, common::PalletString, scheduler::CeremonyIndexType};
#[cfg(feature = "serde_derive")]
use serde::{Deserialize, Serialize};
use sp_core::RuntimeDebug;
use sp_runtime::BoundedVec;

pub type ProposalIdType = u128;
pub type VoteCountType = u128;
pub type VoteEntry<AccountId> = (AccountId, CommunityCeremony);
Expand Down Expand Up @@ -55,6 +56,7 @@ pub enum ProposalAction {
UpdateDemurrage(CommunityIdentifier, Demurrage),
UpdateNominalIncome(CommunityIdentifier, NominalIncomeType),
SetInactivityTimeout(InactivityTimeoutType),
Petition(Option<CommunityIdentifier>, PalletString),
}

#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
Expand All @@ -67,6 +69,7 @@ pub enum ProposalActionIdentifier {
UpdateDemurrage(CommunityIdentifier),
UpdateNominalIncome(CommunityIdentifier),
SetInactivityTimeout,
Petition(Option<CommunityIdentifier>),
}

impl ProposalAction {
Expand All @@ -78,6 +81,8 @@ impl ProposalAction {
ProposalAction::UpdateDemurrage(cid, _) => ProposalAccessPolicy::Community(cid),
ProposalAction::UpdateNominalIncome(cid, _) => ProposalAccessPolicy::Community(cid),
ProposalAction::SetInactivityTimeout(_) => ProposalAccessPolicy::Global,
ProposalAction::Petition(Some(cid), _) => ProposalAccessPolicy::Community(cid),
ProposalAction::Petition(None, _) => ProposalAccessPolicy::Global,
}
}

Expand All @@ -93,6 +98,7 @@ impl ProposalAction {
ProposalActionIdentifier::UpdateNominalIncome(cid),
ProposalAction::SetInactivityTimeout(_) =>
ProposalActionIdentifier::SetInactivityTimeout,
ProposalAction::Petition(maybe_cid, _) => ProposalActionIdentifier::Petition(maybe_cid),
}
}
}
Expand Down
Loading