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

Commit

Permalink
Merge branch 'master' into ao-improved-gossip-topology
Browse files Browse the repository at this point in the history
* master:
  Set new staking limits (#3299)
  Bump derive_more from 0.99.11 to 0.99.14 (#3248)
  add revert consensus log (#3275)
  Add bridge team as codeowners of `bridges` Subtree (#3291)
  Extract and test count_no_shows method for approval voting (#3264)
  • Loading branch information
ordian committed Jun 18, 2021
2 parents 24befd1 + 63d1d49 commit ffb3135
Show file tree
Hide file tree
Showing 11 changed files with 331 additions and 27 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bridges/* @tomusdrw @svyatonik @hcastano
11 changes: 9 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion node/core/approval-voting/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ bitvec = { version = "0.20.1", default-features = false, features = ["alloc"] }
merlin = "2.0"
schnorrkel = "0.9.1"
kvdb = "0.9.0"
derive_more = "0.99.1"
derive_more = "0.99.14"

polkadot-node-subsystem = { path = "../../subsystem" }
polkadot-node-subsystem-util = { path = "../../subsystem-util" }
Expand Down
272 changes: 252 additions & 20 deletions node/core/approval-voting/src/approval_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,52 @@ fn filled_tranche_iterator<'a>(
pre.chain(approval_entries_filled).chain(post)
}

/// Computes the number of no_show validators in a set of assignments given the relevant approvals
/// and tick parameters. This method also returns the next tick at which a no_show will occur
/// amongst the set of validators that have not submitted an approval.
///
/// If the returned `next_no_show` is not None, there are two possible cases for the value of
/// based on the earliest assignment `tick` of a non-approving, yet-to-be-no-show validator:
/// - if `tick` <= `clock_drift`: the value will always be `clock_drift` + `no_show_duration`.
/// - if `tick` > `clock_drift`: the value is equal to `tick` + `no_show_duration`.
fn count_no_shows(
assignments: &[(ValidatorIndex, Tick)],
approvals: &BitSlice<BitOrderLsb0, u8>,
clock_drift: Tick,
no_show_duration: Tick,
drifted_tick_now: Tick,
) -> (usize, Option<u64>) {
let mut next_no_show = None;
let no_shows = assignments.iter()
.map(|(v_index, tick)| (v_index, tick.saturating_sub(clock_drift) + no_show_duration))
.filter(|&(v_index, no_show_at)| {
let has_approved = if let Some(approved) = approvals.get(v_index.0 as usize) {
*approved
} else {
return false;
};

let is_no_show = !has_approved && no_show_at <= drifted_tick_now;

if !is_no_show && !has_approved {
// When doing the comparison above, no_show_at and drifted_tick_now are calculated
// with the clock_drift removed. The reason for adding back the clock_drift in
// computing next_no_show is so that the scheduler knows the deadline at which
// *this node* should observe whether or not the validator is a no show. Recall
// that when the when drifted_tick_now is computed during that subsequent wake up,
// the clock drift will be removed again to do the comparison above.
next_no_show = super::min_prefer_some(
next_no_show,
Some(no_show_at + clock_drift),
);
}

is_no_show
}).count();

(no_shows, next_no_show)
}

/// Determine the amount of tranches of assignments needed to determine approval of a candidate.
pub fn tranches_to_approve(
approval_entry: &ApprovalEntry,
Expand Down Expand Up @@ -346,26 +392,13 @@ pub fn tranches_to_approve(
//
// While we count the no-shows, we also determine the next possible no-show we might
// see within this tranche.
let mut next_no_show = None;
let no_shows = {
let next_no_show = &mut next_no_show;
assignments.iter()
.map(|(v_index, tick)| (v_index, tick.saturating_sub(clock_drift) + no_show_duration))
.filter(|&(v_index, no_show_at)| {
let has_approved = approvals.get(v_index.0 as usize).map(|b| *b).unwrap_or(false);

let is_no_show = !has_approved && no_show_at <= drifted_tick_now;

if !is_no_show && !has_approved {
*next_no_show = super::min_prefer_some(
*next_no_show,
Some(no_show_at + clock_drift),
);
}

is_no_show
}).count()
};
let (no_shows, next_no_show) = count_no_shows(
assignments,
approvals,
clock_drift,
no_show_duration,
drifted_tick_now,
);

let s = s.advance(n_assignments, no_shows, next_no_show);
let output = s.output(tranche, needed_approvals, n_validators, no_show_duration);
Expand Down Expand Up @@ -993,6 +1026,205 @@ mod tests {
assert_eq!(tranches, exp_tranches, "for test tranches: {:?}", test_tranche);
}
}

#[derive(Debug)]
struct NoShowTest {
assignments: Vec<(ValidatorIndex, Tick)>,
approvals: Vec<usize>,
clock_drift: crate::time::Tick,
no_show_duration: crate::time::Tick,
drifted_tick_now: crate::time::Tick,
exp_no_shows: usize,
exp_next_no_show: Option<u64>,
}

fn test_count_no_shows(test: NoShowTest) {
let n_validators = 4;

let mut approvals = bitvec![BitOrderLsb0, u8; 0; n_validators];
for &v_index in &test.approvals {
approvals.set(v_index, true);
}

let (no_shows, next_no_show) = count_no_shows(
&test.assignments,
&approvals,
test.clock_drift,
test.no_show_duration,
test.drifted_tick_now,
);
assert_eq!(no_shows, test.exp_no_shows, "for test: {:?}", test);
assert_eq!(next_no_show, test.exp_next_no_show, "for test {:?}", test);
}

#[test]
fn count_no_shows_empty_assignments() {
test_count_no_shows(NoShowTest {
assignments: vec![],
approvals: vec![],
clock_drift: 0,
no_show_duration: 0,
drifted_tick_now: 0,
exp_no_shows: 0,
exp_next_no_show: None,
})
}

#[test]
fn count_no_shows_single_validator_is_next_no_show() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 21)],
approvals: vec![],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 0,
exp_next_no_show: Some(31),
})
}

#[test]
fn count_no_shows_single_validator_approval_at_drifted_tick_now() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 20)],
approvals: vec![1],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 0,
exp_next_no_show: None,
})
}

#[test]
fn count_no_shows_single_validator_approval_after_drifted_tick_now() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 21)],
approvals: vec![1],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 0,
exp_next_no_show: None,
})
}

#[test]
fn count_no_shows_two_validators_next_no_show_ordered_first() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 21), (ValidatorIndex(2), 22)],
approvals: vec![],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 0,
exp_next_no_show: Some(31),
})
}

#[test]
fn count_no_shows_two_validators_next_no_show_ordered_last() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 22), (ValidatorIndex(2), 21)],
approvals: vec![],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 0,
exp_next_no_show: Some(31),
})
}

#[test]
fn count_no_shows_three_validators_one_almost_late_one_no_show_one_approving() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 21), (ValidatorIndex(2), 20), (ValidatorIndex(3), 20)],
approvals: vec![3],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 1,
exp_next_no_show: Some(31),
})
}

#[test]
fn count_no_shows_three_no_show_validators() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 20), (ValidatorIndex(2), 20), (ValidatorIndex(3), 20)],
approvals: vec![],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 3,
exp_next_no_show: None,
})
}

#[test]
fn count_no_shows_three_approving_validators() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 20), (ValidatorIndex(2), 20), (ValidatorIndex(3), 20)],
approvals: vec![1, 2, 3],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 0,
exp_next_no_show: None,
})
}

#[test]
fn count_no_shows_earliest_possible_next_no_show_is_clock_drift_plus_no_show_duration() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 0)],
approvals: vec![],
clock_drift: 10,
no_show_duration: 20,
drifted_tick_now: 0,
exp_no_shows: 0,
exp_next_no_show: Some(30),
})
}

#[test]
fn count_no_shows_assignment_tick_equal_to_clock_drift_yields_earliest_possible_next_no_show() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1), 10)],
approvals: vec![],
clock_drift: 10,
no_show_duration: 20,
drifted_tick_now: 0,
exp_no_shows: 0,
exp_next_no_show: Some(30),
})
}

#[test]
fn count_no_shows_validator_index_out_of_approvals_range_is_ignored_as_no_show() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1000), 20)],
approvals: vec![],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 0,
exp_next_no_show: None,
})
}

#[test]
fn count_no_shows_validator_index_out_of_approvals_range_is_ignored_as_next_no_show() {
test_count_no_shows(NoShowTest {
assignments: vec![(ValidatorIndex(1000), 21)],
approvals: vec![],
clock_drift: 10,
no_show_duration: 10,
drifted_tick_now: 20,
exp_no_shows: 0,
exp_next_no_show: None,
})
}
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion node/core/dispute-coordinator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ futures = "0.3.12"
tracing = "0.1.26"
parity-scale-codec = "2"
kvdb = "0.9.0"
derive_more = "0.99.1"
derive_more = "0.99.14"
thiserror = "1.0.23"

polkadot-primitives = { path = "../../../primitives" }
Expand Down
2 changes: 1 addition & 1 deletion node/subsystem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description = "Subsystem traits and message definitions"
[dependencies]
async-std = "1.8.0"
async-trait = "0.1.42"
derive_more = "0.99.11"
derive_more = "0.99.14"
futures = "0.3.15"
futures-timer = "3.0.2"
mick-jaeger = "0.1.2"
Expand Down
10 changes: 10 additions & 0 deletions primitives/src/v1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,16 @@ pub enum ConsensusLog {
/// number in the current chain, inclusive.
#[codec(index = 3)]
ForceApprove(BlockNumber),
/// A signal to revert the block number in the same chain as the
/// header this digest is part of and all of its descendents.
///
/// It is a no-op for a block to contain a revert digest targeting
/// its own number or a higher number.
///
/// In practice, these are issued when on-chain logic has detected an
/// invalid parachain block within its own chain, due to a dispute.
#[codec(index = 4)]
Revert(BlockNumber)
}

impl ConsensusLog {
Expand Down
21 changes: 21 additions & 0 deletions runtime/kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1513,10 +1513,31 @@ pub type Executive = frame_executive::Executive<
frame_system::ChainContext<Runtime>,
Runtime,
AllPallets,
SetStakingLimits,
>;
/// The payload being signed in the transactions.
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;

pub struct SetStakingLimits;
impl frame_support::traits::OnRuntimeUpgrade for SetStakingLimits {
fn on_runtime_upgrade() -> Weight {
// This will be the threshold needed henceforth to become a nominator. All nominators will
// less than this amount bonded are at the risk of being chilled by another reporter.
let min_nominator_bond = UNITS / 10;
// The absolute maximum number of nominators. This number is set rather conservatively, and
// is expected to increase soon after this runtime upgrade via another governance proposal.
// The current Polkadot state has more than 30_000 nominators, therefore no other nominator
// can join.
let max_nominators = 20_000;
<pallet_staking::MinNominatorBond<Runtime>>::put(min_nominator_bond);
<pallet_staking::MaxNominatorsCount<Runtime>>::put(max_nominators);

// we set no limits on validators for now.

<Runtime as frame_system::Config>::DbWeight::get().writes(2)
}
}

#[cfg(not(feature = "disable-runtime-api"))]
sp_api::impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
Expand Down
Loading

0 comments on commit ffb3135

Please sign in to comment.