Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 5df6e9e

Browse files
committed
runtime/parachains: Keep track of included candidates in module
1 parent 123b725 commit 5df6e9e

File tree

3 files changed

+192
-57
lines changed

3 files changed

+192
-57
lines changed

runtime/parachains/src/disputes.rs

+61-54
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//! Runtime component for handling disputes of parachain candidates.
1818
1919
use crate::{
20+
shared,
2021
configuration::{self, HostConfiguration},
2122
initializer::SessionChangeNotification,
2223
session_info,
@@ -31,7 +32,7 @@ use primitives::v1::{
3132
ValidDisputeStatementKind, ValidatorId, ValidatorIndex, ValidatorSignature,
3233
};
3334
use sp_runtime::{
34-
traits::{AppVerify, One, Saturating, Zero},
35+
traits::{AppVerify, Saturating},
3536
DispatchError, RuntimeDebug, SaturatedConversion,
3637
};
3738
use sp_std::{collections::btree_set::BTreeSet, prelude::*};
@@ -116,10 +117,10 @@ pub trait DisputesHandler<BlockNumber> {
116117
) -> Result<Vec<(SessionIndex, CandidateHash)>, DispatchError>;
117118

118119
/// Note that the given candidate has been included.
119-
fn note_included(
120+
fn process_included(
120121
session: SessionIndex,
121122
candidate_hash: CandidateHash,
122-
included_in: BlockNumber,
123+
revert_to: BlockNumber,
123124
);
124125

125126
/// Whether the given candidate could be invalid, i.e. there is an ongoing
@@ -151,10 +152,10 @@ impl<BlockNumber> DisputesHandler<BlockNumber> for () {
151152
Ok(Vec::new())
152153
}
153154

154-
fn note_included(
155+
fn process_included(
155156
_session: SessionIndex,
156157
_candidate_hash: CandidateHash,
157-
_included_in: BlockNumber,
158+
_revert_to: BlockNumber,
158159
) {
159160
}
160161

@@ -186,12 +187,12 @@ impl<T: Config> DisputesHandler<T::BlockNumber> for pallet::Pallet<T> {
186187
pallet::Pallet::<T>::provide_multi_dispute_data(statement_sets)
187188
}
188189

189-
fn note_included(
190+
fn process_included(
190191
session: SessionIndex,
191192
candidate_hash: CandidateHash,
192-
included_in: T::BlockNumber,
193+
revert_to: T::BlockNumber,
193194
) {
194-
pallet::Pallet::<T>::note_included(session, candidate_hash, included_in)
195+
pallet::Pallet::<T>::process_included(session, candidate_hash, revert_to);
195196
}
196197

197198
fn could_be_invalid(session: SessionIndex, candidate_hash: CandidateHash) -> bool {
@@ -243,18 +244,6 @@ pub mod pallet {
243244
DisputeState<T::BlockNumber>,
244245
>;
245246

246-
/// All included blocks on the chain, as well as the block number in this chain that
247-
/// should be reverted back to if the candidate is disputed and determined to be invalid.
248-
#[pallet::storage]
249-
pub(super) type Included<T: Config> = StorageDoubleMap<
250-
_,
251-
Twox64Concat,
252-
SessionIndex,
253-
Blake2_128Concat,
254-
CandidateHash,
255-
T::BlockNumber,
256-
>;
257-
258247
/// Maps session indices to a vector indicating the number of potentially-spam disputes
259248
/// each validator is participating in. Potentially-spam disputes are remote disputes which have
260249
/// fewer than `byzantine_threshold + 1` validators.
@@ -565,7 +554,11 @@ impl<T: Config> Pallet<T> {
565554
dispute.concluded_at = Some(now);
566555
<Disputes<T>>::insert(session_index, candidate_hash, &dispute);
567556

568-
if <Included<T>>::contains_key(&session_index, &candidate_hash) {
557+
let is_local = <shared::Pallet<T>>::is_included_candidate(
558+
&session_index,
559+
&candidate_hash,
560+
);
561+
if is_local {
569562
// Local disputes don't count towards spam.
570563

571564
weight += T::DbWeight::get().reads_writes(1, 1);
@@ -632,7 +625,7 @@ impl<T: Config> Pallet<T> {
632625

633626
// This is larger, and will be extracted to the `shared` module for more proper pruning.
634627
// TODO: https://github.com/paritytech/polkadot/issues/3469
635-
<Included<T>>::remove_prefix(to_prune, None);
628+
shared::Pallet::<T>::prune_included_candidates(to_prune);
636629
SpamSlots::<T>::remove(to_prune);
637630
}
638631

@@ -787,7 +780,7 @@ impl<T: Config> Pallet<T> {
787780
};
788781

789782
// Apply spam slot changes. Bail early if too many occupied.
790-
let is_local = <Included<T>>::contains_key(&set.session, &set.candidate_hash);
783+
let is_local = <shared::Pallet<T>>::is_included_candidate(&set.session, &set.candidate_hash);
791784
if !is_local {
792785
let mut spam_slots: Vec<u32> =
793786
SpamSlots::<T>::get(&set.session).unwrap_or_else(|| vec![0; n_validators]);
@@ -919,7 +912,10 @@ impl<T: Config> Pallet<T> {
919912
};
920913

921914
// Apply spam slot changes. Bail early if too many occupied.
922-
let is_local = <Included<T>>::contains_key(&set.session, &set.candidate_hash);
915+
let is_local = <shared::Pallet<T>>::is_included_candidate(
916+
&set.session,
917+
&set.candidate_hash,
918+
);
923919
if !is_local {
924920
let mut spam_slots: Vec<u32> =
925921
SpamSlots::<T>::get(&set.session).unwrap_or_else(|| vec![0; n_validators]);
@@ -993,7 +989,10 @@ impl<T: Config> Pallet<T> {
993989

994990
// Freeze if just concluded against some local candidate
995991
if summary.new_flags.contains(DisputeStateFlags::AGAINST_SUPERMAJORITY) {
996-
if let Some(revert_to) = <Included<T>>::get(&set.session, &set.candidate_hash) {
992+
if let Some((revert_to, _)) = <shared::Pallet<T>>::get_included_candidate(
993+
&set.session,
994+
&set.candidate_hash,
995+
) {
997996
Self::revert_and_freeze(revert_to);
998997
}
999998
}
@@ -1006,19 +1005,11 @@ impl<T: Config> Pallet<T> {
10061005
<Disputes<T>>::iter().collect()
10071006
}
10081007

1009-
pub(crate) fn note_included(
1008+
pub(crate) fn process_included(
10101009
session: SessionIndex,
10111010
candidate_hash: CandidateHash,
1012-
included_in: T::BlockNumber,
1011+
revert_to: T::BlockNumber,
10131012
) {
1014-
if included_in.is_zero() {
1015-
return
1016-
}
1017-
1018-
let revert_to = included_in - One::one();
1019-
1020-
<Included<T>>::insert(&session, &candidate_hash, revert_to);
1021-
10221013
// If we just included a block locally which has a live dispute, decrement spam slots
10231014
// for any involved validators, if the dispute is not already confirmed by f + 1.
10241015
if let Some(state) = <Disputes<T>>::get(&session, candidate_hash) {
@@ -1120,6 +1111,7 @@ fn check_signature(
11201111
#[cfg(test)]
11211112
mod tests {
11221113
use super::*;
1114+
use primitives::v1::CoreIndex;
11231115
use crate::mock::{
11241116
new_test_ext, AccountId, AllPallets, Initializer, MockGenesisConfig, System, Test,
11251117
PUNISH_VALIDATORS_AGAINST, PUNISH_VALIDATORS_FOR, PUNISH_VALIDATORS_INCONCLUSIVE,
@@ -1168,6 +1160,21 @@ mod tests {
11681160
}
11691161
}
11701162

1163+
fn include_candidate(session: SessionIndex, candidate_hash: &CandidateHash, block_number: BlockNumber) {
1164+
if let Some(revert_to) = shared::Pallet::<Test>::note_included_candidate(
1165+
session,
1166+
candidate_hash.clone(),
1167+
block_number,
1168+
CoreIndex(0),
1169+
) {
1170+
Pallet::<Test>::process_included(
1171+
session,
1172+
candidate_hash.clone(),
1173+
revert_to,
1174+
);
1175+
}
1176+
}
1177+
11711178
#[test]
11721179
fn test_dispute_state_flag_from_state() {
11731180
assert_eq!(
@@ -1466,13 +1473,13 @@ mod tests {
14661473
let v0 = <ValidatorId as CryptoType>::Pair::generate().0;
14671474

14681475
let candidate_hash = CandidateHash(sp_core::H256::repeat_byte(1));
1469-
Pallet::<Test>::note_included(0, candidate_hash.clone(), 0);
1470-
Pallet::<Test>::note_included(1, candidate_hash.clone(), 1);
1471-
Pallet::<Test>::note_included(2, candidate_hash.clone(), 2);
1472-
Pallet::<Test>::note_included(3, candidate_hash.clone(), 3);
1473-
Pallet::<Test>::note_included(4, candidate_hash.clone(), 4);
1474-
Pallet::<Test>::note_included(5, candidate_hash.clone(), 5);
1475-
Pallet::<Test>::note_included(6, candidate_hash.clone(), 5);
1476+
include_candidate(0, &candidate_hash, 0);
1477+
include_candidate(1, &candidate_hash, 1);
1478+
include_candidate(2, &candidate_hash, 2);
1479+
include_candidate(3, &candidate_hash, 3);
1480+
include_candidate(4, &candidate_hash, 4);
1481+
include_candidate(5, &candidate_hash, 5);
1482+
include_candidate(6, &candidate_hash, 5);
14761483

14771484
run_to_block(7, |b| {
14781485
// a new session at each block
@@ -1482,13 +1489,13 @@ mod tests {
14821489
// current session is 7,
14831490
// we keep for dispute_period + 1 session and we remove in on_finalize
14841491
// thus we keep info for session 3, 4, 5, 6, 7.
1485-
assert_eq!(Included::<Test>::iter_prefix(0).count(), 0);
1486-
assert_eq!(Included::<Test>::iter_prefix(1).count(), 0);
1487-
assert_eq!(Included::<Test>::iter_prefix(2).count(), 0);
1488-
assert_eq!(Included::<Test>::iter_prefix(3).count(), 1);
1489-
assert_eq!(Included::<Test>::iter_prefix(4).count(), 1);
1490-
assert_eq!(Included::<Test>::iter_prefix(5).count(), 1);
1491-
assert_eq!(Included::<Test>::iter_prefix(6).count(), 1);
1492+
assert_eq!(shared::Pallet::<Test>::included_candidates_iter_prefix(0).count(), 0);
1493+
assert_eq!(shared::Pallet::<Test>::included_candidates_iter_prefix(1).count(), 0);
1494+
assert_eq!(shared::Pallet::<Test>::included_candidates_iter_prefix(2).count(), 0);
1495+
assert_eq!(shared::Pallet::<Test>::included_candidates_iter_prefix(3).count(), 1);
1496+
assert_eq!(shared::Pallet::<Test>::included_candidates_iter_prefix(4).count(), 1);
1497+
assert_eq!(shared::Pallet::<Test>::included_candidates_iter_prefix(5).count(), 1);
1498+
assert_eq!(shared::Pallet::<Test>::included_candidates_iter_prefix(6).count(), 1);
14921499
});
14931500
}
14941501

@@ -1590,7 +1597,7 @@ mod tests {
15901597
}
15911598

15921599
#[test]
1593-
fn test_freeze_on_note_included() {
1600+
fn test_freeze_on_process_included() {
15941601
new_test_ext(Default::default()).execute_with(|| {
15951602
let v0 = <ValidatorId as CryptoType>::Pair::generate().0;
15961603

@@ -1620,7 +1627,7 @@ mod tests {
16201627
}];
16211628
assert!(Pallet::<Test>::provide_multi_dispute_data(stmts).is_ok());
16221629

1623-
Pallet::<Test>::note_included(3, candidate_hash.clone(), 3);
1630+
include_candidate(3, &candidate_hash, 3);
16241631
assert_eq!(Frozen::<Test>::get(), Some(2));
16251632
});
16261633
}
@@ -1637,7 +1644,7 @@ mod tests {
16371644

16381645
let candidate_hash = CandidateHash(sp_core::H256::repeat_byte(1));
16391646

1640-
Pallet::<Test>::note_included(3, candidate_hash.clone(), 3);
1647+
include_candidate(3, &candidate_hash, 3);
16411648

16421649
// v0 votes for 3
16431650
let stmts = vec![DisputeStatementSet {
@@ -1666,7 +1673,7 @@ mod tests {
16661673
// * provide_multi_dispute: with success scenario
16671674
// * disputes: correctness of datas
16681675
// * could_be_invalid: correctness of datas
1669-
// * note_included: decrement spam correctly
1676+
// * process_included: decrement spam correctly
16701677
// * spam slots: correctly incremented and decremented
16711678
// * ensure rewards and punishment are correctly called.
16721679
#[test]
@@ -1942,7 +1949,7 @@ mod tests {
19421949

19431950
// Ensure inclusion removes spam slots
19441951
assert_eq!(SpamSlots::<Test>::get(4), Some(vec![0, 0, 0, 1]));
1945-
Pallet::<Test>::note_included(4, candidate_hash.clone(), 4);
1952+
include_candidate(4, &candidate_hash, 4);
19461953
assert_eq!(SpamSlots::<Test>::get(4), Some(vec![0, 0, 0, 0]));
19471954

19481955
// Ensure the reward_validator function was correctly called

runtime/parachains/src/paras_inherent.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,22 @@ decl_module! {
157157

158158
// Inform the disputes module of all included candidates.
159159
let now = <frame_system::Pallet<T>>::block_number();
160-
for (_, candidate_hash) in &freed_concluded {
161-
T::DisputesHandler::note_included(current_session, *candidate_hash, now);
160+
for (core_index, candidate_hash) in &freed_concluded {
161+
let revert_to = match shared::Pallet::<T>::note_included_candidate(
162+
current_session,
163+
*candidate_hash,
164+
now,
165+
*core_index,
166+
) {
167+
Some(revert_to) => revert_to,
168+
None => continue,
169+
};
170+
171+
T::DisputesHandler::process_included(
172+
current_session,
173+
*candidate_hash,
174+
revert_to,
175+
);
162176
}
163177

164178
// Handle timeouts for any availability core work.

0 commit comments

Comments
 (0)