Skip to content

Commit

Permalink
Make erasure coding an explicit argument of the archiver
Browse files Browse the repository at this point in the history
  • Loading branch information
nazar-pc committed Aug 22, 2024
1 parent dbc2855 commit 68e6954
Show file tree
Hide file tree
Showing 30 changed files with 238 additions and 143 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/pallet-subspace/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ pub fn create_archived_segment() -> &'static NewArchivedSegment {
static ARCHIVED_SEGMENT: OnceLock<NewArchivedSegment> = OnceLock::new();

ARCHIVED_SEGMENT.get_or_init(|| {
let mut archiver = Archiver::new(kzg_instance().clone()).unwrap();
let mut archiver = Archiver::new(kzg_instance().clone(), erasure_coding_instance().clone());

let mut block = vec![0u8; RecordedHistorySegment::SIZE];
rand::thread_rng().fill(block.as_mut_slice());
Expand Down
1 change: 1 addition & 0 deletions crates/sc-consensus-subspace-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ sp-objects = { version = "0.1.0", path = "../sp-objects" }
sp-runtime = { git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631" }
subspace-archiving = { version = "0.1.0", path = "../subspace-archiving" }
subspace-core-primitives = { version = "0.1.0", path = "../subspace-core-primitives" }
subspace-erasure-coding = { version = "0.1.0", path = "../subspace-erasure-coding" }
subspace-farmer-components = { version = "0.1.0", path = "../subspace-farmer-components" }
subspace-networking = { version = "0.1.0", path = "../subspace-networking" }
subspace-rpc-primitives = { version = "0.1.0", path = "../subspace-rpc-primitives" }
Expand Down
11 changes: 10 additions & 1 deletion crates/sc-consensus-subspace-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ use subspace_core_primitives::{
BlockHash, HistorySize, Piece, PieceIndex, PublicKey, SegmentHeader, SegmentIndex, SlotNumber,
Solution,
};
use subspace_erasure_coding::ErasureCoding;
use subspace_farmer_components::FarmerProtocolInfo;
use subspace_networking::libp2p::Multiaddr;
use subspace_rpc_primitives::{
Expand Down Expand Up @@ -215,6 +216,8 @@ where
pub deny_unsafe: DenyUnsafe,
/// Kzg instance
pub kzg: Kzg,
/// Erasure coding instance
pub erasure_coding: ErasureCoding,
}

/// Implements the [`SubspaceRpcApiServer`] trait for interacting with Subspace.
Expand Down Expand Up @@ -243,6 +246,7 @@ where
chain_constants: ChainConstants,
max_pieces_in_sector: u16,
kzg: Kzg,
erasure_coding: ErasureCoding,
deny_unsafe: DenyUnsafe,
_block: PhantomData<Block>,
}
Expand Down Expand Up @@ -300,6 +304,7 @@ where
chain_constants,
max_pieces_in_sector,
kzg: config.kzg,
erasure_coding: config.erasure_coding,
deny_unsafe: config.deny_unsafe,
_block: PhantomData,
})
Expand Down Expand Up @@ -717,7 +722,11 @@ where
debug!(%requested_piece_index, "Re-creating genesis segment on demand");

