From 6f3d7859511c40c45b76cfbcce290e9f87d9a679 Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Sat, 22 Jun 2024 14:45:02 +0200 Subject: [PATCH] chore: extract primitives for proofs --- Cargo.lock | 12 +++ Cargo.toml | 3 +- pallets/market/Cargo.toml | 1 + pallets/market/src/lib.rs | 142 +++++++++++--------------------- pallets/market/src/test.rs | 2 +- primitives/proofs/Cargo.toml | 28 +++++++ primitives/proofs/src/lib.rs | 7 ++ primitives/proofs/src/traits.rs | 26 ++++++ primitives/proofs/src/types.rs | 34 ++++++++ 9 files changed, 161 insertions(+), 94 deletions(-) create mode 100644 primitives/proofs/Cargo.toml create mode 100644 primitives/proofs/src/lib.rs create mode 100644 primitives/proofs/src/traits.rs create mode 100644 primitives/proofs/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index a2e103688..482825245 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7185,6 +7185,7 @@ dependencies = [ "multihash-codetable", "pallet-balances", "parity-scale-codec", + "primitives-proofs", "scale-info", "sp-arithmetic", "sp-core", @@ -9692,6 +9693,17 @@ dependencies = [ "uint", ] +[[package]] +name = "primitives-proofs" +version = "0.1.0" +dependencies = [ + "cid 0.11.1", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + [[package]] name = "prioritized-metered-channel" version = "0.6.1" diff --git a/Cargo.toml b/Cargo.toml index 7f6c7347f..270f35ef4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license-file = "LICENSE" repository = "https://github.com/eigerco/polka-storage" [workspace] -members = ["cli/polka-storage-provider", "node", "pallets/market", "primitives/cli", "runtime", "storage/mater", "storage/polka-index"] +members = ["cli/polka-storage-provider", "node", "pallets/market", "primitives/cli", "primitives/proofs", "runtime", "storage/mater", "storage/polka-index"] resolver = "2" [profile.ci] @@ -83,6 +83,7 @@ uuid = "1.8.0" cli-primitives = { path = "primitives/cli" } pallet-market = { path = "pallets/market", default-features = false } polka-storage-runtime = { path = "runtime" } +primitives-proofs = { path = "primitives/proofs" } # Substrate pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0" } diff --git a/pallets/market/Cargo.toml b/pallets/market/Cargo.toml index c9cc165f5..7360a22a3 100644 --- a/pallets/market/Cargo.toml +++ b/pallets/market/Cargo.toml @@ -20,6 +20,7 @@ cid = { workspace = true, default-features = false, features = ["scale-codec"] } codec = { workspace = true, default-features = false, features = ["derive"] } log = { workspace = true } multihash-codetable = { workspace = true, features = ["blake2b"] } +primitives-proofs = { workspace = true } scale-info = { workspace = true, default-features = false, features = ["derive"] } # frame deps diff --git a/pallets/market/src/lib.rs b/pallets/market/src/lib.rs index e65869baf..25cb092c5 100644 --- a/pallets/market/src/lib.rs +++ b/pallets/market/src/lib.rs @@ -40,6 +40,9 @@ pub mod pallet { }; use frame_system::{pallet_prelude::*, Config as SystemConfig, Pallet as System}; use multihash_codetable::{Code, MultihashDigest}; + use primitives_proofs::{ + DealId, Market, RegisteredSealProof, SectorDeal, SectorNumber, SectorSize, + }; use scale_info::TypeInfo; use sp_arithmetic::traits::BaseArithmetic; use sp_std::vec::Vec; @@ -49,9 +52,6 @@ pub mod pallet { pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - // TODO(@th7nder,17/06/2024): this is likely to be extracted into primitives/ package - type DealId = u64; - #[pallet::config] pub trait Config: frame_system::Config { /// Because this pallet emits events, it depends on the runtime's definition of an event. @@ -93,10 +93,6 @@ pub mod pallet { /// https://github.com/filecoin-project/builtin-actors/blob/c32c97229931636e3097d92cf4c43ac36a7b4b47/actors/market/src/policy.rs#L29 #[pallet::constant] type MaxDealDuration: Get>; - - /// How many deals can be activated in a single batch. - #[pallet::constant] - type MaxSectorsForActivation: Get; } /// Stores balances info for both Storage Providers and Storage Users @@ -220,47 +216,6 @@ pub mod pallet { pub client_signature: OffchainSignature, } - // TODO(@th7nder,20/06/2024): this DOES NOT belong here. it should be somewhere else. - #[allow(non_camel_case_types)] - #[derive(Debug, Decode, Encode, TypeInfo, Eq, PartialEq, Clone)] - pub enum RegisteredSealProof { - StackedDRG2KiBV1P1, - } - - impl RegisteredSealProof { - pub fn sector_size(&self) -> SectorSize { - SectorSize::_2KiB - } - } - - /// SectorSize indicates one of a set of possible sizes in the network. - #[derive(Encode, Decode, TypeInfo, Clone, Debug, PartialEq, Eq, Copy)] - pub enum SectorSize { - _2KiB, - } - - impl SectorSize { - /// - pub fn bytes(&self) -> u64 { - match self { - SectorSize::_2KiB => 2 << 10, - } - } - } - - // TODO(@th7nder,20/06/2024): this DOES not belong here. it should be somewhere else. - pub type SectorNumber = u64; - - #[derive(Debug, Decode, Encode, TypeInfo, Eq, PartialEq, Clone)] - pub struct SectorDeal { - pub sector_number: SectorNumber, - pub sector_expiry: BlockNumber, - pub sector_type: RegisteredSealProof, - pub deal_ids: BoundedVec>, - } - // verify_deals_for_activation is called by Storage Provider Pallllllet! - // it's not an extrinsic then? - #[pallet::pallet] pub struct Pallet(_); @@ -315,10 +270,15 @@ pub mod pallet { AllProposalsInvalid, /// `publish_storage_deals`'s core logic was invoked with a broken invariant that should be called by `validate_deals`. UnexpectedValidationError, + /// There is more than 1 deal of this ID in the Sector DuplicateDeal, + /// Due to a programmer bug, bounds on Bounded data structures were incorrect so couldn't insert into them. DealPreconditionFailed, + /// Tried to activate a deal which is not in the system, DealNotFound, + /// Tried to activate a deal, but data doesn't make sense. Details are in the logs. DealActivationError, + /// Sum of all of the deals piece sizes for a sector exceeds sector size. DealsTooLargeToFitIntoSector, } @@ -522,50 +482,6 @@ pub mod pallet { Ok(()) } - /// Verifies a given set of storage deals is valid for sectors being PreCommitted. - /// Computes UnsealedCID (CommD) for each sector or None for Committed Capacity sectors.. - /// Currently UnsealedCID is hardcoded as we `compute_commd` remains unimplemented because of #92. - pub fn verify_deals_for_activation( - storage_provider: &T::AccountId, - sector_deals: BoundedVec>, T::MaxSectorsForActivation>, - ) -> Result, T::MaxSectorsForActivation>, DispatchError> { - // TODO: - // - primitives - // - trait in primitives - // - docs - let curr_block = System::::block_number(); - let mut unsealed_cids = BoundedVec::new(); - for sector in sector_deals { - let proposals = Self::proposals_for_deals(sector.deal_ids)?; - let sector_size = sector.sector_type.sector_size(); - Self::validate_deals_for_sector( - &proposals, - storage_provider, - sector.sector_number, - sector.sector_expiry, - curr_block, - sector_size, - )?; - - // Sealing a Sector without Deals, Committed Capacity Only. - let commd = if proposals.is_empty() { - None - } else { - Some(Self::compute_commd( - proposals.iter().map(|(_, deal)| deal), - sector.sector_type, - )?) - }; - - // PRE-COND: can't fail, unsealed_cids<_, X> == BoundedVec<_ X> == sector_deals<_, X> - unsealed_cids - .try_push(commd) - .map_err(|_| "programmer error, there should be space for Cids")?; - } - - Ok(unsealed_cids) - } - /// fn compute_commd<'a>( _proposals: impl IntoIterator>, @@ -834,4 +750,46 @@ pub mod pallet { T::Hashing::hash(&bytes) } } + + impl Market> for Pallet { + /// Verifies a given set of storage deals is valid for sectors being PreCommitted. + /// Computes UnsealedCID (CommD) for each sector or None for Committed Capacity sectors. + /// Currently UnsealedCID is hardcoded as we `compute_commd` remains unimplemented because of #92. + fn verify_deals_for_activation( + storage_provider: &T::AccountId, + sector_deals: BoundedVec>, ConstU32<32>>, + ) -> Result, ConstU32<32>>, DispatchError> { + let curr_block = System::::block_number(); + let mut unsealed_cids = BoundedVec::new(); + for sector in sector_deals { + let proposals = Self::proposals_for_deals(sector.deal_ids)?; + let sector_size = sector.sector_type.sector_size(); + Self::validate_deals_for_sector( + &proposals, + storage_provider, + sector.sector_number, + sector.sector_expiry, + curr_block, + sector_size, + )?; + + // Sealing a Sector without Deals, Committed Capacity Only. + let commd = if proposals.is_empty() { + None + } else { + Some(Self::compute_commd( + proposals.iter().map(|(_, deal)| deal), + sector.sector_type, + )?) + }; + + // PRE-COND: can't fail, unsealed_cids<_, X> == BoundedVec<_ X> == sector_deals<_, X> + unsealed_cids + .try_push(commd) + .map_err(|_| "programmer error, there should be space for Cids")?; + } + + Ok(unsealed_cids) + } + } } diff --git a/pallets/market/src/test.rs b/pallets/market/src/test.rs index 308824da8..ca59eb9ae 100644 --- a/pallets/market/src/test.rs +++ b/pallets/market/src/test.rs @@ -5,10 +5,10 @@ use frame_support::{ assert_noop, assert_ok, sp_runtime::{bounded_vec, ArithmeticError, TokenError}, }; +use primitives_proofs::{RegisteredSealProof, SectorDeal, Market as MarketTrait}; use crate::{ mock::*, BalanceEntry, BalanceTable, DealProposal, DealState, Error, Event, Proposals, - RegisteredSealProof, SectorDeal, }; #[test] diff --git a/primitives/proofs/Cargo.toml b/primitives/proofs/Cargo.toml new file mode 100644 index 000000000..f736e92bd --- /dev/null +++ b/primitives/proofs/Cargo.toml @@ -0,0 +1,28 @@ +[package] +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +name = "primitives-proofs" +repository.workspace = true +version = "0.1.0" + +[dependencies] +cid = { workspace = true, default-features = false } +codec = { workspace = true, default-features = false } +scale-info = { workspace = true, default-features = false } + +sp-runtime = { workspace = true, default-features = false } +sp-core = { workspace = true, default-features = false} + +[lints] +workspace = true + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + "sp-runtime/std", + "sp-core/std" +] \ No newline at end of file diff --git a/primitives/proofs/src/lib.rs b/primitives/proofs/src/lib.rs new file mode 100644 index 000000000..72baaff7b --- /dev/null +++ b/primitives/proofs/src/lib.rs @@ -0,0 +1,7 @@ +#![deny(unused_crate_dependencies)] + +mod traits; +mod types; + +pub use traits::*; +pub use types::*; diff --git a/primitives/proofs/src/traits.rs b/primitives/proofs/src/traits.rs new file mode 100644 index 000000000..6807364b8 --- /dev/null +++ b/primitives/proofs/src/traits.rs @@ -0,0 +1,26 @@ +use cid::Cid; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_core::ConstU32; +use sp_runtime::{BoundedVec, DispatchError}; + +use crate::types::{DealId, RegisteredSealProof, SectorNumber}; + +/// Represents functions that are provided by the Market Provider Pallet +pub trait Market { + /// Verifies a given set of storage deals is valid for sectors being PreCommitted. + /// Computes UnsealedCID (CommD) for each sector or None for Committed Capacity sectors. + fn verify_deals_for_activation( + storage_provider: &AccountId, + sector_deals: BoundedVec, ConstU32<32>>, + ) -> Result, ConstU32<32>>, DispatchError>; +} + +/// Binds given Sector with the Deals that it should contain +#[derive(Debug, Decode, Encode, TypeInfo, Eq, PartialEq, Clone)] +pub struct SectorDeal { + pub sector_number: SectorNumber, + pub sector_expiry: BlockNumber, + pub sector_type: RegisteredSealProof, + pub deal_ids: BoundedVec>, +} diff --git a/primitives/proofs/src/types.rs b/primitives/proofs/src/types.rs new file mode 100644 index 000000000..fc965ac20 --- /dev/null +++ b/primitives/proofs/src/types.rs @@ -0,0 +1,34 @@ +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub type DealId = u64; + +pub type SectorNumber = u64; + +#[allow(non_camel_case_types)] +#[derive(Debug, Decode, Encode, TypeInfo, Eq, PartialEq, Clone)] +pub enum RegisteredSealProof { + StackedDRG2KiBV1P1, +} + +impl RegisteredSealProof { + pub fn sector_size(&self) -> SectorSize { + SectorSize::_2KiB + } +} + +/// SectorSize indicates one of a set of possible sizes in the network. +#[derive(Encode, Decode, TypeInfo, Clone, Debug, PartialEq, Eq, Copy)] +pub enum SectorSize { + _2KiB, +} + +impl SectorSize { + /// Returns the size of a sector in bytes + /// + pub fn bytes(&self) -> u64 { + match self { + SectorSize::_2KiB => 2 << 10, + } + } +}