Skip to content

Commit

Permalink
Merge pull request #2036 from subspace/distinguish-pot-chain-reorg-ex…
Browse files Browse the repository at this point in the history
…tension

Distinguish between PoT chain reorg and extension during state update
  • Loading branch information
nazar-pc authored Oct 2, 2023
2 parents cae70b7 + 9ed6648 commit 606d259
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 16 deletions.
56 changes: 43 additions & 13 deletions crates/sc-proof-of-time/src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod state;
mod timekeeper;

use crate::source::gossip::{GossipProof, PotGossipWorker, ToGossipMessage};
use crate::source::state::{NextSlotInput, PotState};
use crate::source::state::{NextSlotInput, PotState, PotStateUpdateOutcome};
use crate::source::timekeeper::{run_timekeeper, TimekeeperProof};
use crate::verifier::PotVerifier;
use core_affinity::CoreId;
Expand All @@ -27,7 +27,7 @@ use std::marker::PhantomData;
use std::sync::Arc;
use std::thread;
use subspace_core_primitives::PotCheckpoints;
use tracing::{debug, error, warn};
use tracing::{debug, error, trace, warn};

const LOCAL_PROOFS_CHANNEL_CAPACITY: usize = 10;
const SLOTS_CHANNEL_CAPACITY: usize = 10;
Expand Down Expand Up @@ -335,24 +335,54 @@ where
// This will do one of 3 things depending on circumstances:
// * if block import is ahead of timekeeper and gossip, it will update next slot input
// * if block import is on a different PoT chain, it will update next slot input to the
// correct fork
// correct fork (reorg)
// * if block import is on the same PoT chain this will essentially do nothing
if let Some(next_slot_input) = self.state.update(
match self.state.update(
best_slot,
best_proof,
Some(subspace_digest_items.pot_parameters_change),
) {
warn!("Proof of time chain reorg happened");
PotStateUpdateOutcome::NoChange => {
trace!(
%best_slot,
"Block import didn't result in proof of time chain changes",
);
}
PotStateUpdateOutcome::Extension { from, to } => {
warn!(
from_next_slot = %from.slot,
to_next_slot = %to.slot,
"Proof of time chain was extended from block import",
);

if self
.to_gossip_sender
.try_send(ToGossipMessage::NextSlotInput(next_slot_input))
.is_err()
{
debug!(
next_slot = %next_slot_input.slot,
"Gossip is not able to keep-up with slot production (block import)",
if self
.to_gossip_sender
.try_send(ToGossipMessage::NextSlotInput(to))
.is_err()
{
debug!(
next_slot = %to.slot,
"Gossip is not able to keep-up with slot production (block import)",
);
}
}
PotStateUpdateOutcome::Reorg { from, to } => {
warn!(
from_next_slot = %from.slot,
to_next_slot = %to.slot,
"Proof of time chain reorg happened",
);

if self
.to_gossip_sender
.try_send(ToGossipMessage::NextSlotInput(to))
.is_err()
{
debug!(
next_slot = %to.slot,
"Gossip is not able to keep-up with slot production (block import)",
);
}
}
}
}
Expand Down
63 changes: 60 additions & 3 deletions crates/sc-proof-of-time/src/source/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ impl InnerState {
}
}

#[derive(Debug)]
pub(super) enum PotStateUpdateOutcome {
NoChange,
Extension {
from: NextSlotInput,
to: NextSlotInput,
},
Reorg {
from: NextSlotInput,
to: NextSlotInput,
},
}

#[derive(Debug)]
pub(super) struct PotState {
inner_state: Atomic<InnerState>,
Expand Down Expand Up @@ -145,7 +158,7 @@ impl PotState {
best_slot: Slot,
best_output: PotOutput,
maybe_updated_parameters_change: Option<Option<PotParametersChange>>,
) -> Option<NextSlotInput> {
) -> PotStateUpdateOutcome {
let mut best_state = None;
// Use `fetch_update` such that we don't accidentally downgrade best slot to smaller value
let previous_best_state = self
Expand All @@ -163,7 +176,51 @@ impl PotState {
.expect("Callback always returns `Some`; qed");
let best_state = best_state.expect("Replaced with `Some` above; qed");

(previous_best_state.next_slot_input != best_state.next_slot_input)
.then_some(best_state.next_slot_input)
if previous_best_state.next_slot_input == best_state.next_slot_input {
return PotStateUpdateOutcome::NoChange;
}

if previous_best_state.next_slot_input.slot < best_state.next_slot_input.slot {
let mut slot_iterations = previous_best_state.next_slot_input.slot_iterations;
let mut seed = previous_best_state.next_slot_input.seed;

for slot in u64::from(previous_best_state.next_slot_input.slot)
..u64::from(best_state.next_slot_input.slot)
{
let slot = Slot::from(slot);

let Some(checkpoints) = self.verifier.try_get_checkpoints(seed, slot_iterations)
else {
break;
};

let next_slot = slot + Slot::from(1);

// In case parameters change in the next slot, account for them
if let Some(Some(parameters_change)) = maybe_updated_parameters_change
&& parameters_change.slot == next_slot
{
slot_iterations = parameters_change.slot_iterations;
seed = checkpoints.output().seed_with_entropy(&parameters_change.entropy);
} else {
seed = checkpoints.output().seed();
}

if next_slot == best_state.next_slot_input.slot
&& slot_iterations == best_state.next_slot_input.slot_iterations
&& seed == best_state.next_slot_input.seed
{
return PotStateUpdateOutcome::Extension {
from: previous_best_state.next_slot_input,
to: best_state.next_slot_input,
};
}
}
}

PotStateUpdateOutcome::Reorg {
from: previous_best_state.next_slot_input,
to: best_state.next_slot_input,
}
}
}

0 comments on commit 606d259

Please sign in to comment.