// Try to re-create genesis segment on demand
match recreate_genesis_segment(&*self.client, self.kzg.clone()) {
match recreate_genesis_segment(
&*self.client,
self.kzg.clone(),
self.erasure_coding.clone(),
) {
Ok(Some(archived_segment)) => {
let archived_segment = Arc::new(archived_segment);
cached_archived_segment.replace(CachedArchivedSegment::Genesis(
Expand Down
1 change: 1 addition & 0 deletions crates/sc-consensus-subspace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ sp-objects = { version = "0.1.0", path = "../sp-objects" }
sp-runtime = { git = "https://github.com/subspace/polkadot-sdk", rev = "5626154d0781ac9a6ffd5a6207ed237f425ae631" }
subspace-archiving = { version = "0.1.0", path = "../subspace-archiving" }
subspace-core-primitives = { version = "0.1.0", path = "../subspace-core-primitives" }
subspace-erasure-coding = { version = "0.1.0", path = "../subspace-erasure-coding" }
subspace-proof-of-space = { version = "0.1.0", path = "../subspace-proof-of-space" }
subspace-verification = { version = "0.1.0", path = "../subspace-verification" }
thiserror = "1.0.63"
Expand Down
10 changes: 8 additions & 2 deletions crates/sc-consensus-subspace/src/archiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ use subspace_archiving::archiver::{Archiver, NewArchivedSegment};
use subspace_core_primitives::crypto::kzg::Kzg;
use subspace_core_primitives::objects::BlockObjectMapping;
use subspace_core_primitives::{BlockNumber, RecordedHistorySegment, SegmentHeader, SegmentIndex};
use subspace_erasure_coding::ErasureCoding;
use tracing::{debug, info, trace, warn};

/// Number of WASM instances is 8, this is a bit lower to avoid warnings exceeding number of
Expand Down Expand Up @@ -412,6 +413,7 @@ where
pub fn recreate_genesis_segment<Block, Client>(
client: &Client,
kzg: Kzg,
erasure_coding: ErasureCoding,
) -> Result<Option<NewArchivedSegment>, Box<dyn Error>>
where
Block: BlockT,
Expand All @@ -437,7 +439,7 @@ where

let encoded_block = encode_block(signed_block);

let new_archived_segment = Archiver::new(kzg)?
let new_archived_segment = Archiver::new(kzg, erasure_coding)
.add_block(encoded_block, block_object_mappings, false)
.into_iter()
.next()
Expand Down Expand Up @@ -581,6 +583,7 @@ where

let archiver = Archiver::with_initial_state(
subspace_link.kzg().clone(),
subspace_link.erasure_coding().clone(),
last_segment_header,
&last_archived_block_encoded,
block_object_mappings,
Expand All @@ -591,7 +594,10 @@ where
} else {
info!("Starting archiving from genesis");

Archiver::new(subspace_link.kzg().clone()).expect("Incorrect parameters for archiver")
Archiver::new(
subspace_link.kzg().clone(),
subspace_link.erasure_coding().clone(),
)
};

// Process blocks since last fully archived block up to the current head minus K
Expand Down
10 changes: 9 additions & 1 deletion crates/sc-consensus-subspace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use crate::slot_worker::{NewSlotNotification, RewardSigningNotification};
use sp_consensus_subspace::ChainConstants;
use sp_runtime::traits::Block as BlockT;
use subspace_core_primitives::crypto::kzg::Kzg;
use subspace_erasure_coding::ErasureCoding;

/// State that must be shared between various consensus components.
#[derive(Clone)]
Expand All @@ -59,11 +60,12 @@ pub struct SubspaceLink<Block: BlockT> {
SubspaceNotificationStream<BlockImportingNotification<Block>>,
chain_constants: ChainConstants,
kzg: Kzg,
erasure_coding: ErasureCoding,
}

impl<Block: BlockT> SubspaceLink<Block> {
/// Create new instance.
pub fn new(chain_constants: ChainConstants, kzg: Kzg) -> Self {
pub fn new(chain_constants: ChainConstants, kzg: Kzg, erasure_coding: ErasureCoding) -> Self {
let (new_slot_notification_sender, new_slot_notification_stream) =
notification::channel("subspace_new_slot_notification_stream");
let (reward_signing_notification_sender, reward_signing_notification_stream) =
Expand All @@ -84,6 +86,7 @@ impl<Block: BlockT> SubspaceLink<Block> {
block_importing_notification_stream,
chain_constants,
kzg,
erasure_coding,
}
}

Expand Down Expand Up @@ -127,4 +130,9 @@ impl<Block: BlockT> SubspaceLink<Block> {
pub fn kzg(&self) -> &Kzg {
&self.kzg
}

/// Access erasure coding instance
pub fn erasure_coding(&self) -> &ErasureCoding {
&self.erasure_coding
}
}
10 changes: 9 additions & 1 deletion crates/subspace-archiving/benches/archiving.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rand::{thread_rng, Rng};
use std::num::NonZeroUsize;
use subspace_archiving::archiver::Archiver;
use subspace_core_primitives::crypto::kzg;
use subspace_core_primitives::crypto::kzg::Kzg;
use subspace_core_primitives::Record;
use subspace_erasure_coding::ErasureCoding;

const AMOUNT_OF_DATA: usize = 5 * 1024 * 1024;
const SMALL_BLOCK_SIZE: usize = 500;
Expand All @@ -11,7 +14,12 @@ fn criterion_benchmark(c: &mut Criterion) {
let mut input = vec![0u8; AMOUNT_OF_DATA];
thread_rng().fill(input.as_mut_slice());
let kzg = Kzg::new(kzg::embedded_kzg_settings());
let archiver = Archiver::new(kzg).unwrap();
let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(Record::NUM_S_BUCKETS.next_power_of_two().ilog2() as usize)
.expect("Not zero; qed"),
)
.unwrap();
let archiver = Archiver::new(kzg, erasure_coding);

c.bench_function("segment-archiving-large-block", |b| {
b.iter(|| {
Expand Down
31 changes: 6 additions & 25 deletions crates/subspace-archiving/src/archiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use alloc::vec;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::num::NonZeroUsize;
use parity_scale_codec::{Compact, CompactLen, Decode, Encode, Input, Output};
#[cfg(feature = "parallel")]
use rayon::prelude::*;
Expand Down Expand Up @@ -189,12 +188,6 @@ pub struct NewArchivedSegment {
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
pub enum ArchiverInstantiationError {
/// Failed to initialize erasure coding
#[cfg_attr(
feature = "thiserror",
error("Failed to initialize erasure coding: {0}")
)]
FailedToInitializeErasureCoding(String),
/// Invalid last archived block, its size is the same as encoded block
#[cfg_attr(
feature = "thiserror",
Expand Down Expand Up @@ -245,22 +238,9 @@ pub struct Archiver {
}

impl Archiver {
// TODO: Make erasure coding an explicit argument
/// Create a new instance with specified record size and recorded history segment size.
///
/// Note: this is the only way to instantiate object archiver, while block archiver can be
/// instantiated with `BlockArchiver::with_initial_state()` in case of restarts.
pub fn new(kzg: Kzg) -> Result<Self, ArchiverInstantiationError> {
// TODO: Check if KZG can process number configured number of elements and update proof
// message in `.expect()`

let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(ArchivedHistorySegment::NUM_PIECES.ilog2() as usize)
.expect("Archived history segment contains at very least one piece; qed"),
)
.map_err(ArchiverInstantiationError::FailedToInitializeErasureCoding)?;

Ok(Self {
/// Create a new instance
pub fn new(kzg: Kzg, erasure_coding: ErasureCoding) -> Self {
Self {
buffer: VecDeque::default(),
incremental_record_commitments: IncrementalRecordCommitmentsState::with_capacity(
RecordedHistorySegment::NUM_RAW_RECORDS,
Expand All @@ -270,19 +250,20 @@ impl Archiver {
segment_index: SegmentIndex::ZERO,
prev_segment_header_hash: Blake3Hash::default(),
last_archived_block: INITIAL_LAST_ARCHIVED_BLOCK,
})
}
}

/// Create a new instance of the archiver with initial state in case of restart.
///
/// `block` corresponds to `last_archived_block` and will be processed accordingly to its state.
pub fn with_initial_state(
kzg: Kzg,
erasure_coding: ErasureCoding,
segment_header: SegmentHeader,
encoded_block: &[u8],
mut object_mapping: BlockObjectMapping,
) -> Result<Self, ArchiverInstantiationError> {
let mut archiver = Self::new(kzg)?;
let mut archiver = Self::new(kzg, erasure_coding);

archiver.segment_index = segment_header.segment_index() + SegmentIndex::ONE;
archiver.prev_segment_header_hash = segment_header.hash();
Expand Down
30 changes: 4 additions & 26 deletions crates/subspace-archiving/src/piece_reconstructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,13 @@ extern crate alloc;
use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::num::NonZeroUsize;
#[cfg(feature = "parallel")]
use rayon::prelude::*;
use subspace_core_primitives::crypto::kzg::{Commitment, Kzg, Polynomial};
use subspace_core_primitives::crypto::{blake3_254_hash_to_scalar, Scalar};
use subspace_core_primitives::{ArchivedHistorySegment, Piece, RawRecord};
use subspace_erasure_coding::ErasureCoding;

/// Reconstructor-related instantiation error.
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
pub enum ReconstructorInstantiationError {
/// Failed to initialize erasure coding
#[cfg_attr(
feature = "thiserror",
error("Failed to initialize erasure coding: {0}")
)]
FailedToInitializeErasureCoding(String),
}

/// Reconstructor-related instantiation error
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
Expand Down Expand Up @@ -55,21 +42,12 @@ pub struct PiecesReconstructor {
}

impl PiecesReconstructor {
// TODO: Make erasure coding an explicit argument
pub fn new(kzg: Kzg) -> Result<Self, ReconstructorInstantiationError> {
// TODO: Check if KZG can process number configured number of elements and update proof
// message in `.expect()`

let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(ArchivedHistorySegment::NUM_PIECES.ilog2() as usize)
.expect("Archived history segment contains at very least one piece; qed"),
)
.map_err(ReconstructorInstantiationError::FailedToInitializeErasureCoding)?;

Ok(Self {
/// Create a new instance
pub fn new(kzg: Kzg, erasure_coding: ErasureCoding) -> Self {
Self {
erasure_coding,
kzg,
})
}
}

/// Returns incomplete pieces (witness missing) and polynomial that can be used to generate
Expand Down
30 changes: 4 additions & 26 deletions crates/subspace-archiving/src/reconstructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::mem;
use core::num::NonZeroUsize;
use parity_scale_codec::Decode;
use subspace_core_primitives::crypto::Scalar;
use subspace_core_primitives::{
Expand All @@ -16,18 +15,6 @@ use subspace_core_primitives::{
};
use subspace_erasure_coding::ErasureCoding;

/// Reconstructor-related instantiation error.
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
pub enum ReconstructorInstantiationError {
/// Failed to initialize erasure coding
#[cfg_attr(
feature = "thiserror",
error("Failed to initialize erasure coding: {0}")
)]
FailedToInitializeErasureCoding(String),
}

/// Reconstructor-related instantiation error
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
Expand Down Expand Up @@ -74,22 +61,13 @@ pub struct Reconstructor {
}

impl Reconstructor {
// TODO: Make erasure coding an explicit argument
pub fn new() -> Result<Self, ReconstructorInstantiationError> {
// TODO: Check if KZG can process number configured number of elements and update proof
// message in `.expect()`

let erasure_coding = ErasureCoding::new(
NonZeroUsize::new(ArchivedHistorySegment::NUM_PIECES.ilog2() as usize)
.expect("Archived history segment contains at very least one piece; qed"),
)
.map_err(ReconstructorInstantiationError::FailedToInitializeErasureCoding)?;

Ok(Self {
/// Create a new instance
pub fn new(erasure_coding: ErasureCoding) -> Self {
Self {
erasure_coding,
last_segment_index: None,
partial_block: None,
})
}
}

/// Given a set of pieces of a segment of the archived history (any half of all pieces are
Expand Down
Loading

0 comments on commit 68e6954

Please sign in to comment.