This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Referendum decision period quantization #12810
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -195,12 +195,17 @@ pub mod pallet { | |
#[pallet::constant] | ||
type UndecidingTimeout: Get<Self::BlockNumber>; | ||
|
||
/// Quantization level for the referendum wakeup scheduler. A higher number will result in | ||
/// fewer storage reads/writes needed for smaller voters, but also result in delays to the | ||
/// automatic referendum status changes. Explicit servicing instructions are unaffected. | ||
/// Quantization level for the referendum wakeup scheduler during the decision stage. A | ||
/// higher number will result in fewer storage reads/writes needed for smaller voters, but | ||
/// also result in delays to the automatic referendum status changes. | ||
#[pallet::constant] | ||
type AlarmInterval: Get<Self::BlockNumber>; | ||
|
||
/// Minimum alarm period for the referendum wakeup scheduler during the decision stage. | ||
/// Prevents wake up calls from being too frequent as a result of the quantization. | ||
#[pallet::constant] | ||
type MinAlarmPeriod: Get<Self::BlockNumber>; | ||
|
||
// The other stuff. | ||
/// Information concerning the different referendum tracks. | ||
#[pallet::constant] | ||
|
@@ -754,9 +759,6 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { | |
call: BoundedCallOf<T, I>, | ||
when: T::BlockNumber, | ||
) -> Option<(T::BlockNumber, ScheduleAddressOf<T, I>)> { | ||
let alarm_interval = T::AlarmInterval::get().max(One::one()); | ||
let when = when.saturating_add(alarm_interval).saturating_sub(One::one()) / | ||
(alarm_interval.saturating_mul(alarm_interval)).max(One::one()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its probably supposed to be calculated from the duration. I moved this logic to decision_alarm, because we need the quantization only for the decision period. |
||
let maybe_result = T::Scheduler::schedule( | ||
DispatchTime::At(when), | ||
None, | ||
|
@@ -802,19 +804,18 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { | |
proposal: status.proposal.clone(), | ||
track: status.track, | ||
}); | ||
let confirming = if is_passing { | ||
if is_passing { | ||
Self::deposit_event(Event::<T, I>::ConfirmStarted { index }); | ||
Some(now.saturating_add(track.confirm_period)) | ||
let confirming = Some(now.saturating_add(track.confirm_period.max(One::one()))); | ||
status.deciding = Some(DecidingStatus { since: now, confirming }); | ||
(confirming, BeginDecidingBranch::Passing) | ||
} else { | ||
None | ||
}; | ||
let deciding_status = DecidingStatus { since: now, confirming }; | ||
let alarm = Self::decision_time(&deciding_status, &status.tally, status.track, track) | ||
.max(now.saturating_add(One::one())); | ||
status.deciding = Some(deciding_status); | ||
let branch = | ||
if is_passing { BeginDecidingBranch::Passing } else { BeginDecidingBranch::Failing }; | ||
(Some(alarm), branch) | ||
status.deciding = Some(DecidingStatus { since: now, confirming: None }); | ||
( | ||
Some(Self::decision_alarm(now, now, &status.tally, status.track, track)), | ||
BeginDecidingBranch::Failing, | ||
) | ||
} | ||
} | ||
|
||
/// If it returns `Some`, deciding has begun and it needs waking at the given block number. The | ||
|
@@ -861,10 +862,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { | |
/// overall more efficient), however the weights become rather less easy to measure. | ||
fn note_one_fewer_deciding(track: TrackIdOf<T, I>) { | ||
// Set an alarm call for the next block to nudge the track along. | ||
let min_alarm_period = T::MinAlarmPeriod::get().max(One::one()); | ||
let now = frame_system::Pallet::<T>::block_number(); | ||
let next_block = now + One::one(); | ||
let alarm_interval = T::AlarmInterval::get().max(One::one()); | ||
let when = (next_block + alarm_interval - One::one()) / alarm_interval * alarm_interval; | ||
let when = now.saturating_add(min_alarm_period); | ||
|
||
let call = match T::Preimages::bound(CallOf::<T, I>::from(Call::one_fewer_deciding { | ||
track, | ||
|
@@ -1081,31 +1081,47 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { | |
ServiceBranch::ContinueNotConfirming | ||
} | ||
}; | ||
alarm = Self::decision_time(deciding, &status.tally, status.track, track); | ||
alarm = deciding.confirming.unwrap_or_else(|| { | ||
Self::decision_alarm(now, deciding.since, &status.tally, status.track, track) | ||
}); | ||
}, | ||
} | ||
|
||
let dirty_alarm = Self::ensure_alarm_at(&mut status, index, alarm); | ||
(ReferendumInfo::Ongoing(status), dirty_alarm || dirty, branch) | ||
} | ||
|
||
/// Determine the point at which a referendum will be accepted, move into confirmation with the | ||
/// given `tally` or end with rejection (whichever happens sooner). | ||
fn decision_time( | ||
deciding: &DecidingStatusOf<T>, | ||
/// Determine the block of the next alarm for a decision check based on the current voting, | ||
/// total decision period and the alarm interval. | ||
fn decision_alarm( | ||
now: T::BlockNumber, | ||
deciding_since: T::BlockNumber, | ||
tally: &T::Tally, | ||
track_id: TrackIdOf<T, I>, | ||
track: &TrackInfoOf<T, I>, | ||
) -> T::BlockNumber { | ||
deciding.confirming.unwrap_or_else(|| { | ||
// Set alarm to the point where the current voting would make it pass. | ||
let approval = tally.approval(track_id); | ||
let support = tally.support(track_id); | ||
let until_approval = track.min_approval.delay(approval); | ||
let until_support = track.min_support.delay(support); | ||
let offset = until_support.max(until_approval); | ||
deciding.since.saturating_add(offset * track.decision_period) | ||
}) | ||
// find a period offset where the current voting would make it pass. | ||
let approval = tally.approval(track_id); | ||
let support = tally.support(track_id); | ||
let until_approval = track.min_approval.delay(approval); | ||
let until_support = track.min_support.delay(support); | ||
// if never passing the offset is 1. | ||
let offset = until_support.max(until_approval); | ||
deciding_since | ||
.saturating_add(now.saturating_sub(deciding_since)) | ||
.saturating_add(Self::decision_interval( | ||
offset * track.decision_period.saturating_sub(now.saturating_sub(deciding_since)), | ||
)) | ||
} | ||
|
||
/// Determine the decision period interval based on the total period and the alarm interval. | ||
fn decision_interval(decision_period: T::BlockNumber) -> T::BlockNumber { | ||
let min_alarm_period = T::MinAlarmPeriod::get().max(One::one()); | ||
let alarm_interval = T::AlarmInterval::get().max(One::one()); | ||
let decision_period = | ||
decision_period.saturating_add(alarm_interval).saturating_sub(One::one()) / | ||
(alarm_interval.saturating_mul(alarm_interval)).max(One::one()); | ||
decision_period.max(min_alarm_period) | ||
} | ||
|
||
/// Cancel the alarm in `status`, if one exists. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the actual use-case for this?