From 4998e04bcd95083a49f986f7e35dc366f3f78bec Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Mon, 24 Jun 2024 12:04:55 +0200 Subject: [PATCH 1/8] feat: add activate_deals to primitives --- primitives/proofs/Cargo.toml | 2 +- primitives/proofs/src/traits.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/primitives/proofs/Cargo.toml b/primitives/proofs/Cargo.toml index b3e142667..b17126af0 100644 --- a/primitives/proofs/Cargo.toml +++ b/primitives/proofs/Cargo.toml @@ -20,4 +20,4 @@ workspace = true [features] default = ["std"] -std = ["codec/std", "scale-info/std", "sp-core/std", "sp-runtime/std"] +std = ["codec/std", "scale-info/std", "sp-core/std", "sp-runtime/std", "cid/scale-codec"] diff --git a/primitives/proofs/src/traits.rs b/primitives/proofs/src/traits.rs index fd0d58ab9..52c3d8931 100644 --- a/primitives/proofs/src/traits.rs +++ b/primitives/proofs/src/traits.rs @@ -12,6 +12,18 @@ pub trait Market { storage_provider: &AccountId, sector_deals: BoundedVec, ConstU32<32>>, ) -> Result, ConstU32<32>>, DispatchError>; + + /// Activate a set of deals grouped by sector, returning the size and + /// extra info about verified deals. + /// Sectors' deals are activated in parameter-defined order. + /// Each sector's deals are activated or fail as a group, but independently of other sectors. + /// Note that confirming all deals fit within a sector is the caller's responsibility + /// (and is implied by confirming the sector's data commitment is derived from the deal peices). + fn activate_deals( + storage_provider: &AccountId, + sector_deals: BoundedVec, ConstU32<32>>, + compute_cid: bool, + ) -> Result, ConstU32<32>>, DispatchError>; } /// Binds given Sector with the Deals that it should contain @@ -33,3 +45,17 @@ pub struct SectorDeal { /// If any of those is invalid, whole activation is rejected. pub deal_ids: BoundedVec>, } + +pub struct ActivatedSector { + /// Information about each deal activated. + pub activated_deals: Vec>, + /// Unsealed CID computed from the deals specified for the sector. + /// A None indicates no deals were specified, or the computation was not requested. + pub unsealed_cid: Option, +} + +pub struct ActivatedDeal { + pub client: AccountId, + pub piece_cid: Cid, + pub piece_size: u64, +} \ No newline at end of file From 2576db1f520f88a38c6c8484f687132db28996f0 Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Mon, 24 Jun 2024 16:59:49 +0200 Subject: [PATCH 2/8] feat(pallet-market): implement activate_deals --- pallets/market/src/lib.rs | 137 +++++++++++++++++++++++++++++--- pallets/market/src/mock.rs | 2 +- pallets/market/src/test.rs | 87 +++++++++++++++++++- primitives/proofs/Cargo.toml | 2 +- primitives/proofs/src/traits.rs | 6 +- 5 files changed, 216 insertions(+), 18 deletions(-) diff --git a/pallets/market/src/lib.rs b/pallets/market/src/lib.rs index 3dab0b8ce..d21623feb 100644 --- a/pallets/market/src/lib.rs +++ b/pallets/market/src/lib.rs @@ -41,7 +41,8 @@ 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, + ActivatedDeal, ActivatedSector, DealId, Market, RegisteredSealProof, SectorDeal, + SectorNumber, SectorSize, }; use scale_info::TypeInfo; use sp_arithmetic::traits::BaseArithmetic; @@ -253,6 +254,12 @@ pub mod pallet { client: T::AccountId, provider: T::AccountId, }, + // Deal has been successfully activated. + DealActivated { + deal_id: DealId, + client: T::AccountId, + provider: T::AccountId, + }, } #[pallet::error] @@ -292,6 +299,10 @@ pub mod pallet { SectorExpiresBeforeDeal, /// Deal needs to be [`DealState::Published`] if it's to be activated InvalidDealState, + /// Tried to activate a deal which is not in the system. + DealNotFound, + /// Tried to activate a deal which is not in the Pending Proposals + DealNotPending, } // NOTE(@th7nder,18/06/2024): @@ -548,6 +559,17 @@ pub mod pallet { DealActivationError::SectorExpiresBeforeDeal ); + // Confirm the deal is in the pending proposals set. + // It will be removed from this queue later, during cron. + // Failing this check is an internal invariant violation. + // The pending deals set exists to prevent duplicate proposals. + // It should be impossible to have a proposal, no deal state, and not be in pending deals. + let hash = Self::hash_proposal(&deal); + ensure!( + PendingProposals::::get().contains(&hash), + DealActivationError::DealNotPending + ); + Ok(()) } @@ -710,17 +732,19 @@ pub mod pallet { return None; } - let hash = Self::hash_proposal(&deal); + let hash = Self::hash_proposal(&deal.proposal); let duplicate_in_state = PendingProposals::::get().contains(&hash); let duplicate_in_message = message_proposals.contains(&hash); if duplicate_in_state || duplicate_in_message { log::error!(target: LOG_TARGET, "invalid deal: cannot publish duplicate deal idx: {}", idx); return None; } - if let Err(e) = PendingProposals::::get().try_insert(hash) { + let mut pending = PendingProposals::::get(); + if let Err(e) = pending.try_insert(hash) { log::error!(target: LOG_TARGET, "cannot publish: too many pending deal proposals, wait for them to be expired/activated, deal idx: {}, err: {:?}", idx, e); return None; } + PendingProposals::::set(pending); // PRE-COND: always succeeds, as there cannot be more deals than T::MaxDeals and this the size of the set message_proposals.try_insert(hash).ok()?; // PRE-COND: always succeeds as there cannot be more clients than T::MaxDeals @@ -735,16 +759,11 @@ pub mod pallet { } // Used for deduplication purposes - // We don't want to store another BTreeSet of ClientDealProposals + // We don't want to store another BTreeSet of DealProposals // We only care about hashes. // It is not an associated function, because T::Hashing is hard to use inside of there. - fn hash_proposal( - proposal: &ClientDealProposal< - T::AccountId, - BalanceOf, - BlockNumberFor, - T::OffchainSignature, - >, + pub(crate) fn hash_proposal( + proposal: &DealProposal, BlockNumberFor>, ) -> T::Hash { let bytes = Encode::encode(proposal); T::Hashing::hash(&bytes) @@ -791,5 +810,101 @@ pub mod pallet { Ok(unsealed_cids) } + + /// Activate a set of deals grouped by sector, returning the size and + /// extra info about verified deals. + /// Sectors' deals are activated in parameter-defined order. + /// Each sector's deals are activated or fail as a group, but independently of other sectors. + /// Note that confirming all deals fit within a sector is the caller's responsibility + /// (and is implied by confirming the sector's data commitment is derived from the deal peices). + fn activate_deals( + storage_provider: &T::AccountId, + sector_deals: BoundedVec>, ConstU32<32>>, + compute_cid: bool, + ) -> Result, ConstU32<32>>, DispatchError> + { + // TODO(@th7nder,#87,17/06/2024): validate a Storage Provider's Account (whether the account was registerd as Storage Provider) + let mut activations = BoundedVec::new(); + let curr_block = System::::block_number(); + let mut activated_deals: BoundedBTreeSet> = + BoundedBTreeSet::new(); + + for sector in sector_deals { + let proposals = Self::proposals_for_deals(sector.deal_ids)?; + let sector_size = sector.sector_type.sector_size(); + if let Err(e) = Self::validate_deals_for_sector( + &proposals, + storage_provider, + sector.sector_number, + sector.sector_expiry, + curr_block, + sector_size, + ) { + log::error!( + "failed to activate sector: {}, skipping... {:?}", + sector.sector_number, + e + ); + continue; + } + + let data_commitment = if compute_cid && !proposals.is_empty() { + Some(Self::compute_commd( + proposals.iter().map(|(_, deal)| deal), + sector.sector_type, + )?) + } else { + None + }; + + let mut activated: BoundedVec<_, ConstU32<128>> = BoundedVec::new(); + for (deal_id, mut proposal) in proposals { + proposal.state = DealState::Active(ActiveDealState { + sector_number: sector.sector_number, + sector_start_block: curr_block, + last_updated_block: None, + slash_block: None, + }); + + activated + .try_push(ActivatedDeal { + client: proposal.client.clone(), + piece_cid: proposal.cid().map_err(|e| { + log::error!( + "there is invalid cid saved on-chain for deal: {}, {:?}", + deal_id, + e + ); + Error::::DealPreconditionFailed + })?, + piece_size: proposal.piece_size, + }) + .map_err(|_| { + log::error!("failed to insert into `activated`, programmer's error"); + Error::::DealPreconditionFailed + })?; + activated_deals.try_insert(deal_id).map_err(|_| { + log::error!("failed to insert into `activated_deals`, programmer's error"); + Error::::DealPreconditionFailed + })?; + + Self::deposit_event(Event::::DealActivated { + deal_id, + client: proposal.client.clone(), + provider: proposal.provider.clone(), + }); + Proposals::::insert(deal_id, proposal); + } + + activations + .try_push(ActivatedSector { + activated_deals: activated, + unsealed_cid: data_commitment, + }) + .map_err(|_| Error::::DealPreconditionFailed)?; + } + + Ok(activations) + } } } diff --git a/pallets/market/src/mock.rs b/pallets/market/src/mock.rs index 92bec1f13..8a120714e 100644 --- a/pallets/market/src/mock.rs +++ b/pallets/market/src/mock.rs @@ -76,7 +76,7 @@ pub fn cid_of(data: &str) -> cid::Cid { Cid::new_v1(CID_CODEC, Code::Blake2b256.digest(data.as_bytes())) } -type DealProposalOf = +pub(crate) type DealProposalOf = DealProposal<::AccountId, BalanceOf, BlockNumberFor>; type ClientDealProposalOf = ClientDealProposal< diff --git a/pallets/market/src/test.rs b/pallets/market/src/test.rs index 901d388bc..14885ce53 100644 --- a/pallets/market/src/test.rs +++ b/pallets/market/src/test.rs @@ -4,11 +4,15 @@ use cid::Cid; use frame_support::{ assert_noop, assert_ok, sp_runtime::{bounded_vec, ArithmeticError, TokenError}, + BoundedBTreeSet, +}; +use primitives_proofs::{ + ActivatedDeal, ActivatedSector, DealId, Market as MarketTrait, RegisteredSealProof, SectorDeal, }; -use primitives_proofs::{Market as MarketTrait, RegisteredSealProof, SectorDeal}; use crate::{ - mock::*, BalanceEntry, BalanceTable, DealProposal, DealState, Error, Event, Proposals, + mock::*, BalanceEntry, BalanceTable, DealProposal, DealState, Error, Event, PendingProposals, + Proposals, }; #[test] @@ -230,6 +234,8 @@ fn publish_storage_deals() { state: DealState::Unpublished, }, ); + let alice_hash = Market::hash_proposal(&alice_proposal.proposal); + let bob_hash = Market::hash_proposal(&bob_proposal.proposal); let _ = Market::add_balance(RuntimeOrigin::signed(account(ALICE)), 60); let _ = Market::add_balance(RuntimeOrigin::signed(account(BOB)), 70); @@ -277,6 +283,8 @@ fn publish_storage_deals() { }), ] ); + assert!(PendingProposals::::get().contains(&alice_hash)); + assert!(PendingProposals::::get().contains(&bob_hash)); }); } @@ -284,7 +292,7 @@ fn publish_storage_deals() { fn verify_deals_for_activation() { let _ = env_logger::try_init(); new_test_ext().execute_with(|| { - Proposals::::insert( + insert_deal( 1, DealProposal { piece_cid: cid_of("polka-storage-data") @@ -330,3 +338,76 @@ fn verify_deals_for_activation() { ); }); } + +#[test] +fn activate_deals() { + let _ = env_logger::try_init(); + new_test_ext().execute_with(|| { + insert_deal( + 1, + DealProposal { + piece_cid: cid_of("polka-storage-data") + .to_bytes() + .try_into() + .expect("hash is always 32 bytes"), + piece_size: 18, + client: account(ALICE), + provider: account(PROVIDER), + label: bounded_vec![0xb, 0xe, 0xe, 0xf], + start_block: 100, + end_block: 110, + storage_price_per_block: 5, + provider_collateral: 25, + state: DealState::Published, + }, + ); + + let deals = bounded_vec![ + SectorDeal { + sector_number: 1, + sector_expiry: 120, + sector_type: RegisteredSealProof::StackedDRG2KiBV1P1, + deal_ids: bounded_vec![1] + }, + SectorDeal { + sector_number: 2, + sector_expiry: 50, + sector_type: RegisteredSealProof::StackedDRG2KiBV1P1, + deal_ids: bounded_vec![] + } + ]; + + let piece_cid = + Cid::from_str("bafk2bzacecg3xxc4f2ql2hreiuy767u6r72ekdz54k7luieknboaakhft5rgk") + .unwrap(); + let placeholder_commd_cid = + Cid::from_str("bafk2bzaceajreoxfdcpdvitpvxm7vkpvcimlob5ejebqgqidjkz4qoug4q6zu") + .unwrap(); + assert_eq!( + Ok(bounded_vec![ + ActivatedSector { + activated_deals: bounded_vec![ActivatedDeal { + client: account(ALICE), + piece_cid: piece_cid, + piece_size: 18 + }], + unsealed_cid: Some(placeholder_commd_cid), + }, + ActivatedSector { + activated_deals: bounded_vec![], + unsealed_cid: None + } + ]), + Market::activate_deals(&account(PROVIDER), deals, true) + ); + }); +} + +fn insert_deal(deal_id: DealId, deal: DealProposalOf) { + let hash = Market::hash_proposal(&deal); + let mut pending = BoundedBTreeSet::new(); + pending.try_insert(hash).unwrap(); + PendingProposals::::set(pending); + + Proposals::::insert(deal_id, deal); +} diff --git a/primitives/proofs/Cargo.toml b/primitives/proofs/Cargo.toml index b17126af0..7dce974eb 100644 --- a/primitives/proofs/Cargo.toml +++ b/primitives/proofs/Cargo.toml @@ -20,4 +20,4 @@ workspace = true [features] default = ["std"] -std = ["codec/std", "scale-info/std", "sp-core/std", "sp-runtime/std", "cid/scale-codec"] +std = ["cid/scale-codec", "codec/std", "scale-info/std", "sp-core/std", "sp-runtime/std"] diff --git a/primitives/proofs/src/traits.rs b/primitives/proofs/src/traits.rs index 52c3d8931..be2e2b00c 100644 --- a/primitives/proofs/src/traits.rs +++ b/primitives/proofs/src/traits.rs @@ -46,16 +46,18 @@ pub struct SectorDeal { pub deal_ids: BoundedVec>, } +#[derive(RuntimeDebug, Eq, PartialEq)] pub struct ActivatedSector { /// Information about each deal activated. - pub activated_deals: Vec>, + pub activated_deals: BoundedVec, ConstU32<128>>, /// Unsealed CID computed from the deals specified for the sector. /// A None indicates no deals were specified, or the computation was not requested. pub unsealed_cid: Option, } +#[derive(RuntimeDebug, Eq, PartialEq)] pub struct ActivatedDeal { pub client: AccountId, pub piece_cid: Cid, pub piece_size: u64, -} \ No newline at end of file +} From 5f61bc2e0bd5265e96c4318081c56f885709543d Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Wed, 26 Jun 2024 10:53:31 +0200 Subject: [PATCH 3/8] style: fix trait namings and extract consts for Market trait --- pallets/market/src/lib.rs | 45 +++++++++++++++++++-------------- pallets/market/src/test.rs | 10 ++++---- primitives/proofs/Cargo.toml | 2 +- primitives/proofs/src/traits.rs | 33 ++++++++++++++++++------ 4 files changed, 57 insertions(+), 33 deletions(-) diff --git a/pallets/market/src/lib.rs b/pallets/market/src/lib.rs index d21623feb..76e360dc5 100644 --- a/pallets/market/src/lib.rs +++ b/pallets/market/src/lib.rs @@ -41,8 +41,8 @@ pub mod pallet { use frame_system::{pallet_prelude::*, Config as SystemConfig, Pallet as System}; use multihash_codetable::{Code, MultihashDigest}; use primitives_proofs::{ - ActivatedDeal, ActivatedSector, DealId, Market, RegisteredSealProof, SectorDeal, - SectorNumber, SectorSize, + ActiveDeal, ActiveSector, DealId, Market, RegisteredSealProof, SectorDeal, SectorNumber, + SectorSize, MAX_DEALS_FOR_ALL_SECTORS, MAX_DEALS_PER_SECTOR, MAX_SECTORS_PER_CALL, }; use scale_info::TypeInfo; use sp_arithmetic::traits::BaseArithmetic; @@ -574,9 +574,9 @@ pub mod pallet { } fn proposals_for_deals( - deal_ids: BoundedVec>, - ) -> Result), ConstU32<32>>, DispatchError> { - let mut unique_deals: BoundedBTreeSet> = BoundedBTreeSet::new(); + deal_ids: BoundedVec>, + ) -> Result), ConstU32>, DispatchError> { + let mut unique_deals: BoundedBTreeSet> = BoundedBTreeSet::new(); let mut proposals = BoundedVec::new(); for deal_id in deal_ids { ensure!(!unique_deals.contains(&deal_id), { @@ -776,8 +776,9 @@ pub mod pallet { /// 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> { + sector_deals: BoundedVec>, ConstU32>, + ) -> Result, ConstU32>, DispatchError> + { let curr_block = System::::block_number(); let mut unsealed_cids = BoundedVec::new(); for sector in sector_deals { @@ -819,15 +820,19 @@ pub mod pallet { /// (and is implied by confirming the sector's data commitment is derived from the deal peices). fn activate_deals( storage_provider: &T::AccountId, - sector_deals: BoundedVec>, ConstU32<32>>, + sector_deals: BoundedVec>, ConstU32>, compute_cid: bool, - ) -> Result, ConstU32<32>>, DispatchError> - { + ) -> Result< + BoundedVec, ConstU32>, + DispatchError, + > { // TODO(@th7nder,#87,17/06/2024): validate a Storage Provider's Account (whether the account was registerd as Storage Provider) let mut activations = BoundedVec::new(); let curr_block = System::::block_number(); - let mut activated_deals: BoundedBTreeSet> = - BoundedBTreeSet::new(); + let mut activated_deal_ids: BoundedBTreeSet< + DealId, + ConstU32, + > = BoundedBTreeSet::new(); for sector in sector_deals { let proposals = Self::proposals_for_deals(sector.deal_ids)?; @@ -857,7 +862,7 @@ pub mod pallet { None }; - let mut activated: BoundedVec<_, ConstU32<128>> = BoundedVec::new(); + let mut activated_deals: BoundedVec<_, ConstU32<128>> = BoundedVec::new(); for (deal_id, mut proposal) in proposals { proposal.state = DealState::Active(ActiveDealState { sector_number: sector.sector_number, @@ -866,8 +871,8 @@ pub mod pallet { slash_block: None, }); - activated - .try_push(ActivatedDeal { + activated_deals + .try_push(ActiveDeal { client: proposal.client.clone(), piece_cid: proposal.cid().map_err(|e| { log::error!( @@ -883,8 +888,10 @@ pub mod pallet { log::error!("failed to insert into `activated`, programmer's error"); Error::::DealPreconditionFailed })?; - activated_deals.try_insert(deal_id).map_err(|_| { - log::error!("failed to insert into `activated_deals`, programmer's error"); + activated_deal_ids.try_insert(deal_id).map_err(|_| { + log::error!( + "failed to insert into `activated_deal_ids`, programmer's error" + ); Error::::DealPreconditionFailed })?; @@ -897,8 +904,8 @@ pub mod pallet { } activations - .try_push(ActivatedSector { - activated_deals: activated, + .try_push(ActiveSector { + active_deals: activated_deals, unsealed_cid: data_commitment, }) .map_err(|_| Error::::DealPreconditionFailed)?; diff --git a/pallets/market/src/test.rs b/pallets/market/src/test.rs index 14885ce53..ae6085d64 100644 --- a/pallets/market/src/test.rs +++ b/pallets/market/src/test.rs @@ -7,7 +7,7 @@ use frame_support::{ BoundedBTreeSet, }; use primitives_proofs::{ - ActivatedDeal, ActivatedSector, DealId, Market as MarketTrait, RegisteredSealProof, SectorDeal, + ActiveDeal, ActiveSector, DealId, Market as MarketTrait, RegisteredSealProof, SectorDeal, }; use crate::{ @@ -385,16 +385,16 @@ fn activate_deals() { .unwrap(); assert_eq!( Ok(bounded_vec![ - ActivatedSector { - activated_deals: bounded_vec![ActivatedDeal { + ActiveSector { + active_deals: bounded_vec![ActiveDeal { client: account(ALICE), piece_cid: piece_cid, piece_size: 18 }], unsealed_cid: Some(placeholder_commd_cid), }, - ActivatedSector { - activated_deals: bounded_vec![], + ActiveSector { + active_deals: bounded_vec![], unsealed_cid: None } ]), diff --git a/primitives/proofs/Cargo.toml b/primitives/proofs/Cargo.toml index 7dce974eb..24fe2f225 100644 --- a/primitives/proofs/Cargo.toml +++ b/primitives/proofs/Cargo.toml @@ -8,7 +8,7 @@ repository.workspace = true version = "0.1.0" [dependencies] -cid = { workspace = true, default-features = false } +cid = { workspace = true, default-features = false, features = ["alloc"]} codec = { workspace = true, default-features = false, features = ["derive"] } scale-info = { workspace = true, default-features = false, features = ["derive"] } diff --git a/primitives/proofs/src/traits.rs b/primitives/proofs/src/traits.rs index be2e2b00c..eb4f4fc21 100644 --- a/primitives/proofs/src/traits.rs +++ b/primitives/proofs/src/traits.rs @@ -4,14 +4,26 @@ use sp_runtime::{BoundedVec, DispatchError, RuntimeDebug}; use crate::types::{DealId, RegisteredSealProof, SectorNumber}; +/// Number of Sectors that can be provided in a single extrinsics call. +/// Required for BoundedVec. +/// It was selected arbitrarly, without precise calculations. +pub const MAX_SECTORS_PER_CALL: u32 = 32; +/// Number of Deals that can be contained in a single sector. +/// Required for BoundedVec. +/// It was selected arbitrarly, without precise calculations. +pub const MAX_DEALS_PER_SECTOR: u32 = 128; +/// Flattened size of all active deals for all of the sectors. +/// Required for BoundedVec. +pub const MAX_DEALS_FOR_ALL_SECTORS: u32 = MAX_SECTORS_PER_CALL * MAX_DEALS_PER_SECTOR; + /// 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>; + sector_deals: BoundedVec, ConstU32>, + ) -> Result, ConstU32>, DispatchError>; /// Activate a set of deals grouped by sector, returning the size and /// extra info about verified deals. @@ -21,9 +33,9 @@ pub trait Market { /// (and is implied by confirming the sector's data commitment is derived from the deal peices). fn activate_deals( storage_provider: &AccountId, - sector_deals: BoundedVec, ConstU32<32>>, + sector_deals: BoundedVec, ConstU32>, compute_cid: bool, - ) -> Result, ConstU32<32>>, DispatchError>; + ) -> Result, ConstU32>, DispatchError>; } /// Binds given Sector with the Deals that it should contain @@ -43,21 +55,26 @@ pub struct SectorDeal { pub sector_type: RegisteredSealProof, /// Deals Ids that are supposed to be activated. /// If any of those is invalid, whole activation is rejected. - pub deal_ids: BoundedVec>, + pub deal_ids: BoundedVec>, } +/// A sector with all of its active deals. #[derive(RuntimeDebug, Eq, PartialEq)] -pub struct ActivatedSector { +pub struct ActiveSector { /// Information about each deal activated. - pub activated_deals: BoundedVec, ConstU32<128>>, + pub active_deals: BoundedVec, ConstU32>, /// Unsealed CID computed from the deals specified for the sector. /// A None indicates no deals were specified, or the computation was not requested. pub unsealed_cid: Option, } +/// An active deal with references to data that it stores #[derive(RuntimeDebug, Eq, PartialEq)] -pub struct ActivatedDeal { +pub struct ActiveDeal { + /// Client's account pub client: AccountId, + /// Data that was stored pub piece_cid: Cid, + /// Real size of the data pub piece_size: u64, } From bdec583dc815ebbe69b1985b7c2f7904cd0a5098 Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Wed, 26 Jun 2024 10:59:09 +0200 Subject: [PATCH 4/8] test(pallet-market): publish_for_activation helper function --- pallets/market/src/lib.rs | 8 ++++++-- pallets/market/src/test.rs | 10 +++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pallets/market/src/lib.rs b/pallets/market/src/lib.rs index 76e360dc5..9178123c0 100644 --- a/pallets/market/src/lib.rs +++ b/pallets/market/src/lib.rs @@ -575,8 +575,12 @@ pub mod pallet { fn proposals_for_deals( deal_ids: BoundedVec>, - ) -> Result), ConstU32>, DispatchError> { - let mut unique_deals: BoundedBTreeSet> = BoundedBTreeSet::new(); + ) -> Result< + BoundedVec<(DealId, DealProposalOf), ConstU32>, + DispatchError, + > { + let mut unique_deals: BoundedBTreeSet> = + BoundedBTreeSet::new(); let mut proposals = BoundedVec::new(); for deal_id in deal_ids { ensure!(!unique_deals.contains(&deal_id), { diff --git a/pallets/market/src/test.rs b/pallets/market/src/test.rs index ae6085d64..d1612ac4b 100644 --- a/pallets/market/src/test.rs +++ b/pallets/market/src/test.rs @@ -292,7 +292,7 @@ fn publish_storage_deals() { fn verify_deals_for_activation() { let _ = env_logger::try_init(); new_test_ext().execute_with(|| { - insert_deal( + publish_for_activation( 1, DealProposal { piece_cid: cid_of("polka-storage-data") @@ -343,7 +343,7 @@ fn verify_deals_for_activation() { fn activate_deals() { let _ = env_logger::try_init(); new_test_ext().execute_with(|| { - insert_deal( + publish_for_activation( 1, DealProposal { piece_cid: cid_of("polka-storage-data") @@ -403,7 +403,11 @@ fn activate_deals() { }); } -fn insert_deal(deal_id: DealId, deal: DealProposalOf) { +/// Creates a new deal and saves it in the Runtime Storage. +/// In addition to saving it to `Proposals::` it also calculate's +/// it's hash and saves it to `PendingProposals::`. +/// Behaves like `publish_storage_deals` without the validation and calling extrinsics. +fn publish_for_activation(deal_id: DealId, deal: DealProposalOf) { let hash = Market::hash_proposal(&deal); let mut pending = BoundedBTreeSet::new(); pending.try_insert(hash).unwrap(); From fd0472aee835a7c0622a39d3a06d3c01123e18d2 Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Wed, 26 Jun 2024 11:01:47 +0200 Subject: [PATCH 5/8] docs(pallet-market): improve typos and spelling --- pallets/market/src/lib.rs | 6 +++--- primitives/proofs/src/traits.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pallets/market/src/lib.rs b/pallets/market/src/lib.rs index 9178123c0..e5a91f09d 100644 --- a/pallets/market/src/lib.rs +++ b/pallets/market/src/lib.rs @@ -695,7 +695,7 @@ pub mod pallet { Error::::ProposalsNotPublishedByStorageProvider ); - // TODO(@th7nder,#87,17/06/2024): validate a Storage Provider's Account (whether the account was registerd as Storage Provider) + // TODO(@th7nder,#87,17/06/2024): validate a Storage Provider's Account (whether the account was registered as Storage Provider) let mut total_client_lockup: BoundedBTreeMap, T::MaxDeals> = BoundedBTreeMap::new(); @@ -821,7 +821,7 @@ pub mod pallet { /// Sectors' deals are activated in parameter-defined order. /// Each sector's deals are activated or fail as a group, but independently of other sectors. /// Note that confirming all deals fit within a sector is the caller's responsibility - /// (and is implied by confirming the sector's data commitment is derived from the deal peices). + /// (and is implied by confirming the sector's data commitment is derived from the deal pieces). fn activate_deals( storage_provider: &T::AccountId, sector_deals: BoundedVec>, ConstU32>, @@ -830,7 +830,7 @@ pub mod pallet { BoundedVec, ConstU32>, DispatchError, > { - // TODO(@th7nder,#87,17/06/2024): validate a Storage Provider's Account (whether the account was registerd as Storage Provider) + // TODO(@th7nder,#87,17/06/2024): validate a Storage Provider's Account (whether the account was registered as Storage Provider) let mut activations = BoundedVec::new(); let curr_block = System::::block_number(); let mut activated_deal_ids: BoundedBTreeSet< diff --git a/primitives/proofs/src/traits.rs b/primitives/proofs/src/traits.rs index eb4f4fc21..37106f800 100644 --- a/primitives/proofs/src/traits.rs +++ b/primitives/proofs/src/traits.rs @@ -30,7 +30,7 @@ pub trait Market { /// Sectors' deals are activated in parameter-defined order. /// Each sector's deals are activated or fail as a group, but independently of other sectors. /// Note that confirming all deals fit within a sector is the caller's responsibility - /// (and is implied by confirming the sector's data commitment is derived from the deal peices). + /// (and is implied by confirming the sector's data commitment is derived from the deal pieces). fn activate_deals( storage_provider: &AccountId, sector_deals: BoundedVec, ConstU32>, From 973b0596b80568362ec5ddb9ce06e170bfbd30bd Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Wed, 26 Jun 2024 11:06:01 +0200 Subject: [PATCH 6/8] refactor(pallet-market): add constructor for ActiveDealState --- pallets/market/src/lib.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/pallets/market/src/lib.rs b/pallets/market/src/lib.rs index e5a91f09d..e105cda71 100644 --- a/pallets/market/src/lib.rs +++ b/pallets/market/src/lib.rs @@ -138,6 +138,20 @@ pub mod pallet { slash_block: Option, } + impl ActiveDealState { + fn new( + sector_number: SectorNumber, + sector_start_block: BlockNumber, + ) -> ActiveDealState { + ActiveDealState { + sector_number, + sector_start_block, + last_updated_block: None, + slash_block: None, + } + } + } + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] /// Reference: // It cannot be generic over because, #[derive(RuntimeDebug, TypeInfo)] also make `T` to have `RuntimeDebug`/`TypeInfo` @@ -868,12 +882,9 @@ pub mod pallet { let mut activated_deals: BoundedVec<_, ConstU32<128>> = BoundedVec::new(); for (deal_id, mut proposal) in proposals { - proposal.state = DealState::Active(ActiveDealState { - sector_number: sector.sector_number, - sector_start_block: curr_block, - last_updated_block: None, - slash_block: None, - }); + // Make it Active! This is what's this function is about in the end. + proposal.state = + DealState::Active(ActiveDealState::new(sector.sector_number, curr_block)); activated_deals .try_push(ActiveDeal { From d8823d06f15e6c93e5b547918644cf0ca4490ff2 Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Wed, 26 Jun 2024 12:18:17 +0200 Subject: [PATCH 7/8] fix(pallet-market): activated_deals bound --- pallets/market/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/market/src/lib.rs b/pallets/market/src/lib.rs index e105cda71..e4fd488cf 100644 --- a/pallets/market/src/lib.rs +++ b/pallets/market/src/lib.rs @@ -880,7 +880,7 @@ pub mod pallet { None }; - let mut activated_deals: BoundedVec<_, ConstU32<128>> = BoundedVec::new(); + let mut activated_deals: BoundedVec<_, ConstU32> = BoundedVec::new(); for (deal_id, mut proposal) in proposals { // Make it Active! This is what's this function is about in the end. proposal.state = From 2c909aa11a747a832d185dd47fced6f18691159d Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Fri, 28 Jun 2024 09:20:37 +0200 Subject: [PATCH 8/8] style: formatting --- pallets/market/src/lib.rs | 3 ++- primitives/proofs/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pallets/market/src/lib.rs b/pallets/market/src/lib.rs index e4fd488cf..601d8290d 100644 --- a/pallets/market/src/lib.rs +++ b/pallets/market/src/lib.rs @@ -880,7 +880,8 @@ pub mod pallet { None }; - let mut activated_deals: BoundedVec<_, ConstU32> = BoundedVec::new(); + let mut activated_deals: BoundedVec<_, ConstU32> = + BoundedVec::new(); for (deal_id, mut proposal) in proposals { // Make it Active! This is what's this function is about in the end. proposal.state = diff --git a/primitives/proofs/Cargo.toml b/primitives/proofs/Cargo.toml index 24fe2f225..56edb8c47 100644 --- a/primitives/proofs/Cargo.toml +++ b/primitives/proofs/Cargo.toml @@ -8,7 +8,7 @@ repository.workspace = true version = "0.1.0" [dependencies] -cid = { workspace = true, default-features = false, features = ["alloc"]} +cid = { workspace = true, default-features = false, features = ["alloc"] } codec = { workspace = true, default-features = false, features = ["derive"] } scale-info = { workspace = true, default-features = false, features = ["derive"] }