diff --git a/pallets/storage-provider/Cargo.toml b/pallets/storage-provider/Cargo.toml index 558fa82c4..ec4b5ede1 100644 --- a/pallets/storage-provider/Cargo.toml +++ b/pallets/storage-provider/Cargo.toml @@ -38,6 +38,7 @@ env_logger = { workspace = true } multihash-codetable = { workspace = true, features = ["blake2b"] } pallet-balances = { workspace = true, default-features = false } pallet-market = { workspace = true, default-features = false } +primitives = { workspace = true, default-features = false, features = ["builder"] } rstest = { workspace = true } sp-io = { workspace = true } diff --git a/pallets/storage-provider/src/lib.rs b/pallets/storage-provider/src/lib.rs index de1b7724f..979356c5e 100644 --- a/pallets/storage-provider/src/lib.rs +++ b/pallets/storage-provider/src/lib.rs @@ -63,7 +63,7 @@ pub mod pallet { }, proofs::{derive_prover_id, PublicReplicaInfo, RegisteredPoStProof}, randomness::{draw_randomness, AuthorVrfHistory, DomainSeparationTag}, - sector::SectorNumber, + sector::{SectorNumber, SectorPreCommitInfo}, PartitionNumber, MAX_PARTITIONS_PER_DEADLINE, MAX_SEAL_PROOF_BYTES, MAX_SECTORS, MAX_SECTORS_PER_CALL, }; @@ -78,8 +78,8 @@ pub mod pallet { }, proofs::{assign_proving_period_offset, SubmitWindowedPoStParams}, sector::{ - ProveCommitResult, ProveCommitSector, SectorOnChainInfo, SectorPreCommitInfo, - SectorPreCommitOnChainInfo, TerminateSectorsParams, TerminationDeclaration, + ProveCommitResult, ProveCommitSector, SectorOnChainInfo, SectorPreCommitOnChainInfo, + TerminateSectorsParams, TerminationDeclaration, }, sector_map::DeadlineSectorMap, storage_provider::{ diff --git a/pallets/storage-provider/src/sector.rs b/pallets/storage-provider/src/sector.rs index 01915a77c..fb492bc31 100644 --- a/pallets/storage-provider/src/sector.rs +++ b/pallets/storage-provider/src/sector.rs @@ -1,36 +1,15 @@ use codec::{Decode, Encode}; use frame_support::{pallet_prelude::*, BoundedVec}; use primitives::{ - pallets::SectorDeal, proofs::RegisteredSealProof, sector::SectorNumber, DealId, - PartitionNumber, CID_SIZE_IN_BYTES, MAX_DEALS_PER_SECTOR, MAX_SEAL_PROOF_BYTES, - MAX_TERMINATIONS_PER_CALL, + pallets::SectorDeal, + proofs::RegisteredSealProof, + sector::{SectorNumber, SectorPreCommitInfo}, + PartitionNumber, CID_SIZE_IN_BYTES, MAX_SEAL_PROOF_BYTES, MAX_TERMINATIONS_PER_CALL, }; use scale_info::TypeInfo; use crate::pallet::DECLARATIONS_MAX; -/// This type is passed into the pre commit function on the storage provider pallet -#[derive(Clone, RuntimeDebug, Decode, Encode, PartialEq, Eq, TypeInfo)] -pub struct SectorPreCommitInfo { - pub seal_proof: RegisteredSealProof, - /// Which sector number this SP is pre-committing. - pub sector_number: SectorNumber, - /// This value is also known as `commR` or "commitment of replication". The terms `commR` and `sealed_cid` are interchangeable. - /// Using sealed_cid as I think that is more descriptive. - /// Some docs on commR here: - pub sealed_cid: BoundedVec>, - /// The block number at which we requested the randomness when sealing the sector. - pub seal_randomness_height: BlockNumber, - /// Deals Ids that are supposed to be activated. - /// If any of those is invalid, whole activation is rejected. - pub deal_ids: BoundedVec>, - /// Expiration of the pre-committed sector. - pub expiration: BlockNumber, - /// This value is also known as `commD` or "commitment of data". - /// Once a sector is full `commD` is produced representing the root node of all of the piece CIDs contained in the sector. - pub unsealed_cid: BoundedVec>, -} - /// Information stored on-chain for a pre-committed sector. #[derive(Clone, RuntimeDebug, Decode, Encode, TypeInfo)] pub struct SectorPreCommitOnChainInfo { diff --git a/pallets/storage-provider/src/tests/mod.rs b/pallets/storage-provider/src/tests/mod.rs index f75baea8c..e4a711161 100644 --- a/pallets/storage-provider/src/tests/mod.rs +++ b/pallets/storage-provider/src/tests/mod.rs @@ -1,8 +1,6 @@ extern crate alloc; use alloc::collections::BTreeSet; -use core::str::FromStr; -use cid::Cid; use codec::Encode; use frame_support::{ assert_ok, derive_impl, @@ -19,9 +17,8 @@ use primitives::{ pallets::ProofVerification, proofs::{ProverId, PublicReplicaInfo, RegisteredPoStProof, RegisteredSealProof, Ticket}, sector::SectorNumber, - DealId, PartitionNumber, CID_SIZE_IN_BYTES, MAX_DEALS_PER_SECTOR, MAX_PARTITIONS_PER_DEADLINE, - MAX_POST_PROOF_BYTES, MAX_PROOFS_PER_BLOCK, MAX_REPLICAS_PER_BLOCK, MAX_SEAL_PROOF_BYTES, - MAX_TERMINATIONS_PER_CALL, PEER_ID_MAX_BYTES, + PartitionNumber, MAX_PARTITIONS_PER_DEADLINE, MAX_POST_PROOF_BYTES, MAX_PROOFS_PER_BLOCK, + MAX_REPLICAS_PER_BLOCK, MAX_SEAL_PROOF_BYTES, MAX_TERMINATIONS_PER_CALL, PEER_ID_MAX_BYTES, }; use sp_arithmetic::traits::Zero; use sp_core::{bounded_vec, Pair}; @@ -37,7 +34,6 @@ use crate::{ }, pallet::DECLARATIONS_MAX, proofs::{PoStProof, SubmitWindowedPoStParams}, - sector::SectorPreCommitInfo, }; mod deadline; @@ -53,6 +49,8 @@ mod storage_provider_registration; mod submit_windowed_post; mod terminate_sectors; +pub type SectorPreCommitInfoBuilder = primitives::sector::builder::SectorPreCommitInfoBuilder; + type Block = frame_system::mocking::MockBlock; type BlockNumber = u64; @@ -374,79 +372,6 @@ fn publish_deals(storage_provider: &str) { System::reset_events(); } -struct SectorPreCommitInfoBuilder { - seal_proof: RegisteredSealProof, - sector_number: SectorNumber, - sealed_cid: BoundedVec>, - deal_ids: BoundedVec>, - expiration: u64, - unsealed_cid: BoundedVec>, - seal_randomness_height: u64, -} - -impl Default for SectorPreCommitInfoBuilder { - fn default() -> Self { - let unsealed_cid = - Cid::from_str("baga6ea4seaqmruupwrxaeck7m3f5jtswpr7jv6bvwqeu5jinzjlcybh6er3ficq") - .unwrap() - .to_bytes() - .try_into() - .expect("hash is always 32 bytes"); - - let sealed_cid = - Cid::from_str("bagboea4b5abcamxmh7exq7vrvacvajooeapagr3a4g3tpjhw73iny47hvafw76gr") - .unwrap() - .to_bytes() - .try_into() - .expect("hash is always 32 bytes"); - - Self { - seal_proof: RegisteredSealProof::StackedDRG2KiBV1P1, - sector_number: SectorNumber::new(1).unwrap(), - sealed_cid, - deal_ids: bounded_vec![0, 1], - expiration: 120 * MINUTES, - unsealed_cid, - seal_randomness_height: 1, - } - } -} - -impl SectorPreCommitInfoBuilder { - pub fn sector_number(mut self, sector_number: SectorNumber) -> Self { - self.sector_number = sector_number; - self - } - - pub fn deals(mut self, deal_ids: Vec) -> Self { - self.deal_ids = BoundedVec::try_from(deal_ids).unwrap(); - self - } - - pub fn expiration(mut self, expiration: u64) -> Self { - self.expiration = expiration; - self - } - - pub fn unsealed_cid(mut self, unsealed_cid: &str) -> Self { - let cid = Cid::from_str(unsealed_cid).expect("valid unsealed_cid"); - self.unsealed_cid = BoundedVec::try_from(cid.to_bytes()).unwrap(); - self - } - - pub fn build(self) -> SectorPreCommitInfo { - SectorPreCommitInfo { - seal_proof: self.seal_proof, - sector_number: self.sector_number, - sealed_cid: self.sealed_cid, - deal_ids: self.deal_ids, - expiration: self.expiration, - unsealed_cid: self.unsealed_cid, - seal_randomness_height: self.seal_randomness_height, - } - } -} - /// Builder to simplify writing complex tests of [`DealProposal`]. /// Exclusively uses [`Test`] for simplification purposes. struct DealProposalBuilder { diff --git a/pallets/storage-provider/src/tests/pre_commit_sectors.rs b/pallets/storage-provider/src/tests/pre_commit_sectors.rs index 94860a625..e92021de9 100644 --- a/pallets/storage-provider/src/tests/pre_commit_sectors.rs +++ b/pallets/storage-provider/src/tests/pre_commit_sectors.rs @@ -1,13 +1,12 @@ use frame_support::{assert_noop, assert_ok, pallet_prelude::*}; use frame_system::pallet_prelude::BlockNumberFor; -use primitives::MAX_SECTORS_PER_CALL; +use primitives::{sector::SectorPreCommitInfo, MAX_SECTORS_PER_CALL}; use sp_core::bounded_vec; use sp_runtime::{BoundedVec, DispatchError}; use super::new_test_ext; use crate::{ pallet::{Error, Event, StorageProviders}, - sector::SectorPreCommitInfo, tests::{ account, events, publish_deals, register_storage_provider, run_to_block, Balances, MaxProveCommitDuration, MaxSectorExpiration, RuntimeEvent, RuntimeOrigin, diff --git a/pallets/storage-provider/src/tests/prove_commit_sectors.rs b/pallets/storage-provider/src/tests/prove_commit_sectors.rs index 234bee3f9..409d6d64f 100644 --- a/pallets/storage-provider/src/tests/prove_commit_sectors.rs +++ b/pallets/storage-provider/src/tests/prove_commit_sectors.rs @@ -1,6 +1,6 @@ use frame_support::{assert_noop, assert_ok, pallet_prelude::*}; use frame_system::pallet_prelude::BlockNumberFor; -use primitives::MAX_SECTORS_PER_CALL; +use primitives::{sector::SectorPreCommitInfo, MAX_SECTORS_PER_CALL}; use sp_core::bounded_vec; use super::{new_test_ext, MaxProveCommitDuration}; @@ -8,7 +8,7 @@ use crate::{ deadline::deadline_is_mutable, error::GeneralPalletError, pallet::{Error, Event, StorageProviders}, - sector::{ProveCommitResult, ProveCommitSector, SectorPreCommitInfo}, + sector::{ProveCommitResult, ProveCommitSector}, tests::{ account, events, publish_deals, register_storage_provider, run_to_block, Balances, RuntimeEvent, RuntimeOrigin, SectorPreCommitInfoBuilder, StorageProvider, System, Test, diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 7b0391f0c..19f77ad6f 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -32,6 +32,7 @@ serde_json = { workspace = true, default-features = true } workspace = true [features] +builder = [] clap = ["dep:clap", "std"] default = ["std"] serde = ["dep:serde"] diff --git a/primitives/src/sector/mod.rs b/primitives/src/sector/mod.rs new file mode 100644 index 000000000..693970662 --- /dev/null +++ b/primitives/src/sector/mod.rs @@ -0,0 +1,14 @@ +mod number; +mod pre_commit; +mod size; + +// NOTE(@jmg-duarte,16/01/2025): unsure if the visitor should be exposed +pub use number::{SectorNumber, SectorNumberError}; +pub use pre_commit::SectorPreCommitInfo; +pub use size::SectorSize; + +// `test` is only useful locally +#[cfg(any(test, feature = "builder"))] +pub mod builder { + pub use crate::sector::pre_commit::builder::SectorPreCommitInfoBuilder; +} diff --git a/primitives/src/sector.rs b/primitives/src/sector/number.rs similarity index 73% rename from primitives/src/sector.rs rename to primitives/src/sector/number.rs index 66d4bd7bc..52f67fe42 100644 --- a/primitives/src/sector.rs +++ b/primitives/src/sector/number.rs @@ -1,9 +1,11 @@ -use core::{fmt::Display, marker::PhantomData}; +//! Sector number primitive. + +use core::marker::PhantomData; use codec::{Decode, Encode, MaxEncodedLen}; use scale_decode::{ visitor::{self}, - DecodeAsType, ToString, TypeResolver, Visitor, + ToString, TypeResolver, Visitor, }; use scale_encode::EncodeAsType; use scale_info::TypeInfo; @@ -164,53 +166,8 @@ impl From for u64 { } } -impl Display for SectorNumber { +impl core::fmt::Display for SectorNumber { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", self.0) } } - -/// SectorSize indicates one of a set of possible sizes in the network. -#[derive( - Encode, Decode, DecodeAsType, EncodeAsType, TypeInfo, Clone, RuntimeDebug, PartialEq, Eq, Copy, -)] -#[cfg_attr(feature = "serde", derive(::serde::Deserialize, ::serde::Serialize))] -#[codec(crate = ::codec)] -#[decode_as_type(crate_path = "::scale_decode")] -#[encode_as_type(crate_path = "::scale_encode")] -pub enum SectorSize { - _2KiB, - _8MiB, - _512MiB, - _32GiB, - _64GiB, -} - -impl SectorSize { - /// Returns the size of a sector in bytes - /// - pub fn bytes(&self) -> u64 { - match self { - SectorSize::_2KiB => 2 << 10, - SectorSize::_8MiB => 8 << 20, - SectorSize::_512MiB => 512 << 20, - SectorSize::_32GiB => 32 << 30, - SectorSize::_64GiB => 2 * (32 << 30), - } - } -} - -impl core::fmt::Display for SectorSize { - fn fmt( - &self, - f: &mut scale_info::prelude::fmt::Formatter<'_>, - ) -> scale_info::prelude::fmt::Result { - match self { - SectorSize::_2KiB => write!(f, "2KiB"), - SectorSize::_8MiB => write!(f, "8MiB"), - SectorSize::_512MiB => write!(f, "512MiB"), - SectorSize::_32GiB => write!(f, "32GiB"), - SectorSize::_64GiB => write!(f, "64GiB"), - } - } -} diff --git a/primitives/src/sector/pre_commit.rs b/primitives/src/sector/pre_commit.rs new file mode 100644 index 000000000..44918e7e1 --- /dev/null +++ b/primitives/src/sector/pre_commit.rs @@ -0,0 +1,139 @@ +//! Pre-commit primitive. + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_core::ConstU32; +use sp_runtime::{BoundedVec, RuntimeDebug}; + +use crate::{ + proofs::RegisteredSealProof, sector::SectorNumber, DealId, CID_SIZE_IN_BYTES, + MAX_DEALS_PER_SECTOR, +}; + +/// This type is passed into the pre commit function on the storage provider pallet +#[derive(Clone, RuntimeDebug, Decode, Encode, PartialEq, Eq, TypeInfo)] +pub struct SectorPreCommitInfo { + pub seal_proof: RegisteredSealProof, + /// Which sector number this SP is pre-committing. + pub sector_number: SectorNumber, + /// This value is also known as `commR` or "commitment of replication". The terms `commR` and `sealed_cid` are interchangeable. + /// Using sealed_cid as I think that is more descriptive. + /// Some docs on commR here: + pub sealed_cid: BoundedVec>, + /// The block number at which we requested the randomness when sealing the sector. + pub seal_randomness_height: BlockNumber, + /// Deals Ids that are supposed to be activated. + /// If any of those is invalid, whole activation is rejected. + pub deal_ids: BoundedVec>, + /// Expiration of the pre-committed sector. + pub expiration: BlockNumber, + /// This value is also known as `commD` or "commitment of data". + /// Once a sector is full `commD` is produced representing the root node of all of the piece CIDs contained in the sector. + pub unsealed_cid: BoundedVec>, +} + +#[cfg(any(test, feature = "builder"))] +pub mod builder { + + use core::str::FromStr; + + use cid::Cid; + use sp_core::ConstU32; + use sp_runtime::BoundedVec; + + use super::SectorPreCommitInfo; + use crate::{ + proofs::RegisteredSealProof, sector::SectorNumber, DealId, CID_SIZE_IN_BYTES, + MAX_DEALS_PER_SECTOR, + }; + + /// [`SectorPreCommitInfo`] builder. + /// + /// Usage: + /// ```no_run + /// // Instances are created with defaults + /// SectorPreCommitInfoBuilder::default() + /// .sector_number(10.into()) + /// .deals(vec![1000]); + /// ``` + pub struct SectorPreCommitInfoBuilder { + seal_proof: RegisteredSealProof, + sector_number: SectorNumber, + sealed_cid: BoundedVec>, + deal_ids: BoundedVec>, + expiration: BlockNumber, + unsealed_cid: BoundedVec>, + seal_randomness_height: BlockNumber, + } + + impl Default for SectorPreCommitInfoBuilder + where + BlockNumber: sp_runtime::traits::BlockNumber, + { + fn default() -> Self { + let unsealed_cid = + Cid::from_str("baga6ea4seaqmruupwrxaeck7m3f5jtswpr7jv6bvwqeu5jinzjlcybh6er3ficq") + .unwrap() + .to_bytes() + .try_into() + .expect("hash is always 32 bytes"); + + let sealed_cid = + Cid::from_str("bagboea4b5abcamxmh7exq7vrvacvajooeapagr3a4g3tpjhw73iny47hvafw76gr") + .unwrap() + .to_bytes() + .try_into() + .expect("hash is always 32 bytes"); + + Self { + seal_proof: RegisteredSealProof::StackedDRG2KiBV1P1, + sector_number: SectorNumber::new(1).unwrap(), + sealed_cid, + deal_ids: BoundedVec::try_from(vec![0, 1]) + .expect("default valid should always be within bounds"), + expiration: 120u32.into(), + unsealed_cid, + seal_randomness_height: BlockNumber::one(), + } + } + } + + impl SectorPreCommitInfoBuilder + where + BlockNumber: sp_runtime::traits::BlockNumber, + { + pub fn sector_number(mut self, sector_number: SectorNumber) -> Self { + self.sector_number = sector_number; + self + } + + /// Panics if the length of `deal_ids` is larger than [`MAX_DEALS_PER_SECTOR`]. + pub fn deals(mut self, deal_ids: Vec) -> Self { + self.deal_ids = BoundedVec::try_from(deal_ids).unwrap(); + self + } + + pub fn expiration(mut self, expiration: BlockNumber) -> Self { + self.expiration = expiration; + self + } + + pub fn unsealed_cid(mut self, unsealed_cid: &str) -> Self { + let cid = Cid::from_str(unsealed_cid).expect("valid unsealed_cid"); + self.unsealed_cid = BoundedVec::try_from(cid.to_bytes()).unwrap(); + self + } + + pub fn build(self) -> SectorPreCommitInfo { + SectorPreCommitInfo { + seal_proof: self.seal_proof, + sector_number: self.sector_number, + sealed_cid: self.sealed_cid, + deal_ids: self.deal_ids, + expiration: self.expiration, + unsealed_cid: self.unsealed_cid, + seal_randomness_height: self.seal_randomness_height, + } + } + } +} diff --git a/primitives/src/sector/size.rs b/primitives/src/sector/size.rs new file mode 100644 index 000000000..1d9f8aca2 --- /dev/null +++ b/primitives/src/sector/size.rs @@ -0,0 +1,52 @@ +//! Sector size primitive. + +use codec::{Decode, Encode}; +use scale_decode::DecodeAsType; +use scale_encode::EncodeAsType; +use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; + +/// SectorSize indicates one of a set of possible sizes in the network. +#[derive( + Encode, Decode, DecodeAsType, EncodeAsType, TypeInfo, Clone, RuntimeDebug, PartialEq, Eq, Copy, +)] +#[cfg_attr(feature = "serde", derive(::serde::Deserialize, ::serde::Serialize))] +#[codec(crate = ::codec)] +#[decode_as_type(crate_path = "::scale_decode")] +#[encode_as_type(crate_path = "::scale_encode")] +pub enum SectorSize { + _2KiB, + _8MiB, + _512MiB, + _32GiB, + _64GiB, +} + +impl SectorSize { + /// Returns the size of a sector in bytes + /// + pub fn bytes(&self) -> u64 { + match self { + SectorSize::_2KiB => 2 << 10, + SectorSize::_8MiB => 8 << 20, + SectorSize::_512MiB => 512 << 20, + SectorSize::_32GiB => 32 << 30, + SectorSize::_64GiB => 2 * (32 << 30), + } + } +} + +impl core::fmt::Display for SectorSize { + fn fmt( + &self, + f: &mut scale_info::prelude::fmt::Formatter<'_>, + ) -> scale_info::prelude::fmt::Result { + match self { + SectorSize::_2KiB => write!(f, "2KiB"), + SectorSize::_8MiB => write!(f, "8MiB"), + SectorSize::_512MiB => write!(f, "512MiB"), + SectorSize::_32GiB => write!(f, "32GiB"), + SectorSize::_64GiB => write!(f, "64GiB"), + } + } +}