Skip to content

Support non-deal data in sectors (off-chain deals part 1) #57

@magik6k

Description

@magik6k

Problem

Currently Filecoin sectors can only store deal data referenced by on-chain deals. CC sectors and non-deal areas of sectors must store null (\0) bytes to be verifiable on-chain. This limitation is caused by how the UnsealedCID (CommD) is computed in the miner actor.

Unfortunately publishing deals is a very expensive on-chain operation, especially for smaller pieces where this cost it can be the main part of the storage fee. Off-chain deal support / alternative markets (e.g. more scalable storage market on ETH2.0 with data stored on Filecoin) seem to be good solutions to this problem, at least for non-FIL+ deals.

This proposal is only the first, but major, part of what needs to be done to support off-chain deals. It's likely that some off-chain deal protocols will require additional actor methods to be implemented (for example a method to check if a sector wasn't terminated early for settling payment channels)

Current state

Currently, when precommitting sectors, a number of DealIDs can be specified with SectorPreCommitInfo:

// Information provided by a miner when pre-committing a sector.
type SectorPreCommitInfo struct {
	SealProof       abi.RegisteredSealProof
	SectorNumber    abi.SectorNumber
	SealedCID       cid.Cid `checked:"true"`
	SealRandEpoch   abi.ChainEpoch
	DealIDs         []abi.DealID    // ****
	Expiration      abi.ChainEpoch
	ReplaceCapacity bool
	ReplaceSectorDeadline  uint64
	ReplaceSectorPartition uint64
	ReplaceSectorNumber    abi.SectorNumber
}

This information is then stored in miner actor state, and used to compute UnsealedCID when verifying PoRep by turning specified DealIDs into []abi.PieceInfos, and calling the ComputeUnsealedSectorCID syscall through the storage market actor.

type abi.PieceInfo struct {
	Size     abi.PaddedPieceSize
	PieceCID cid.Cid
}
ComputeUnsealedSectorCID(reg abi.RegisteredSealProof, pieces []abi.PieceInfo) (cid.Cid, error)

Proposed solution

We can change or create a new version of the SectorPreCommitInfo miner actor struct, changing the DealIDs array to a new array which allows specifying non-deal PieceCIDs:

+type SectorPieceInfo struct{
+	PieceCID  *cid.Cid `checked:"true"` // CommP
+	PieceSize abi.PaddedPieceSize
+
+	DealID abi.DealID
+}

// Information provided by a miner when pre-committing a sector.
type SectorPreCommitInfo struct {
	SealProof       abi.RegisteredSealProof
	SectorNumber    abi.SectorNumber
	SealedCID       cid.Cid `checked:"true"` // CommR
	SealRandEpoch   abi.ChainEpoch
-	DealIDs         []abi.DealID
+	Pieces          []SectorPieceInfo

	Expiration      abi.ChainEpoch
	ReplaceCapacity bool // Whether to replace a "committed capacity" no-deal sector (requires non-empty DealIDs)
	// The committed capacity sector to replace, and it's deadline/partition location
	ReplaceSectorDeadline  uint64
	ReplaceSectorPartition uint64
	ReplaceSectorNumber    abi.SectorNumber
}

When computing UnsealedCID for PoRep verification, []SectorPieceInfo would be turned into []abi.PieceInfo for the ComputeUnsealedSectorCID actor syscall as follows:

  • If PieceCID is null, assert that PieceSize==0, then get abi.PieceInfo for the referenced DealID from the market actor
  • If PieceCID is not null, assert that DealID==0, check the multicodec/multihash the same way it's checked in the storage market actor, then create abi.PieceInfo using specified PieceCID/PieceSize
  • Process all entries in sequence, keeping order when creating []abi.PieceInfo to allow interleaving non-deal and deal data

(it's possible to save 1 byte per entry by changing PieceSize/DealID to a single uint64 value (DealIdOrPieceSize), and processing it based on whether PieceCID is null or not)

Discussion

State migration

Depending on implementation details, this proposal may involve a relatively major state migration. We should look into ways of limiting that.

Added overhead for deal data

Publishing storage on-chain deals already has multiple kilobytes of read/write overhead. Each abi.DealID entry is 5B (1B cbor header, 4B for integer data). Depending on implementation, a dealID SectorPieceInfo entry will be 7 or 8 bytes, which is a negligible difference

Related FIPs

  • FIP-0008 (Add miner batched sector pre-commit method) is proposing creation of a new precommit method. It could be used to also introduce changes to SectorPreCommitInfo without breaking the old method
  • FIP-0007 (h/amt-v3) requires a migration of all HAMT data. Since this proposal also likely requires migration of at least miner PreCommittedSectors HAMTs, it may be a good idea to bundle those migrations into a single state upgrade

Metadata

Metadata

Assignees

No one assigned

    Labels

    FIP0016Links an existing discussion item to an existing FIP.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions