Skip to content

Commit

Permalink
Merge pull request #675 from paritytech/AndreiEres/async-backing-cand…
Browse files Browse the repository at this point in the history
…idates

Fix candidate tracking on async backing
  • Loading branch information
AndreiEres authored Apr 19, 2024
2 parents 76842f5 + 0465afe commit 5f05614
Show file tree
Hide file tree
Showing 9 changed files with 540 additions and 338 deletions.
8 changes: 7 additions & 1 deletion essentials/src/chain_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub struct SubxtCandidateEvent {
pub parachain_id: u32,
/// The event type
pub event_type: SubxtCandidateEventType,
/// Core index
pub core_idx: u32,
}

/// A helper structure to keep track of a dispute and it's relay parent
Expand Down Expand Up @@ -126,6 +128,7 @@ pub async fn decode_chain_event<T: subxt::Config>(
return Ok(ChainEvent::CandidateChanged(Box::new(create_candidate_event(
decoded.0.commitments_hash,
decoded.0.descriptor,
decoded.2 .0,
SubxtCandidateEventType::Backed,
))))
}
Expand All @@ -135,6 +138,7 @@ pub async fn decode_chain_event<T: subxt::Config>(
return Ok(ChainEvent::CandidateChanged(Box::new(create_candidate_event(
decoded.0.commitments_hash,
decoded.0.descriptor,
decoded.2 .0,
SubxtCandidateEventType::Included,
))))
}
Expand All @@ -144,6 +148,7 @@ pub async fn decode_chain_event<T: subxt::Config>(
return Ok(ChainEvent::CandidateChanged(Box::new(create_candidate_event(
decoded.0.commitments_hash,
decoded.0.descriptor,
decoded.2 .0,
SubxtCandidateEventType::TimedOut,
))))
}
Expand Down Expand Up @@ -190,9 +195,10 @@ fn decode_to_specific_event<E: subxt::events::StaticEvent, C: subxt::Config>(
fn create_candidate_event(
commitments_hash: <PolkadotConfig as subxt::Config>::Hash,
candidate_descriptor: CandidateDescriptor<<PolkadotConfig as subxt::Config>::Hash>,
core_idx: u32,
event_type: SubxtCandidateEventType,
) -> SubxtCandidateEvent {
let candidate_hash = BlakeTwo256::hash_of(&(&candidate_descriptor, commitments_hash));
let parachain_id = candidate_descriptor.para_id.0;
SubxtCandidateEvent { event_type, candidate_descriptor, parachain_id, candidate_hash }
SubxtCandidateEvent { event_type, candidate_descriptor, parachain_id, candidate_hash, core_idx }
}
11 changes: 10 additions & 1 deletion essentials/src/collector/candidate_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct CandidateInclusionRecord<T: Encode + Decode + Clone> {
/// Relay parent block number when a candidate was timed out
pub timedout: Option<u32>,
/// Observed core index
pub core_idx: Option<u32>,
pub core_idx: u32,
/// Stated relay parent
pub relay_parent: T,
/// Stated relay parent number
Expand Down Expand Up @@ -109,6 +109,11 @@ pub struct CandidateRecord {
}

impl CandidateRecord {
/// Returns if a candidate has been included
pub fn is_included(&self) -> bool {
self.candidate_inclusion.included.is_some()
}

/// Returns if a candidate has been disputed
#[allow(dead_code)]
pub fn is_disputed(&self) -> bool {
Expand Down Expand Up @@ -144,4 +149,8 @@ impl CandidateRecord {
pub fn parachain_id(&self) -> u32 {
self.candidate_inclusion.parachain_id
}

pub fn core_idx(&self) -> u32 {
self.candidate_inclusion.core_idx
}
}
2 changes: 1 addition & 1 deletion essentials/src/collector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ impl Collector {
relay_parent_number: relay_parent.number,
parachain_id: change_event.parachain_id,
backed: relay_block_number,
core_idx: None,
core_idx: change_event.core_idx,
timedout: None,
included: None,
};
Expand Down
105 changes: 15 additions & 90 deletions parachain-tracer/src/parachain_block_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,30 @@ use subxt::config::{substrate::BlakeTwo256, Hasher};
/// This is used for displaying CLI updates and also goes to Storage.
#[derive(Encode, Decode, Debug, Default)]
pub struct ParachainBlockInfo {
/// The candidate information as observed during backing
pub candidate: Option<BackedCandidate<H256>>,
/// Candidate hash
pub candidate_hash: Option<H256>,
/// The current state.
state: ParachainBlockState,
pub candidate_hash: H256,
/// The number of signed bitfields.
pub bitfield_count: u32,
/// The maximum expected number of availability bits that can be set. Corresponds to `max_validators`.
pub max_availability_bits: u32,
/// The current number of observed availability bits set to 1.
pub current_availability_bits: u32,
/// Parachain availability core assignment information.
pub assigned_core: Option<u32>,
pub assigned_core: u32,
/// Core occupation status.
pub core_occupied: bool,
/// The current state.
pub state: ParachainBlockState,
}

impl ParachainBlockInfo {
pub fn maybe_reset(&mut self) {
if self.is_included() {
self.state = ParachainBlockState::Idle;
self.candidate = None;
self.candidate_hash = None;
}
pub fn new(candidate_hash: H256, assigned_core: u32, bitfield_count: u32) -> Self {
Self { candidate_hash, assigned_core, bitfield_count, ..Default::default() }
}

pub fn set_idle(&mut self) {
self.state = ParachainBlockState::Idle
}

pub fn set_backed(&mut self) {
self.state = ParachainBlockState::Backed
pub fn candidate_hash(candidate: &BackedCandidate<H256>) -> H256 {
let commitments_hash = BlakeTwo256::hash_of(&candidate.candidate.commitments);
BlakeTwo256::hash_of(&(&candidate.candidate.descriptor, commitments_hash))
}

pub fn set_pending(&mut self) {
Expand All @@ -65,45 +56,24 @@ impl ParachainBlockInfo {
self.state = ParachainBlockState::Included
}

pub fn set_candidate(&mut self, candidate: BackedCandidate<H256>) {
let commitments_hash = BlakeTwo256::hash_of(&candidate.candidate.commitments);
let candidate_hash = BlakeTwo256::hash_of(&(&candidate.candidate.descriptor, commitments_hash));
self.candidate_hash = Some(candidate_hash);
self.candidate = Some(candidate);
}

pub fn is_idle(&self) -> bool {
self.state == ParachainBlockState::Idle
}

pub fn is_backed(&self) -> bool {
self.state == ParachainBlockState::Backed
}

pub fn is_pending(&self) -> bool {
self.state == ParachainBlockState::PendingAvailability
}

pub fn is_included(&self) -> bool {
self.state == ParachainBlockState::Included
}

pub fn is_data_available(&self) -> bool {
self.current_availability_bits > (self.max_availability_bits / 3) * 2
}

pub fn is_bitfield_propagation_slow(&self) -> bool {
self.max_availability_bits > 0 && !self.is_idle() && self.bitfield_count <= (self.max_availability_bits / 3) * 2
self.max_availability_bits > 0 && self.bitfield_count <= (self.max_availability_bits / 3) * 2
}
}

/// The state of parachain block.
#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, Eq)]
enum ParachainBlockState {
// Parachain block pipeline is idle.
#[default]
Idle,
pub enum ParachainBlockState {
// A candidate is currently backed.
#[default]
Backed,
// A candidate is pending inclusion.
PendingAvailability,
Expand All @@ -115,60 +85,15 @@ enum ParachainBlockState {
mod tests {
use crate::test_utils::create_para_block_info;

#[test]
fn test_does_not_reset_state_if_not_included() {
let mut info = create_para_block_info();
info.set_backed();

assert!(info.is_backed());
assert!(info.candidate.is_some());
assert!(info.candidate_hash.is_some());

info.maybe_reset();

assert!(info.is_backed());
assert!(info.candidate.is_some());
assert!(info.candidate_hash.is_some());
}

#[test]
fn test_resets_state_if_included() {
let mut info = create_para_block_info();
info.set_included();

assert!(info.is_included());
assert!(info.candidate.is_some());
assert!(info.candidate_hash.is_some());

info.maybe_reset();

assert!(info.is_idle());
assert!(info.candidate.is_none());
assert!(info.candidate_hash.is_none());
}

#[test]
fn test_is_data_available() {
let mut info = create_para_block_info();
assert!(!info.is_data_available());

info.max_availability_bits = 200;
info.current_availability_bits = 134;
assert!(info.is_data_available());
}

#[test]
fn test_is_bitfield_propagation_slow() {
let mut info = create_para_block_info();
let mut info = create_para_block_info(100);
assert!(!info.is_bitfield_propagation_slow());

info.max_availability_bits = 200;
assert!(!info.is_bitfield_propagation_slow());

info.bitfield_count = 100;
assert!(!info.is_bitfield_propagation_slow());
assert!(info.is_bitfield_propagation_slow());

info.set_backed();
info.bitfield_count = 120;
assert!(info.is_bitfield_propagation_slow());
}
}
38 changes: 7 additions & 31 deletions parachain-tracer/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,17 @@ pub fn create_hrmp_channels() -> BTreeMap<u32, SubxtHrmpChannel> {
pub fn create_candidate_record(
para_id: u32,
backed: u32,
included: Option<u32>,
relay_parent: H256,
relay_parent_number: u32,
) -> CandidateRecord {
CandidateRecord {
candidate_inclusion: CandidateInclusionRecord {
parachain_id: para_id,
backed,
included: None,
included,
timedout: None,
core_idx: None,
core_idx: 0,
relay_parent,
relay_parent_number,
},
Expand All @@ -161,35 +162,10 @@ pub fn create_candidate_record(
}
}

pub fn create_para_block_info() -> ParachainBlockInfo {
let mut info = ParachainBlockInfo::default();
info.set_candidate(BackedCandidate {
candidate: CommittedCandidateReceipt {
descriptor: CandidateDescriptor {
para_id: Id(100),
relay_parent: Default::default(),
collator: collator_app::Public(Public([0; 32])),
persisted_validation_data_hash: Default::default(),
pov_hash: Default::default(),
erasure_root: Default::default(),
signature: collator_app::Signature(Signature([0; 64])),
para_head: Default::default(),
validation_code_hash: ValidationCodeHash(Default::default()),
},
commitments: CandidateCommitments {
upward_messages: BoundedVec(Default::default()),
horizontal_messages: BoundedVec(Default::default()),
new_validation_code: Default::default(),
head_data: HeadData(Default::default()),
processed_downward_messages: Default::default(),
hrmp_watermark: Default::default(),
},
},
validity_votes: vec![],
validator_indices: DecodedBits::from_iter([true]),
});

info
pub fn create_para_block_info(para_id: u32) -> ParachainBlockInfo {
let candidate = create_backed_candidate(para_id);
let hash = ParachainBlockInfo::candidate_hash(&candidate);
ParachainBlockInfo::new(hash, 0, 0)
}

pub async fn storage_write<T: Encode>(
Expand Down
Loading

0 comments on commit 5f05614

Please sign in to comment.