Skip to content

Commit

Permalink
Merge branch 'main' into l1-random-walker
Browse files Browse the repository at this point in the history
  • Loading branch information
shamil-gadelshin authored Dec 21, 2023
2 parents 015674a + f76fb31 commit 9ff1733
Show file tree
Hide file tree
Showing 22 changed files with 669 additions and 1,157 deletions.
9 changes: 9 additions & 0 deletions crates/pallet-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,8 @@ impl<T: Config> Pallet<T> {
}

/// Returns the block number of oldest execution receipt.
// FIXME: the `oldest_receipt_number` may not be correct if fraud proof is submitted
// and bad ER were pruned, see https://github.com/subspace/subspace/issues/2354
pub fn oldest_receipt_number(domain_id: DomainId) -> DomainBlockNumberFor<T> {
Self::head_receipt_number(domain_id).saturating_sub(Self::block_tree_pruning_depth())
}
Expand Down Expand Up @@ -1929,6 +1931,13 @@ impl<T: Config> Pallet<T> {
pub fn execution_receipt(receipt_hash: ReceiptHashFor<T>) -> Option<ExecutionReceiptOf<T>> {
BlockTreeNodes::<T>::get(receipt_hash).map(|db| db.execution_receipt)
}

pub fn receipt_hash(
domain_id: DomainId,
domain_number: DomainBlockNumberFor<T>,
) -> Option<ReceiptHashFor<T>> {
BlockTree::<T>::get(domain_id, domain_number)
}
}

impl<T> Pallet<T>
Expand Down
1 change: 0 additions & 1 deletion crates/sc-consensus-subspace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
homepage = "https://subspace.network"
repository = "https://github.com/subspace/subspace"
documentation = "https://docs.rs/sc-consensus-subspace"
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
Expand Down
25 changes: 0 additions & 25 deletions crates/sc-consensus-subspace/README.md

This file was deleted.

67 changes: 62 additions & 5 deletions crates/sc-consensus-subspace/src/archiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,37 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Consensus archiver module.
//! Consensus archiver responsible for archival of blockchain history, it is driven by block import
//! pipeline.
//!
//! Contains implementation of archiving process in Subspace blockchain that converts blockchain
//! history (blocks) into archived history (pieces).
//! Implements archiving process in Subspace blockchain that converts blockchain history (blocks)
//! into archived history (pieces).
//!
//! The main entry point here is [`create_subspace_archiver`] that will create a task, which while
//! driven will perform the archiving itself.
//!
//! Archiving is triggered by block importing notification ([`SubspaceLink::block_importing_notification_stream`])
//! and tries to archive the block at [`ChainConstants::confirmation_depth_k`](sp_consensus_subspace::ChainConstants::confirmation_depth_k)
//! depth from the block being imported. Block import will then wait for archiver to acknowledge
//! processing, which is necessary for ensuring that when the next block is imported, inherents will
//! contain segment header of newly archived block (must happen exactly in the next block).
//!
//! Archiving itself will also wait for acknowledgement by various subscribers before proceeding,
//! which includes farmer subscription, in case of reference implementation via RPC
//! (`sc-consensus-subspace-rpc`), but could also be in other ways.
//!
//! [`SegmentHeadersStore`] is maintained as a data structure containing all known (including future
//! in case of syncing) segment headers. This data structure contents is then made available to
//! other parts of the protocol that need to know what correct archival history of the blockchain
//! looks like. For example, it is used during node sync and farmer plotting in order to verify
//! pieces of archival history received from other network participants.
//!
//! [`recreate_genesis_segment`] is a bit of a hack and is useful for deriving of the genesis
//! segment that is special case since we don't have enough data in the blockchain history itself
//! during genesis in order to do the archiving.
//!
//! [`encode_block`] and [`decode_block`] are symmetric encoding/decoding functions turning
//! [`SignedBlock`]s into bytes and back.
use crate::block_import::BlockImportingNotification;
use crate::slot_worker::SubspaceSyncOracle;
Expand Down Expand Up @@ -74,7 +101,16 @@ struct SegmentHeadersStoreInner<AS> {
cache: Mutex<Vec<SegmentHeader>>,
}

