diff --git a/prdoc/pr_9025.prdoc b/prdoc/pr_9025.prdoc new file mode 100644 index 0000000000000..e36bd824853e4 --- /dev/null +++ b/prdoc/pr_9025.prdoc @@ -0,0 +1,8 @@ +title: EPMB / signed pallet: Add support for lazy deletion of the leader from the storage +doc: +- audience: Runtime Dev + description: |- + Lazy deletion of leader from storage +crates: +- name: pallet-election-provider-multi-block + bump: minor diff --git a/substrate/frame/election-provider-multi-block/src/signed/mod.rs b/substrate/frame/election-provider-multi-block/src/signed/mod.rs index 7326e58861471..7351b3c6e1b07 100644 --- a/substrate/frame/election-provider-multi-block/src/signed/mod.rs +++ b/substrate/frame/election-provider-multi-block/src/signed/mod.rs @@ -166,7 +166,7 @@ impl SolutionDataProvider for Pallet { // defensive: if there is a result to be reported, then we must have had some // leader. if let Some((winner, metadata)) = - Submissions::::take_leader_with_data(Self::current_round()).defensive() + Submissions::::take_leader(Self::current_round(), true).defensive() { // first, let's give them their reward. let reward = metadata.reward.saturating_add(metadata.fee); @@ -380,24 +380,27 @@ pub mod pallet { result } - /// *Fully* **TAKE** (i.e. get and remove) the leader from storage, with all of its - /// associated data. + /// Takes the leader from the sorted scores for a given round. + /// + /// This function always removes the leader's score and their submission metadata from storage. /// - /// This removes all associated data of the leader from storage, discarding the submission - /// data and score, returning the rest. - pub(crate) fn take_leader_with_data( + /// If `with_data` is `true`, it will also remove all associated submission pages. + /// If `false`, the submission pages are left in storage for later. + pub(crate) fn take_leader( round: u32, + with_data: bool, ) -> Option<(T::AccountId, SubmissionMetadata)> { Self::mutate_checked(round, || { SortedScores::::mutate(round, |sorted| sorted.pop()).and_then( |(submitter, _score)| { - // NOTE: safe to remove unbounded, as at most `Pages` pages are stored. - let r: MultiRemovalResults = SubmissionStorage::::clear_prefix( - (round, &submitter), - u32::MAX, - None, - ); - debug_assert!(r.unique <= T::Pages::get()); + if with_data { + let r: MultiRemovalResults = SubmissionStorage::::clear_prefix( + (round, &submitter), + u32::MAX, + None, + ); + debug_assert!(r.unique <= T::Pages::get()); + } SubmissionMetadataStorage::::take(round, &submitter) .map(|metadata| (submitter, metadata)) @@ -1010,7 +1013,7 @@ impl Pallet { /// Common logic for handling solution rejection - slash the submitter and try next solution fn handle_solution_rejection(current_round: u32) { if let Some((loser, metadata)) = - Submissions::::take_leader_with_data(current_round).defensive() + Submissions::::take_leader(current_round, true).defensive() { // Slash the deposit let slash = metadata.deposit;