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

Pot verification preparation #1900

Merged
merged 10 commits into from
Aug 30, 2023
22 changes: 11 additions & 11 deletions crates/pallet-subspace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ use sp_std::collections::btree_map::BTreeMap;
use sp_std::prelude::*;
use subspace_core_primitives::crypto::Scalar;
#[cfg(feature = "pot")]
use subspace_core_primitives::PotCheckpoint;
use subspace_core_primitives::PotProof;
use subspace_core_primitives::{
ArchivedHistorySegment, HistorySize, PublicKey, Randomness, RewardSignature, SectorId,
SectorIndex, SegmentHeader, SegmentIndex, SolutionRange,
Expand Down Expand Up @@ -785,15 +785,15 @@ impl<T: Config> Pallet<T> {
// On the first non-zero block (i.e. block #1) we need to adjust internal storage
// accordingly.
if *GenesisSlot::<T>::get() == 0 {
GenesisSlot::<T>::put(pre_digest.slot);
GenesisSlot::<T>::put(pre_digest.slot());
debug_assert_ne!(*GenesisSlot::<T>::get(), 0);
}

// The slot number of the current block being initialized.
CurrentSlot::<T>::put(pre_digest.slot);
CurrentSlot::<T>::put(pre_digest.slot());

{
let farmer_public_key = pre_digest.solution.public_key.clone();
let farmer_public_key = pre_digest.solution().public_key.clone();

// Optional restriction for block authoring to the root user
if !AllowAuthoringByAnyone::<T>::get() {
Expand All @@ -817,10 +817,10 @@ impl<T: Config> Pallet<T> {

let key = (
farmer_public_key,
pre_digest.solution.sector_index,
pre_digest.solution.chunk,
AuditChunkOffset(pre_digest.solution.audit_chunk_offset),
pre_digest.slot,
pre_digest.solution().sector_index,
pre_digest.solution().chunk,
AuditChunkOffset(pre_digest.solution().audit_chunk_offset),
pre_digest.slot(),
);
if ParentBlockVoters::<T>::get().contains_key(&key) {
let (public_key, _sector_index, _chunk, _audit_chunk_offset, slot) = key;
Expand Down Expand Up @@ -848,7 +848,7 @@ impl<T: Config> Pallet<T> {
chunk,
audit_chunk_offset,
slot,
pre_digest.solution.reward_address.clone(),
pre_digest.solution().reward_address.clone(),
));
}
}
Expand Down Expand Up @@ -883,7 +883,7 @@ impl<T: Config> Pallet<T> {

// Extract PoR randomness from pre-digest.
#[cfg(not(feature = "pot"))]
let por_randomness = derive_randomness(&pre_digest.solution, pre_digest.slot.into());
let por_randomness = derive_randomness(pre_digest.solution(), pre_digest.slot().into());
// Store PoR randomness for block duration as it might be useful.
#[cfg(not(feature = "pot"))]
PorRandomness::<T>::put(por_randomness);
Expand Down Expand Up @@ -1447,7 +1447,7 @@ fn check_vote<T: Config>(
global_randomness: vote_verification_data.global_randomness,
// TODO: This is incorrect, find a way to verify votes
#[cfg(feature = "pot")]
proof_of_time: PotCheckpoint::default(),
proof_of_time: PotProof::default(),
solution_range: vote_verification_data.solution_range,
piece_check_params: Some(PieceCheckParams {
max_pieces_in_sector: T::MaxPiecesInSector::get(),
Expand Down
2 changes: 1 addition & 1 deletion crates/pallet-subspace/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ pub fn make_pre_digest(
slot: Slot,
solution: Solution<FarmerPublicKey, <Test as frame_system::Config>::AccountId>,
) -> Digest {
let log = DigestItem::subspace_pre_digest(&PreDigest {
let log = DigestItem::subspace_pre_digest(&PreDigest::V0 {
slot,
solution,
#[cfg(feature = "pot")]
Expand Down
47 changes: 25 additions & 22 deletions crates/sc-consensus-subspace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,10 @@ where
if self
.client
.runtime_api()
.is_in_block_list(*block.header.parent_hash(), &pre_digest.solution.public_key)
.is_in_block_list(
*block.header.parent_hash(),
&pre_digest.solution().public_key,
)
.or_else(|error| {
if block.state_action.skip_execution_checks() {
Ok(false)
Expand All @@ -722,11 +725,11 @@ where
warn!(
target: "subspace",
"Verifying block with solution provided by farmer in block list: {}",
pre_digest.solution.public_key
pre_digest.solution().public_key
);

return Err(Error::<Block::Header>::FarmerInBlockList(
pre_digest.solution.public_key.clone(),
pre_digest.solution().public_key.clone(),
)
.into());
}
Expand All @@ -752,7 +755,7 @@ where
#[cfg(not(feature = "pot"))]
global_randomness: subspace_digest_items.global_randomness,
#[cfg(feature = "pot")]
proof_of_time: pre_digest.proof_of_time,
proof_of_time: pre_digest.proof_of_time(),
solution_range: subspace_digest_items.solution_range,
piece_check_params: None,
},
Expand All @@ -766,7 +769,7 @@ where

match checked_header {
CheckedHeader::Checked(pre_header, verified_info) => {
let slot = verified_info.pre_digest.slot;
let slot = verified_info.pre_digest.slot();

// the header is valid but let's check if there was something else already
// proposed at the same slot by the given author. if there was, we will
Expand All @@ -776,7 +779,7 @@ where
slot_now,
slot,
&block.header,
&verified_info.pre_digest.solution.public_key,
&verified_info.pre_digest.solution().public_key,
&block.origin,
)
.await
Expand Down Expand Up @@ -902,7 +905,7 @@ where

let pre_digest = &subspace_digest_items.pre_digest;
if let Some(root_plot_public_key) = root_plot_public_key {
if &pre_digest.solution.public_key != root_plot_public_key {
if &pre_digest.solution().public_key != root_plot_public_key {
// Only root plot public key is allowed.
return Err(Error::OnlyRootPlotPublicKeyAllowed);
}
Expand All @@ -913,7 +916,7 @@ where
if self
.client
.runtime_api()
.is_in_block_list(parent_hash, &pre_digest.solution.public_key)
.is_in_block_list(parent_hash, &pre_digest.solution().public_key)
.or_else(|error| {
if skip_runtime_access {
Ok(false)
Expand All @@ -925,11 +928,11 @@ where
warn!(
target: "subspace",
"Ignoring block with solution provided by farmer in block list: {}",
pre_digest.solution.public_key
pre_digest.solution().public_key
);

return Err(Error::FarmerInBlockList(
pre_digest.solution.public_key.clone(),
pre_digest.solution().public_key.clone(),
));
}

Expand Down Expand Up @@ -992,8 +995,8 @@ where
}

let sector_id = SectorId::new(
PublicKey::from(&pre_digest.solution.public_key).hash(),
pre_digest.solution.sector_index,
PublicKey::from(&pre_digest.solution().public_key).hash(),
pre_digest.solution().sector_index,
);

let chain_constants = get_chain_constants(self.client.as_ref())?;
Expand All @@ -1005,8 +1008,8 @@ where
.runtime_api()
.max_pieces_in_sector(parent_hash)?;
let piece_index = sector_id.derive_piece_index(
pre_digest.solution.piece_offset,
pre_digest.solution.history_size,
pre_digest.solution().piece_offset,
pre_digest.solution().history_size,
max_pieces_in_sector,
chain_constants.recent_segments(),
chain_constants.recent_history_fraction(),
Expand All @@ -1024,7 +1027,7 @@ where
.get_segment_header(
subspace_digest_items
.pre_digest
.solution
.solution()
.history_size
.sector_expiration_check(chain_constants.min_sector_lifetime())
.ok_or(Error::InvalidHistorySize)?
Expand All @@ -1035,14 +1038,14 @@ where
// Piece is not checked during initial block verification because it requires access to
// segment header and runtime, check it now.
subspace_verification::verify_solution::<PosTable, _, _>(
&pre_digest.solution,
pre_digest.solution(),
// Slot was already checked during initial block verification
pre_digest.slot.into(),
pre_digest.slot().into(),
&VerifySolutionParams {
#[cfg(not(feature = "pot"))]
global_randomness: subspace_digest_items.global_randomness,
#[cfg(feature = "pot")]
proof_of_time: subspace_digest_items.pre_digest.proof_of_time,
proof_of_time: subspace_digest_items.pre_digest.proof_of_time(),
solution_range: subspace_digest_items.solution_range,
piece_check_params: Some(PieceCheckParams {
max_pieces_in_sector,
Expand All @@ -1059,13 +1062,13 @@ where
},
&self.subspace_link.kzg,
)
.map_err(|error| VerificationError::VerificationError(pre_digest.slot, error))?;
.map_err(|error| VerificationError::VerificationError(pre_digest.slot(), error))?;

let parent_slot = extract_pre_digest(&parent_header).map(|d| d.slot)?;
let parent_slot = extract_pre_digest(&parent_header).map(|d| d.slot())?;

// Make sure that slot number is strictly increasing
if pre_digest.slot <= parent_slot {
return Err(Error::SlotMustIncrease(parent_slot, pre_digest.slot));
if pre_digest.slot() <= parent_slot {
return Err(Error::SlotMustIncrease(parent_slot, pre_digest.slot()));
}

if !skip_runtime_access {
Expand Down
11 changes: 6 additions & 5 deletions crates/sc-consensus-subspace/src/slot_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ where
return None;
}
};
let parent_slot = parent_pre_digest.slot;
let parent_slot = parent_pre_digest.slot();

if slot <= parent_slot {
debug!(
Expand Down Expand Up @@ -464,7 +464,7 @@ where
// block reward is claimed
if maybe_pre_digest.is_none() && solution_distance <= solution_range / 2 {
info!(target: "subspace", "🚜 Claimed block at slot {slot}");
maybe_pre_digest.replace(PreDigest {
maybe_pre_digest.replace(PreDigest::V0 {
slot,
solution,
#[cfg(feature = "pot")]
Expand Down Expand Up @@ -541,7 +541,7 @@ where
let signature = self
.sign_reward(
H256::from_slice(header_hash.as_ref()),
&pre_digest.solution.public_key,
&pre_digest.solution().public_key,
)
.await?;

Expand All @@ -568,7 +568,8 @@ where

fn should_backoff(&self, slot: Slot, chain_head: &Block::Header) -> bool {
if let Some(ref strategy) = self.backoff_authoring_blocks {
if let Ok(chain_head_slot) = extract_pre_digest(chain_head).map(|digest| digest.slot) {
if let Ok(chain_head_slot) = extract_pre_digest(chain_head).map(|digest| digest.slot())
{
return strategy.should_backoff(
*chain_head.number(),
chain_head_slot,
Expand Down Expand Up @@ -604,7 +605,7 @@ where
fn proposing_remaining_duration(&self, slot_info: &SlotInfo<Block>) -> std::time::Duration {
let parent_slot = extract_pre_digest(&slot_info.chain_head)
.ok()
.map(|d| d.slot);
.map(|d| d.slot());

sc_consensus_slots::proposing_remaining_duration(
parent_slot,
Expand Down
58 changes: 47 additions & 11 deletions crates/sp-consensus-subspace/src/digests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use sp_runtime::DigestItem;
use sp_std::collections::btree_map::{BTreeMap, Entry};
use sp_std::fmt;
#[cfg(feature = "pot")]
use subspace_core_primitives::PotCheckpoint;
use subspace_core_primitives::PotProof;
#[cfg(not(feature = "pot"))]
use subspace_core_primitives::Randomness;
use subspace_core_primitives::{SegmentCommitment, SegmentIndex, Solution, SolutionRange};
Expand All @@ -37,17 +37,53 @@ use subspace_verification::derive_randomness;
/// A Subspace pre-runtime digest. This contains all data required to validate a block and for the
/// Subspace runtime module.
#[derive(Debug, Clone, Encode, Decode)]
pub struct PreDigest<PublicKey, RewardAddress> {
pub enum PreDigest<PublicKey, RewardAddress> {
/// Initial version of the pre-digest
#[codec(index = 0)]
V0 {
/// Slot
slot: Slot,
/// Solution (includes PoR)
solution: Solution<PublicKey, RewardAddress>,
/// Proof of time for this slot
#[cfg(feature = "pot")]
proof_of_time: PotProof,
/// Future proof of time
#[cfg(feature = "pot")]
future_proof_of_time: PotProof,
},
}

impl<PublicKey, RewardAddress> PreDigest<PublicKey, RewardAddress> {
/// Slot
pub slot: Slot,
#[inline]
pub fn slot(&self) -> Slot {
let Self::V0 { slot, .. } = self;
*slot
}
/// Solution (includes PoR)
pub solution: Solution<PublicKey, RewardAddress>,
#[inline]
pub fn solution(&self) -> &Solution<PublicKey, RewardAddress> {
let Self::V0 { solution, .. } = self;
solution
}
/// Proof of time for this slot
#[cfg(feature = "pot")]
pub proof_of_time: PotCheckpoint,
#[inline]
pub fn proof_of_time(&self) -> PotProof {
let Self::V0 { proof_of_time, .. } = self;
*proof_of_time
}
/// Future proof of time
#[cfg(feature = "pot")]
pub future_proof_of_time: PotCheckpoint,
#[inline]
pub fn future_proof_of_time(&self) -> PotProof {
let Self::V0 {
future_proof_of_time,
..
} = self;
*future_proof_of_time
}
}

/// A digest item which is usable with Subspace consensus.
Expand Down Expand Up @@ -593,7 +629,7 @@ where
// genesis block doesn't contain a pre digest so let's generate a
// dummy one to not break any invariants in the rest of the code
if header.number().is_zero() {
return Ok(PreDigest {
return Ok(PreDigest::V0 {
slot: Slot::from(0),
solution: Solution::genesis_solution(
FarmerPublicKey::unchecked_from([0u8; 32]),
Expand Down Expand Up @@ -632,8 +668,8 @@ pub fn derive_next_global_randomness<Header: HeaderT>(
}

Some(derive_randomness(
&pre_digest.solution,
pre_digest.slot.into(),
pre_digest.solution(),
pre_digest.slot().into(),
))
}

Expand Down Expand Up @@ -779,7 +815,7 @@ pub fn verify_next_digests<Header: HeaderT>(
number,
era_duration,
slot_probability,
current_slot: header_digests.pre_digest.slot,
current_slot: header_digests.pre_digest.slot(),
current_solution_range: header_digests.solution_range,
era_start_slot,
should_adjust_solution_range: *should_adjust_solution_range,
Expand All @@ -801,7 +837,7 @@ pub fn verify_next_digests<Header: HeaderT>(
Some(updated_root_plot_public_key) => {
if number.is_one()
&& root_plot_public_key.is_none()
&& &header_digests.pre_digest.solution.public_key
&& &header_digests.pre_digest.solution().public_key
== updated_root_plot_public_key
{
root_plot_public_key.replace(updated_root_plot_public_key.clone());
Expand Down
Loading