Skip to content

Commit

Permalink
Democracy 2nd iteration (#362)
Browse files Browse the repository at this point in the history
* user reputation commitments for recording votes

* use timetstamps instead of blocks

* add more events

* add more events

* pass enactment errors to user

* implement proposal actions

* taplo fmt

* remove VoteEntries and fix benchmarks

* fix toml

* fix typo

* taplo fmt

* fmt

* fixes

* add no_std to_string

* fix more typos

---------

Co-authored-by: Alain Brenzikofer <alain@integritee.network>
  • Loading branch information
pifragile and brenzi authored Feb 26, 2024
1 parent ad8cc43 commit 66805f4
Show file tree
Hide file tree
Showing 9 changed files with 684 additions and 309 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

172 changes: 97 additions & 75 deletions communities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,42 +175,7 @@ pub mod pallet {
location: Location,
) -> DispatchResultWithPostInfo {
T::TrustableForNonDestructiveAction::ensure_origin(origin)?;

ensure!(
<pallet_encointer_scheduler::Pallet<T>>::current_phase()
== CeremonyPhaseType::Registering,
Error::<T>::RegistrationPhaseRequired
);
Self::ensure_cid_exists(&cid)?;
Self::validate_location(&location)?;
let geo_hash = GeoHash::try_from_params(location.lat, location.lon)
.map_err(|_| <Error<T>>::InvalidLocationForGeohash)?;
// insert location into locations
let mut locations = Self::locations(cid, &geo_hash);
match locations.binary_search(&location) {
Ok(_) => (),
Err(index) => {
locations
.try_insert(index, location)
.map_err(|_| Error::<T>::TooManyLocationsPerGeohash)?;
<Locations<T>>::insert(cid, &geo_hash, locations);
},
}
// check if cid is in cids_by_geohash, if not, add it
let mut cids = Self::cids_by_geohash(&geo_hash);
match cids.binary_search(&cid) {
Ok(_) => (),
Err(index) => {
cids.try_insert(index, cid)
.map_err(|_| Error::<T>::TooManyCommunityIdentifiersPerGeohash)?;
<CommunityIdentifiersByGeohash<T>>::insert(&geo_hash, cids);
},
}
sp_io::offchain_index::set(CACHE_DIRTY_KEY, &true.encode());

info!(target: LOG, "added location {:?} to community with cid: {:?}", location, cid);
Self::deposit_event(Event::LocationAdded(cid, location));
Ok(().into())
Self::do_add_location(cid, location)
}

/// Remove an existing meetup `location` from the community with `cid`.
Expand All @@ -226,20 +191,7 @@ pub mod pallet {
location: Location,
) -> DispatchResultWithPostInfo {
T::CommunityMaster::ensure_origin(origin)?;

ensure!(
<pallet_encointer_scheduler::Pallet<T>>::current_phase()
== CeremonyPhaseType::Registering,
Error::<T>::RegistrationPhaseRequired
);
Self::ensure_cid_exists(&cid)?;

let geo_hash = GeoHash::try_from_params(location.lat, location.lon)
.map_err(|_| <Error<T>>::InvalidLocationForGeohash)?;
Self::remove_location_intern(cid, location, geo_hash);
info!(target: LOG, "removed location {:?} to community with cid: {:?}", location, cid);
Self::deposit_event(Event::LocationRemoved(cid, location));
Ok(().into())
Self::do_remove_location(cid, location)
}

/// Update the metadata of the community with `cid`.
Expand All @@ -253,21 +205,7 @@ pub mod pallet {
community_metadata: CommunityMetadataType,
) -> DispatchResultWithPostInfo {
T::CommunityMaster::ensure_origin(origin)?;

Self::ensure_cid_exists(&cid)?;
community_metadata
.validate()
.map_err(|_| <Error<T>>::InvalidCommunityMetadata)?;

<CommunityMetadata<T>>::insert(cid, &community_metadata);

sp_io::offchain_index::set(&cid.encode(), &community_metadata.name.encode());
sp_io::offchain_index::set(CACHE_DIRTY_KEY, &true.encode());

info!(target: LOG, "updated community metadata for cid: {:?}", cid);
Self::deposit_event(Event::MetadataUpdated(cid));

Ok(().into())
Self::do_update_community_metadata(cid, community_metadata)
}

#[pallet::call_index(4)]
Expand All @@ -278,16 +216,7 @@ pub mod pallet {
demurrage: Demurrage,
) -> DispatchResultWithPostInfo {
T::CommunityMaster::ensure_origin(origin)?;

Self::ensure_cid_exists(&cid)?;

<pallet_encointer_balances::Pallet<T>>::set_demurrage(&cid, demurrage)
.map_err(|_| <Error<T>>::InvalidDemurrage)?;

info!(target: LOG, " updated demurrage for cid: {:?}", cid);
Self::deposit_event(Event::DemurrageUpdated(cid, demurrage));

Ok(().into())
Self::do_update_demurrage(cid, demurrage)
}

#[pallet::call_index(5)]
Expand Down Expand Up @@ -476,6 +405,99 @@ pub mod pallet {
}

impl<T: Config> Pallet<T> {
pub fn do_add_location(
cid: CommunityIdentifier,
location: Location,
) -> DispatchResultWithPostInfo {
ensure!(
<pallet_encointer_scheduler::Pallet<T>>::current_phase()
== CeremonyPhaseType::Registering,
Error::<T>::RegistrationPhaseRequired
);
Self::ensure_cid_exists(&cid)?;
Self::validate_location(&location)?;
let geo_hash = GeoHash::try_from_params(location.lat, location.lon)
.map_err(|_| <Error<T>>::InvalidLocationForGeohash)?;
// insert location into locations
let mut locations = Self::locations(cid, &geo_hash);
match locations.binary_search(&location) {
Ok(_) => (),
Err(index) => {
locations
.try_insert(index, location)
.map_err(|_| Error::<T>::TooManyLocationsPerGeohash)?;
<Locations<T>>::insert(cid, &geo_hash, locations);
},
}
// check if cid is in cids_by_geohash, if not, add it
let mut cids = Self::cids_by_geohash(&geo_hash);
match cids.binary_search(&cid) {
Ok(_) => (),
Err(index) => {
cids.try_insert(index, cid)
.map_err(|_| Error::<T>::TooManyCommunityIdentifiersPerGeohash)?;
<CommunityIdentifiersByGeohash<T>>::insert(&geo_hash, cids);
},
}
sp_io::offchain_index::set(CACHE_DIRTY_KEY, &true.encode());

info!(target: LOG, "added location {:?} to community with cid: {:?}", location, cid);
Self::deposit_event(Event::LocationAdded(cid, location));
Ok(().into())
}

pub fn do_remove_location(
cid: CommunityIdentifier,
location: Location,
) -> DispatchResultWithPostInfo {
ensure!(
<pallet_encointer_scheduler::Pallet<T>>::current_phase()
== CeremonyPhaseType::Registering,
Error::<T>::RegistrationPhaseRequired
);
Self::ensure_cid_exists(&cid)?;

let geo_hash = GeoHash::try_from_params(location.lat, location.lon)
.map_err(|_| <Error<T>>::InvalidLocationForGeohash)?;
Self::remove_location_intern(cid, location, geo_hash);
info!(target: LOG, "removed location {:?} to community with cid: {:?}", location, cid);
Self::deposit_event(Event::LocationRemoved(cid, location));
Ok(().into())
}
pub fn do_update_community_metadata(
cid: CommunityIdentifier,
community_metadata: CommunityMetadataType,
) -> DispatchResultWithPostInfo {
Self::ensure_cid_exists(&cid)?;
community_metadata
.validate()
.map_err(|_| <Error<T>>::InvalidCommunityMetadata)?;

<CommunityMetadata<T>>::insert(cid, &community_metadata);

sp_io::offchain_index::set(&cid.encode(), &community_metadata.name.encode());
sp_io::offchain_index::set(CACHE_DIRTY_KEY, &true.encode());

info!(target: LOG, "updated community metadata for cid: {:?}", cid);
Self::deposit_event(Event::MetadataUpdated(cid));

Ok(().into())
}
pub fn do_update_demurrage(
cid: CommunityIdentifier,
demurrage: Demurrage,
) -> DispatchResultWithPostInfo {
Self::ensure_cid_exists(&cid)?;

<pallet_encointer_balances::Pallet<T>>::set_demurrage(&cid, demurrage)
.map_err(|_| <Error<T>>::InvalidDemurrage)?;

info!(target: LOG, " updated demurrage for cid: {:?}", cid);
Self::deposit_event(Event::DemurrageUpdated(cid, demurrage));

Ok(().into())
}

pub fn do_update_nominal_income(
cid: CommunityIdentifier,
nominal_income: NominalIncomeType,
Expand Down
1 change: 1 addition & 0 deletions democracy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ scale-info = { workspace = true }
encointer-primitives = { workspace = true }
pallet-encointer-ceremonies = { workspace = true }
pallet-encointer-communities = { workspace = true }
pallet-encointer-reputation-commitments = { workspace = true }
pallet-encointer-scheduler = { workspace = true }

# substrate deps
Expand Down
45 changes: 27 additions & 18 deletions democracy/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@ use encointer_primitives::{
storage::{current_ceremony_index_key, global_reputation_count, participant_reputation},
};
use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite};
use frame_support::{assert_ok, traits::OnInitialize, BoundedVec};
use frame_support::{
assert_ok,
traits::{OnFinalize, OriginTrait},
BoundedVec,
};
use frame_system::RawOrigin;
use parity_scale_codec::Encode;
#[cfg(not(feature = "std"))]
use sp_std::vec;

fn advance_n_blocks<T: Config>(n: u64) {
for _ in 0..n {
frame_system::Pallet::<T>::set_block_number(
frame_system::Pallet::<T>::block_number() + 1u32.into(),
);
frame_system::Pallet::<T>::on_initialize(frame_system::Pallet::<T>::block_number());
}
fn advance_timestamp_equivalent_to_n_blocks<T: Config>(n: u64) {
let offset: T::Moment = (n * 6000u64)
.try_into()
.unwrap_or_else(|_| panic!("Something went horribly wrong!"));
let new_time: T::Moment = pallet_timestamp::Pallet::<T>::get() + offset;
let _ = pallet_timestamp::Pallet::<T>::set(T::RuntimeOrigin::none(), new_time);
pallet_timestamp::Pallet::<T>::on_finalize(frame_system::Pallet::<T>::block_number());
}

benchmarks! {
Expand All @@ -38,35 +42,41 @@ benchmarks! {
let zoran = account::<T::AccountId>("zoran", 1, 1);
let cid = CommunityIdentifier::default();

let proposal_action = ProposalAction::SetInactivityTimeout(8);
assert_ok!(EncointerDemocracy::<T>::submit_proposal(
RawOrigin::Signed(zoran.clone()).into(),
proposal_action
));

frame_support::storage::unhashed::put_raw(&participant_reputation((cid, 3), &zoran), &Reputation::VerifiedUnlinked.encode());
frame_support::storage::unhashed::put_raw(&participant_reputation((cid, 4), &zoran), &Reputation::VerifiedUnlinked.encode());
frame_support::storage::unhashed::put_raw(&participant_reputation((cid, 5), &zoran), &Reputation::VerifiedUnlinked.encode());
frame_support::storage::unhashed::put_raw(&global_reputation_count(3), &1u128.encode());
frame_support::storage::unhashed::put_raw(&global_reputation_count(4), &1u128.encode());
frame_support::storage::unhashed::put_raw(&global_reputation_count(5), &1u128.encode());

let reputation_vec: ReputationVecOf<T> = BoundedVec::try_from(vec![
(cid, 3),
(cid, 4),
(cid, 5),
]).unwrap();

assert!(<VoteEntries<T>>::iter().next().is_none());
let proposal_action = ProposalAction::SetInactivityTimeout(8);
assert_ok!(EncointerDemocracy::<T>::submit_proposal(
RawOrigin::Signed(zoran.clone()).into(),
proposal_action
));

assert_eq!(<Tallies<T>>::get(1).unwrap().ayes, 0);
}: _(RawOrigin::Signed(zoran.clone()),
1,
Vote::Aye,
reputation_vec)
verify {
assert!(<VoteEntries<T>>::iter().next().is_some());
assert_eq!(<Tallies<T>>::get(1).unwrap().ayes, 3);
}

update_proposal_state {
frame_support::storage::unhashed::put_raw(&current_ceremony_index_key(), &7u32.encode());
let zoran = account::<T::AccountId>("zoran", 1, 1);
let cid = CommunityIdentifier::default();

frame_support::storage::unhashed::put_raw(&global_reputation_count(5), &3u128.encode());

let proposal_action = ProposalAction::SetInactivityTimeout(8);
assert_ok!(EncointerDemocracy::<T>::submit_proposal(
RawOrigin::Signed(zoran.clone()).into(),
Expand All @@ -76,11 +86,10 @@ benchmarks! {

Tallies::<T>::insert(1, Tally { turnout: 3, ayes: 3 });

frame_support::storage::unhashed::put_raw(&global_reputation_count(5), &3u128.encode());
assert_eq!(EncointerDemocracy::<T>::proposals(1).unwrap().state, ProposalState::Ongoing);
EncointerDemocracy::<T>::update_proposal_state(RawOrigin::Signed(zoran.clone()).into(), 1).ok();
assert!(<EnactmentQueue<T>>::iter().next().is_none());
advance_n_blocks::<T>(21);
advance_timestamp_equivalent_to_n_blocks::<T>(21);

}: _(RawOrigin::Signed(zoran), 1)
verify {
Expand Down
Loading

0 comments on commit 66805f4

Please sign in to comment.