Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4 / 5] Make approval-voting runnable on a worker thread #4846

Merged
merged 28 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8dbb088
Make approval-distribution logic runnable on a separate thread
alexggh Jun 17, 2024
14727c5
Move crypto checks in the approval-distribution
alexggh Jun 19, 2024
1942139
Make approval-voting runable on a worker thread
alexggh Jun 18, 2024
7175957
Address review feedback
alexggh Jul 26, 2024
469866f
Merge remote-tracking branch 'origin/alexaggh/approval-voting-paralle…
alexggh Jul 26, 2024
d9fdd51
Address review feedback
alexggh Jul 26, 2024
135fe79
Merge remote-tracking branch 'origin/alexaggh/approval-voting-paralle…
alexggh Jul 26, 2024
2752d6e
Fail early on oversized claims
alexggh Jul 29, 2024
00d22ee
Add more unittests
alexggh Jul 29, 2024
4f99f65
Merge remote-tracking branch 'origin/master' into alexaggh/approval-v…
alexggh Jul 29, 2024
f289995
Merge remote-tracking branch 'origin/alexaggh/approval-voting-paralle…
alexggh Jul 29, 2024
ead49d2
Review feedback
alexggh Aug 8, 2024
c67d99d
Add checked indirect assignment
alexggh Aug 8, 2024
23d5a28
Merge remote-tracking branch 'origin/alexaggh/approval-voting-paralle…
alexggh Aug 8, 2024
247161f
Merge remote-tracking branch 'origin/master' into alexaggh/approval-v…
alexggh Aug 12, 2024
edd7898
Merge remote-tracking branch 'origin/alexaggh/approval-voting-paralle…
alexggh Aug 12, 2024
0b140cc
Change OurViewChange order
alexggh Aug 13, 2024
0581468
Merge branch 'fix_signal_order' into alexaggh/approval-voting-paralle…
alexggh Aug 13, 2024
08889e1
Merge remote-tracking branch 'origin/master' into alexaggh/approval-v…
alexggh Aug 14, 2024
d04d4cc
Merge branch 'alexaggh/approval-voting-parallel-3-5' into alexaggh/ap…
alexggh Aug 14, 2024
b0fb6d4
Merge remote-tracking branch 'origin/master' into alexaggh/approval-v…
alexggh Aug 27, 2024
7539184
Remove crate dependency between approval-distribution and approval-vo…
alexggh Aug 27, 2024
8da0be8
Merge branch 'alexaggh/approval-voting-parallel-3-5' into alexaggh/ap…
alexggh Aug 27, 2024
377f4e1
Address review feedback
alexggh Aug 27, 2024
f5a2447
Merge remote-tracking branch 'origin/master' into alexaggh/approval-v…
alexggh Sep 9, 2024
2410bd2
Update polkadot/node/core/approval-voting/src/lib.rs
alexggh Sep 9, 2024
72150d4
Add prdoc
alexggh Sep 11, 2024
e58ec71
Make cargo fmt happy
alexggh Sep 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions polkadot/cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,16 +373,16 @@ pub fn run() -> Result<()> {
Ok(runner.async_run(|mut config| {
let (client, backend, _, task_manager) =
polkadot_service::new_chain_ops(&mut config, None)?;
let task_handle = task_manager.spawn_handle();
let aux_revert = Box::new(|client, backend, blocks| {
polkadot_service::revert_backend(client, backend, blocks, config).map_err(
|err| {
polkadot_service::revert_backend(client, backend, blocks, config, task_handle)
.map_err(|err| {
match err {
polkadot_service::Error::Blockchain(err) => err.into(),
// Generic application-specific error.
err => sc_cli::Error::Application(err.into()),
}
},
)
})
});
Ok((
cmd.run(client, backend, Some(aux_revert)).map_err(Error::SubstrateCli),
Expand Down
1 change: 1 addition & 0 deletions polkadot/node/core/approval-voting/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ kvdb = { workspace = true }
derive_more = { workspace = true, default-features = true }
thiserror = { workspace = true }
itertools = { workspace = true }
async-trait = { workspace = true }

polkadot-node-subsystem = { workspace = true, default-features = true }
polkadot-node-subsystem-util = { workspace = true, default-features = true }
Expand Down
8 changes: 4 additions & 4 deletions polkadot/node/core/approval-voting/src/approval_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ use polkadot_primitives::ValidatorIndex;

use crate::{
persisted_entries::{ApprovalEntry, CandidateEntry, TrancheEntry},
time::Tick,
MAX_RECORDED_NO_SHOW_VALIDATORS_PER_CANDIDATE,
};
use polkadot_node_primitives::approval::time::Tick;

/// Result of counting the necessary tranches needed for approving a block.
#[derive(Debug, PartialEq, Clone)]
Expand Down Expand Up @@ -1195,9 +1195,9 @@ mod tests {
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,
clock_drift: Tick,
no_show_duration: Tick,
drifted_tick_now: Tick,
exp_no_shows: usize,
exp_next_no_show: Option<u64>,
}
Expand Down
174 changes: 29 additions & 145 deletions polkadot/node/core/approval-voting/src/criteria.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@

//! Assignment criteria VRF generation and checking.

use codec::{Decode, Encode};
use codec::Encode;
use itertools::Itertools;
pub use polkadot_node_primitives::approval::criteria::{
AssignmentCriteria, Config, InvalidAssignment, InvalidAssignmentReason, OurAssignment,
};
use polkadot_node_primitives::approval::{
self as approval_types,
v1::{AssignmentCert, AssignmentCertKind, DelayTranche, RelayVRFStory},
v2::{
AssignmentCertKindV2, AssignmentCertV2, CoreBitfield, VrfPreOutput, VrfProof, VrfSignature,
},
};

use polkadot_primitives::{
AssignmentId, AssignmentPair, CandidateHash, CoreIndex, GroupIndex, IndexedVec, SessionInfo,
ValidatorIndex,
AssignmentPair, CandidateHash, CoreIndex, GroupIndex, IndexedVec, ValidatorIndex,
};
use rand::{seq::SliceRandom, SeedableRng};
use rand_chacha::ChaCha20Rng;
Expand All @@ -44,56 +47,19 @@ use std::{

use super::LOG_TARGET;

/// Details pertaining to our assignment on a block.
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
pub struct OurAssignment {
cert: AssignmentCertV2,
tranche: DelayTranche,
validator_index: ValidatorIndex,
// Whether the assignment has been triggered already.
triggered: bool,
}

impl OurAssignment {
pub fn cert(&self) -> &AssignmentCertV2 {
&self.cert
}

pub fn tranche(&self) -> DelayTranche {
self.tranche
}

pub(crate) fn validator_index(&self) -> ValidatorIndex {
self.validator_index
}

pub(crate) fn triggered(&self) -> bool {
self.triggered
}

pub(crate) fn mark_triggered(&mut self) {
self.triggered = true;
}
}

impl From<crate::approval_db::v2::OurAssignment> for OurAssignment {
fn from(entry: crate::approval_db::v2::OurAssignment) -> Self {
OurAssignment {
cert: entry.cert,
tranche: entry.tranche,
validator_index: entry.validator_index,
triggered: entry.triggered,
}
OurAssignment::new(entry.cert, entry.tranche, entry.validator_index, entry.triggered)
}
}

impl From<OurAssignment> for crate::approval_db::v2::OurAssignment {
fn from(entry: OurAssignment) -> Self {
Self {
cert: entry.cert,
tranche: entry.tranche,
validator_index: entry.validator_index,
triggered: entry.triggered,
tranche: entry.tranche(),
validator_index: entry.validator_index(),
triggered: entry.triggered(),
cert: entry.into_cert(),
}
}
}
Expand Down Expand Up @@ -223,60 +189,7 @@ fn assigned_core_transcript(core_index: CoreIndex) -> Transcript {
t
}

/// Information about the world assignments are being produced in.
#[derive(Clone, Debug)]
pub struct Config {
/// The assignment public keys for validators.
assignment_keys: Vec<AssignmentId>,
/// The groups of validators assigned to each core.
validator_groups: IndexedVec<GroupIndex, Vec<ValidatorIndex>>,
/// The number of availability cores used by the protocol during this session.
n_cores: u32,
/// The zeroth delay tranche width.
zeroth_delay_tranche_width: u32,
/// The number of samples we do of `relay_vrf_modulo`.
relay_vrf_modulo_samples: u32,
/// The number of delay tranches in total.
n_delay_tranches: u32,
}

impl<'a> From<&'a SessionInfo> for Config {
fn from(s: &'a SessionInfo) -> Self {
Config {
assignment_keys: s.assignment_keys.clone(),
validator_groups: s.validator_groups.clone(),
n_cores: s.n_cores,
zeroth_delay_tranche_width: s.zeroth_delay_tranche_width,
relay_vrf_modulo_samples: s.relay_vrf_modulo_samples,
n_delay_tranches: s.n_delay_tranches,
}
}
}

/// A trait for producing and checking assignments. Used to mock.
pub(crate) trait AssignmentCriteria {
fn compute_assignments(
&self,
keystore: &LocalKeystore,
relay_vrf_story: RelayVRFStory,
config: &Config,
leaving_cores: Vec<(CandidateHash, CoreIndex, GroupIndex)>,
enable_v2_assignments: bool,
) -> HashMap<CoreIndex, OurAssignment>;

fn check_assignment_cert(
&self,
claimed_core_bitfield: CoreBitfield,
validator_index: ValidatorIndex,
config: &Config,
relay_vrf_story: RelayVRFStory,
assignment: &AssignmentCertV2,
// Backing groups for each "leaving core".
backing_groups: Vec<GroupIndex>,
) -> Result<DelayTranche, InvalidAssignment>;
}

pub(crate) struct RealAssignmentCriteria;
pub struct RealAssignmentCriteria;

impl AssignmentCriteria for RealAssignmentCriteria {
fn compute_assignments(
Expand Down Expand Up @@ -469,12 +382,12 @@ fn compute_relay_vrf_modulo_assignments_v1(
};

// All assignments of type RelayVRFModulo have tranche 0.
assignments.entry(core).or_insert(OurAssignment {
cert: cert.into(),
tranche: 0,
assignments.entry(core).or_insert(OurAssignment::new(
cert.into(),
0,
validator_index,
triggered: false,
});
false,
));
}
}
}
Expand Down Expand Up @@ -549,7 +462,7 @@ fn compute_relay_vrf_modulo_assignments_v2(
};

// All assignments of type RelayVRFModulo have tranche 0.
OurAssignment { cert, tranche: 0, validator_index, triggered: false }
OurAssignment::new(cert, 0, validator_index, false)
}) {
for core_index in assigned_cores {
assignments.insert(core_index, assignment.clone());
Expand Down Expand Up @@ -583,15 +496,15 @@ fn compute_relay_vrf_delay_assignments(
},
};

let our_assignment = OurAssignment { cert, tranche, validator_index, triggered: false };
let our_assignment = OurAssignment::new(cert, tranche, validator_index, false);

let used = match assignments.entry(core) {
Entry::Vacant(e) => {
let _ = e.insert(our_assignment);
true
},
Entry::Occupied(mut e) =>
if e.get().tranche > our_assignment.tranche {
if e.get().tranche() > our_assignment.tranche() {
e.insert(our_assignment);
true
} else {
Expand All @@ -612,35 +525,6 @@ fn compute_relay_vrf_delay_assignments(
}
}

/// Assignment invalid.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct InvalidAssignment(pub(crate) InvalidAssignmentReason);

impl std::fmt::Display for InvalidAssignment {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Invalid Assignment: {:?}", self.0)
}
}

impl std::error::Error for InvalidAssignment {}

/// Failure conditions when checking an assignment cert.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum InvalidAssignmentReason {
ValidatorIndexOutOfBounds,
SampleOutOfBounds,
CoreIndexOutOfBounds,
InvalidAssignmentKey,
IsInBackingGroup,
VRFModuloCoreIndexMismatch,
VRFModuloOutputMismatch,
VRFDelayCoreIndexMismatch,
VRFDelayOutputMismatch,
InvalidArguments,
/// Assignment vrf check resulted in 0 assigned cores.
NullAssignment,
}

/// Checks the crypto of an assignment cert. Failure conditions:
/// * Validator index out of bounds
/// * VRF signature check fails
Expand Down Expand Up @@ -820,21 +704,21 @@ fn is_in_backing_group(
/// Migration helpers.
impl From<crate::approval_db::v1::OurAssignment> for OurAssignment {
fn from(value: crate::approval_db::v1::OurAssignment) -> Self {
Self {
cert: value.cert.into(),
tranche: value.tranche,
validator_index: value.validator_index,
Self::new(
value.cert.into(),
value.tranche,
value.validator_index,
// Whether the assignment has been triggered already.
triggered: value.triggered,
}
value.triggered,
)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::import::tests::garbage_vrf_signature;
use polkadot_primitives::{Hash, ASSIGNMENT_KEY_TYPE_ID};
use polkadot_primitives::{AssignmentId, Hash, ASSIGNMENT_KEY_TYPE_ID};
use sp_application_crypto::sr25519;
use sp_core::crypto::Pair as PairT;
use sp_keyring::sr25519::Keyring as Sr25519Keyring;
Expand Down Expand Up @@ -1053,7 +937,7 @@ mod tests {

let mut counted = 0;
for (core, assignment) in assignments {
let cores = match assignment.cert.kind.clone() {
let cores = match assignment.cert().kind.clone() {
AssignmentCertKindV2::RelayVRFModuloCompact { core_bitfield } => core_bitfield,
AssignmentCertKindV2::RelayVRFModulo { sample: _ } => core.into(),
AssignmentCertKindV2::RelayVRFDelay { core_index } => core_index.into(),
Expand All @@ -1062,7 +946,7 @@ mod tests {
let mut mutated = MutatedAssignment {
cores: cores.clone(),
groups: cores.iter_ones().map(|core| group_for_core(core)).collect(),
cert: assignment.cert,
cert: assignment.into_cert(),
own_group: GroupIndex(0),
val_index: ValidatorIndex(0),
config: config.clone(),
Expand Down
Loading
Loading