Skip to content

Commit

Permalink
feat(market-pallet): verify_deaals_for_activation
Browse files Browse the repository at this point in the history
  • Loading branch information
th7nder committed Jun 20, 2024
1 parent 3ef637d commit 1ee3bd8
Showing 1 changed file with 141 additions and 2 deletions.
143 changes: 141 additions & 2 deletions pallets/market/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub mod pallet {
},
PalletId,
};
use frame_system::{pallet_prelude::*, Config as SystemConfig};
use frame_system::{pallet_prelude::*, Config as SystemConfig, Pallet as System};
use scale_info::TypeInfo;
use sp_arithmetic::traits::BaseArithmetic;
use sp_std::vec::Vec;
Expand Down Expand Up @@ -126,7 +126,7 @@ pub mod pallet {
/// Reference: <https://github.com/filecoin-project/builtin-actors/blob/17ede2b256bc819dc309edf38e031e246a516486/actors/market/src/deal.rs#L138>
pub struct ActiveDealState<BlockNumber> {
/// Sector in which given piece has been included
sector_number: u128,
sector_number: SectorNumber,

/// At which block (time) the deal's sector has been activated.
sector_start_block: BlockNumber,
Expand Down Expand Up @@ -201,6 +201,9 @@ pub mod pallet {
}
}

type DealProposalOf<T> =
DealProposal<<T as frame_system::Config>::AccountId, BalanceOf<T>, BlockNumberFor<T>>;

/// After Storage Client has successfully negotiated with the Storage Provider, they prepare a DealProposal,
/// sign it with their signature and send to the Storage Provider.
/// Storage Provider only after successful file transfer and verification of the data, calls an extrinsic `market.publish_storage_deals`.
Expand All @@ -212,6 +215,38 @@ 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,
}

// 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<BlockNumber> {
pub sector_number: SectorNumber,
pub sector_expiry: BlockNumber,
pub sector_type: RegisteredSealProof,
pub deal_ids: BoundedVec<DealId, ConstU32<128>>,
}
// verify_deals_for_activation is called by Storage Provider Pallllllet!
// it's not an extrinsic then?

#[pallet::pallet]
pub struct Pallet<T>(_);

Expand Down Expand Up @@ -266,6 +301,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,
DuplicateDeal {
deal_id: DealId,
},
DealPreconditionFailed {
deal_id: DealId,
},
DealNotFound {
deal_id: DealId,
},
}

// NOTE(@th7nder,18/06/2024):
Expand Down Expand Up @@ -456,6 +500,101 @@ pub mod pallet {
Ok(())
}

/// Exposed to the Storage Provider Pallet
/// They call it when doing `precommit`.
/// Verify that a given set of storage deals is valid for a sector currently being PreCommitted
/// and return UnsealedCID for the set of deals.
// TODO(@th7nder,20/06/2024): what's a good number for BoundedVec `sector_deals`?
pub fn verify_deals_for_activation(
storage_provider: &T::AccountId,
sector_deals: BoundedVec<SectorDeal<BlockNumberFor<T>>, ConstU32<32>>,
) -> Result<BoundedVec<Option<Cid>, ConstU32<32>>, DispatchError> {
let curr_block = System::<T>::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_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(), 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)
}

/// <https://github.com/filecoin-project/builtin-actors/blob/17ede2b256bc819dc309edf38e031e246a516486/actors/market/src/lib.rs#L1370>
fn compute_commd<'a>(
proposals: impl IntoIterator<Item = &'a DealProposalOf<T>>,
sector_type: RegisteredSealProof,
) -> Result<Cid, DispatchError> {
todo!();
}

/// <https://github.com/filecoin-project/builtin-actors/blob/17ede2b256bc819dc309edf38e031e246a516486/actors/market/src/lib.rs#L1388>
fn validate_deals_for_sector(
proposals: &BoundedVec<DealProposalOf<T>, ConstU32<32>>,
provider: &T::AccountId,
sector_expiry: BlockNumberFor<T>,
sector_activation: BlockNumberFor<T>,
sector_size: SectorSize,
) -> DispatchResult {
todo!();
}

/// <https://github.com/filecoin-project/builtin-actors/blob/17ede2b256bc819dc309edf38e031e246a516486/actors/market/src/lib.rs#L1570>
fn validate_deal_can_activate(
deal: &DealProposalOf<T>,
provider: &T::AccountId,
sector_expiry: BlockNumberFor<T>,
curr_block: BlockNumberFor<T>,
) -> DispatchResult {
todo!()
}

fn proposals_for_deals(
deal_ids: BoundedVec<DealId, ConstU32<128>>,
) -> Result<BoundedVec<DealProposalOf<T>, ConstU32<32>>, DispatchError> {
let mut unique_deals: BoundedBTreeSet<DealId, ConstU32<32>> = BoundedBTreeSet::new();
let mut proposals: BoundedVec<DealProposalOf<T>, ConstU32<32>> = BoundedVec::new();
for deal_id in deal_ids {
ensure!(
!unique_deals.contains(&deal_id),
Error::<T>::DuplicateDeal { deal_id }
);

// PRE-COND: always succeeds, unique_deals has the same boundary as sector.deal_ids[]
unique_deals
.try_insert(deal_id)
.map_err(|deal_id| Error::<T>::DealPreconditionFailed { deal_id })?;

let proposal: DealProposalOf<T> = Proposals::<T>::try_get(&deal_id)
.map_err(|_| Error::<T>::DealNotFound { deal_id })?;

// PRE-COND: always succeeds, unique_deals has the same boundary as sector.deal_ids[]
proposals
.try_push(proposal)
.map_err(|_| Error::<T>::DealPreconditionFailed { deal_id })?;
}

Ok(proposals)
}

fn generate_deal_id() -> DealId {
let ret = NextDealId::<T>::get();
let next = ret
Expand Down

0 comments on commit 1ee3bd8

Please sign in to comment.