/// Persistent storage of segment headers
/// Persistent storage of segment headers.
///
/// It maintains all known segment headers. During sync from DSN it is possible that this data structure contains
/// segment headers that from the point of view of the tip of the current chain are "in the future". This is expected
/// and must be accounted for in the archiver and other places.
///
/// Segment headers are stored in batches (which is more efficient to store and retrieve). Each next batch contains
/// distinct segment headers with monotonically increasing segment indices. During instantiation all previously stored
/// batches will be read and in-memory representation of the whole contents will be created such that queries to this
/// data structure are quick and not involving any disk I/O.
#[derive(Debug)]
pub struct SegmentHeadersStore<AS> {
inner: Arc<SegmentHeadersStoreInner<AS>>,
Expand Down Expand Up @@ -335,7 +371,10 @@ where
best_archived_block: (Block::Hash, NumberFor<Block>),
}

/// Encode block for archiving purposes
/// Encode block for archiving purposes.
///
/// Only specific Subspace justifications are included in the encoding, determined by result of
/// [`SubspaceJustification::must_be_archived`], other justifications are filtered-out.
pub fn encode_block<Block>(mut signed_block: SignedBlock<Block>) -> Vec<u8>
where
Block: BlockT,
Expand Down Expand Up @@ -664,6 +703,24 @@ fn finalize_block<Block, Backend, Client>(
/// `store_segment_header` extrinsic).
///
/// NOTE: Archiver is doing blocking operations and must run in a dedicated task.
///
/// Archiver is only able to move forward and doesn't support reorgs. Upon restart it will check
/// [`SegmentHeadersStore`] and chain history to reconstruct "current" state it was in before last
/// shutdown and continue incrementally archiving blockchain history from there.
///
/// Archiving is triggered by block importing notification ([`SubspaceLink::block_importing_notification_stream`])
/// and tries to archive the block at [`ChainConstants::confirmation_depth_k`](sp_consensus_subspace::ChainConstants::confirmation_depth_k)
/// depth from the block being imported. Block import will then wait for archiver to acknowledge
/// processing, which is necessary for ensuring that when the next block is imported, inherents will
/// contain segment header of newly archived block (must happen exactly in the next block).
///
/// Once segment header is archived, notification ([`SubspaceLink::archived_segment_notification_stream`])
/// will be sent and archiver will be paused until all receivers have provided an acknowledgement
/// for it.
///
/// Archiving will be incremental during normal operation to decrease impact on block import and
/// non-incremental heavily parallel during sync process since parallel implementation is more
/// efficient overall and during sync only total sync time matters.
pub fn create_subspace_archiver<Block, Backend, Client, AS, SO>(
segment_headers_store: SegmentHeadersStore<AS>,
subspace_link: &SubspaceLink<Block>,
Expand Down
13 changes: 11 additions & 2 deletions crates/sc-consensus-subspace/src/block_import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Block import module.
//! Block import for Subspace, which includes stateful verification and corresponding notifications.
//!
//! Contains implementation of block import with corresponding checks and notifications.
//! In most cases block import happens after stateless block verification using [`verifier`](crate::verifier),
//! the only exception to that is locally authored blocks.
//!
//! Since [`verifier`](crate::verifier) is stateless, the remaining checks in block import are those
//! that require presence of the parent block or its state in the database. Specifically for Proof
//! of Time individual checkpoints are assumed to be checked already and only PoT inputs need to be
//! checked to correspond to the state of the parent block.
//!
//! After all checks and right before importing the block notification ([`SubspaceLink::block_importing_notification_stream`])
//! will be sent that [`archiver`](crate::archiver) among other things is subscribed to.
use crate::archiver::SegmentHeadersStore;
use crate::verifier::VerificationError;
Expand Down
11 changes: 9 additions & 2 deletions crates/sc-consensus-subspace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![doc = include_str!("../README.md")]
//! `sc-consensus-subspace` is the core of Subspace consensus implementation.
//!
//! You should familiarize yourself with [Subnomicon](https://subnomicon.subspace.network/) and, ideally, protocol
//! specifications. Documentation here assumes decent prior knowledge of the protocol on conceptual level and will not
//! explain how the protocol works, it will instead explain how the protocol is implemented.
//!
//! All of the modules here are crucial for consensus, open each module for specific details.
#![feature(const_option, let_chains, try_blocks)]
#![forbid(unsafe_code)]
#![warn(missing_docs)]
Expand All @@ -40,7 +47,7 @@ use std::sync::Arc;
use subspace_core_primitives::crypto::kzg::Kzg;
use subspace_core_primitives::SegmentHeader;

/// State that must be shared between the import queue and the authoring logic.
/// State that must be shared between various consensus components.
#[derive(Clone)]
pub struct SubspaceLink<Block: BlockT> {
new_slot_notification_sender: SubspaceNotificationSender<NewSlotNotification>,
Expand Down
17 changes: 15 additions & 2 deletions crates/sc-consensus-subspace/src/slot_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Slot worker module.
//! Slot worker drives block and vote production based on slots produced in [`sc_proof_of_time`].
//!
//! Contains implementation of Subspace slot worker that produces block and votes.
//! While slot worker uses [`sc_consensus_slots`], it is not driven by time, but instead by Proof of
//! Time that is produced by [`PotSourceWorker`](sc_proof_of_time::source::PotSourceWorker).
//!
//! Each time a new proof is found, [`PotSlotWorker::on_proof`] is called and corresponding
//! [`SlotInfo`] notification is sent ([`SubspaceLink::new_slot_notification_stream`]) to farmers to
//! do the audit and try to prove they have a solution without actually waiting for the response.
//! [`ChainConstants::block_authoring_delay`](sp_consensus_subspace::ChainConstants::block_authoring_delay)
//! slots later (when corresponding future proof arrives) all the solutions produced by farmers so
//! far are collected and corresponding block and/or votes are produced. In case PoT chain reorg
//! happens, outdated solutions (they are tied to proofs of time) are thrown away.
//!
//! Custom [`SubspaceSyncOracle`] wrapper is introduced due to Subspace-specific changes comparing
//! to the base Substrate behavior where major syncing is assumed to not happen in case authoring is
//! forced.
use crate::archiver::SegmentHeadersStore;
use crate::SubspaceLink;
Expand Down
15 changes: 14 additions & 1 deletion crates/sc-consensus-subspace/src/verifier.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
//! Subspace block import implementation
//! Stateless and parallelized block verification that happens before block is imported (except for locally produced
//! blocks that are imported directly).
//!
//! The goal of verifier is to check internal consistency of the block, which includes things like
//! solution according to claimed inputs, signature, Proof of Time checkpoints in justifications,
//! etc.
//!
//! This should be the majority of the block verification computation such that all that is left for
//! [`block_import`](crate::block_import) to check is that information in the block corresponds to
//! the state of the parent block, which for the most part is comparing bytes against known good
//! values.
//!
//! This is a significant tradeoff in the protocol: having a smaller header vs being able to verify
//! a lot of things stateless and in parallel.
use futures::lock::Mutex;
use rand::prelude::*;
Expand Down
3 changes: 3 additions & 0 deletions crates/sp-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,9 @@ sp_api::decl_runtime_apis! {

/// Get the consensus chain sudo account id, currently only used in the intentional malicious operator
fn sudo_account_id() -> subspace_runtime_primitives::AccountId;

/// Returns the execution receipt hash of the given domain and domain block number
fn receipt_hash(domain_id: DomainId, domain_number: HeaderNumberFor<DomainHeader>) -> Option<HeaderHashFor<DomainHeader>>;
}

pub trait BundleProducerElectionApi<Balance: Encode + Decode> {
Expand Down
23 changes: 18 additions & 5 deletions crates/subspace-farmer/src/bin/subspace-farmer/commands/farm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
mod dsn;

use crate::commands::farm::dsn::configure_dsn;
use crate::commands::shared::print_disk_farm_info;
use crate::utils::shutdown_signal;
use anyhow::anyhow;
use bytesize::ByteSize;
Expand Down Expand Up @@ -60,6 +59,10 @@ fn available_parallelism() -> usize {
}
}

fn should_farm_during_initial_plotting() -> bool {
available_parallelism() > 8
}

/// Arguments for farmer
#[derive(Debug, Parser)]
pub(crate) struct FarmingArgs {
Expand Down Expand Up @@ -126,7 +129,7 @@ pub(crate) struct FarmingArgs {
/// intense on CPU and memory that farming will likely not work properly, yet it will
/// significantly impact plotting speed, delaying the time when farming can actually work
/// properly.
#[arg(long)]
#[arg(long, default_value_t = should_farm_during_initial_plotting(), action = clap::ArgAction::Set)]
farm_during_initial_plotting: bool,
/// Size of PER FARM thread pool used for farming (mostly for blocking I/O, but also for some
/// compute-intensive operations during proving), defaults to number of CPU cores available in
Expand Down Expand Up @@ -171,8 +174,8 @@ struct DsnArgs {
/// Multiaddr to listen on for subspace networking, for instance `/ip4/0.0.0.0/tcp/0`,
/// multiple are supported.
#[arg(long, default_values_t = [
"/ip4/0.0.0.0/udp/30533/quic-v1".parse::<Multiaddr>().expect("Manual setting"),
"/ip4/0.0.0.0/tcp/30533".parse::<Multiaddr>().expect("Manual setting"),
"/ip4/0.0.0.0/udp/30533/quic-v1".parse::<Multiaddr>().expect("Statically correct; qed"),
"/ip4/0.0.0.0/tcp/30533".parse::<Multiaddr>().expect("Statically correct; qed"),
])]
listen_on: Vec<Multiaddr>,
/// Determines whether we allow keeping non-global (private, shared, loopback..) addresses in
Expand Down Expand Up @@ -490,7 +493,17 @@ where
};

if !no_info {
print_disk_farm_info(disk_farm.directory, disk_farm_index);
let info = single_disk_farm.info();
println!("Single disk farm {disk_farm_index}:");
println!(" ID: {}", info.id());
println!(" Genesis hash: 0x{}", hex::encode(info.genesis_hash()));
println!(" Public key: 0x{}", hex::encode(info.public_key()));
println!(
" Allocated space: {} ({})",
bytesize::to_string(info.allocated_space(), true),
bytesize::to_string(info.allocated_space(), false)
);
println!(" Directory: {}", disk_farm.directory.display());
}

single_disk_farms.push(single_disk_farm);
Expand Down
6 changes: 6 additions & 0 deletions crates/subspace-farmer/src/single_disk_farm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ impl SingleDiskFarmInfo {
}

/// Summary of single disk farm for presentational purposes
#[derive(Debug)]
pub enum SingleDiskFarmSummary {
/// Farm was found and read successfully
Found {
Expand Down Expand Up @@ -1302,6 +1303,11 @@ impl SingleDiskFarm {
self.single_disk_farm_info.id()
}

/// Info of this farm
pub fn info(&self) -> &SingleDiskFarmInfo {
&self.single_disk_farm_info
}

/// Number of sectors in this farm
pub fn total_sectors_count(&self) -> SectorIndex {
self.total_sectors_count
Expand Down
4 changes: 4 additions & 0 deletions crates/subspace-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,10 @@ impl_runtime_apis! {
fn sudo_account_id() -> AccountId {
SudoId::get()
}

fn receipt_hash(domain_id: DomainId, domain_number: DomainNumber) -> Option<DomainHash> {
Domains::receipt_hash(domain_id, domain_number)
}
}

impl sp_domains::BundleProducerElectionApi<Block, Balance> for Runtime {
Expand Down
1 change: 1 addition & 0 deletions domains/client/domain-operator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ sc-cli = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-s
sc-service = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "0831dfc3c54b10ab46e82acf98603b4af1a47bd5", default-features = false }
sc-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "0831dfc3c54b10ab46e82acf98603b4af1a47bd5" }
sp-state-machine = { version = "0.28.0", git = "https://github.com/subspace/polkadot-sdk", rev = "0831dfc3c54b10ab46e82acf98603b4af1a47bd5" }
subspace-core-primitives = { version = "0.1.0", default-features = false, path = "../../../crates/subspace-core-primitives" }
subspace-test-runtime = { version = "0.1.0", path = "../../../test/subspace-test-runtime" }
subspace-test-service = { version = "0.1.0", path = "../../../test/subspace-test-service" }
substrate-test-runtime-client = { version = "2.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "0831dfc3c54b10ab46e82acf98603b4af1a47bd5" }
Expand Down
Loading

0 comments on commit 9ff1733

Please sign in to comment.