Skip to content
This repository has been archived by the owner on Jun 6, 2023. It is now read-only.

Prototype implementation of FIL+ explicity subsidy #1560

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions actors/builtin/cbor_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

257 changes: 133 additions & 124 deletions actors/builtin/market/market_actor.go

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions actors/builtin/market/market_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const (
// Bitwidth of AMTs determined empirically from mutation patterns and projections of mainnet data.
const ProposalsAmtBitwidth = 5
const StatesAmtBitwidth = 6
const VerifiedRewardsHistoryAmtBitwidth = 5 // FIXME calibrate this
const ProviderVerifiedClaimsHamtBitwidth = 5 // FIXME calibrate this
const StoragePowerDeltaQueueAmtBitwidth = 5 // FIXME calibrate this

type State struct {
// Proposals are deals that have been proposed and not yet cleaned up after expiry or termination.
Expand Down Expand Up @@ -60,6 +63,16 @@ type State struct {
TotalProviderLockedCollateral abi.TokenAmount
// Total storage fee that is locked in escrow -> unlocked when payments are made
TotalClientStorageFee abi.TokenAmount

// Sum of space occupied by active verified deals at end of last epoch.
TotalVerifiedSpace abi.StoragePower
// Queue of deltas to total verified space in the current or future epochs.
// The sum of TotalVerifiedSpace plus all deltas should equal zero, never dipping below zero in the interim.
TotalVerifiedSpaceDeltas cid.Cid // AMT[epoch]big.Int
// Recent history of past total verified space and verified reward received
VerifiedRewardsHistory cid.Cid // AMT[epoch]VerifiedDealTotals
// Provider verified deal claims
ProviderVerifiedClaims cid.Cid // HAMT[actorID]{...}
}

func ConstructState(store adt.Store) (*State, error) {
Expand All @@ -85,6 +98,19 @@ func ConstructState(store adt.Store) (*State, error) {
return nil, xerrors.Errorf("failed to create empty balance table: %w", err)
}

emptyStoragePowerDeltaQueueCid, err := adt.StoreEmptyArray(store, StoragePowerDeltaQueueAmtBitwidth)
if err != nil {
return nil, xerrors.Errorf("failed to create empty array: %w", err)
}
emptyVerifiedRewardsHistoryCid, err := adt.StoreEmptyArray(store, VerifiedRewardsHistoryAmtBitwidth)
if err != nil {
return nil, xerrors.Errorf("failed to create empty array: %w", err)
}
emptyProviderVerifiedClaimsCid, err := adt.StoreEmptyMap(store, builtin.DefaultHamtBitwidth)
if err != nil {
return nil, xerrors.Errorf("failed to create empty map: %w", err)
}

return &State{
Proposals: emptyProposalsArrayCid,
States: emptyStatesArrayCid,
Expand All @@ -98,6 +124,11 @@ func ConstructState(store adt.Store) (*State, error) {
TotalClientLockedCollateral: abi.NewTokenAmount(0),
TotalProviderLockedCollateral: abi.NewTokenAmount(0),
TotalClientStorageFee: abi.NewTokenAmount(0),

TotalVerifiedSpace: big.Zero(),
TotalVerifiedSpaceDeltas: emptyStoragePowerDeltaQueueCid,
VerifiedRewardsHistory: emptyVerifiedRewardsHistoryCid,
ProviderVerifiedClaims: emptyProviderVerifiedClaimsCid,
}, nil
}

Expand Down Expand Up @@ -297,6 +328,12 @@ type marketStateMutation struct {
totalClientStorageFee abi.TokenAmount

nextDealId abi.DealID

verifiedPermit MarketStateMutationPermission
totalVerifiedSpace abi.StoragePower
totalVerifiedSpaceDeltas *StoragePowerDeltaQueue
verifiedRewardHistory *VerifiedRewardHistory
providerVerifiedClaims *ProviderVerifiedClaims
}

func (s *State) mutator(store adt.Store) *marketStateMutation {
Expand Down Expand Up @@ -355,6 +392,27 @@ func (m *marketStateMutation) build() (*marketStateMutation, error) {
m.dealsByEpoch = dbe
}

if m.verifiedPermit != Invalid {
m.totalVerifiedSpace = m.st.TotalVerifiedSpace
tvsq, err := AsStoragePowerDeltaQueue(m.store, m.st.TotalVerifiedSpaceDeltas)
if err != nil {
return nil, xerrors.Errorf("failed to load verified space deltas: %w", err)
}
m.totalVerifiedSpaceDeltas = tvsq

hvr, err := AsVerifiedRewardHistory(m.store, m.st.VerifiedRewardsHistory)
if err != nil {
return nil, xerrors.Errorf("failed to load historical verified rewards: %w", err)
}
m.verifiedRewardHistory = hvr

pvc, err := AsProviderVerifiedClaims(m.store, m.st.ProviderVerifiedClaims)
if err != nil {
return nil, xerrors.Errorf("failed to load provider verified claims: %w", err)
}
m.providerVerifiedClaims = pvc
}

m.nextDealId = m.st.NextID

return m, nil
Expand Down Expand Up @@ -390,6 +448,11 @@ func (m *marketStateMutation) withDealsByEpoch(permit MarketStateMutationPermiss
return m
}

func (m *marketStateMutation) withVerifiedRewards(permit MarketStateMutationPermission) *marketStateMutation {
m.verifiedPermit = permit
return m
}

func (m *marketStateMutation) commitState() error {
var err error
if m.proposalPermit == WritePermission {
Expand Down Expand Up @@ -431,6 +494,19 @@ func (m *marketStateMutation) commitState() error {
}
}

if m.verifiedPermit == WritePermission {
m.st.TotalVerifiedSpace = m.totalVerifiedSpace
if m.st.TotalVerifiedSpaceDeltas, err = m.totalVerifiedSpaceDeltas.Root(); err != nil {
return xerrors.Errorf("failed to flush verified space deltas: %w", err)
}
if m.st.VerifiedRewardsHistory, err = m.verifiedRewardHistory.Root(); err != nil {
return xerrors.Errorf("failed to flush historical verified rewards: %w", err)
}
if m.st.ProviderVerifiedClaims, err = m.providerVerifiedClaims.Root(); err != nil {
return xerrors.Errorf("failed to flush provider verified claims: %w", err)
}
}

m.st.NextID = m.nextDealId
return nil
}
182 changes: 182 additions & 0 deletions actors/builtin/market/types.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package market

import (
"io"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
. "github.com/filecoin-project/specs-actors/v8/actors/util/adt"
"golang.org/x/xerrors"

"github.com/ipfs/go-cid"
)

///// Deal proposal array /////

// A specialization of a array to deals.
// It is an error to query for a key that doesn't exist.
type DealArray struct {
Expand Down Expand Up @@ -42,6 +49,8 @@ func (t *DealArray) Delete(id abi.DealID) error {
return t.Array.Delete(uint64(id))
}

///// Deal state array /////

// A specialization of a array to deals.
// It is an error to query for a key that doesn't exist.
type DealMetaArray struct {
Expand Down Expand Up @@ -93,3 +102,176 @@ func (t *DealMetaArray) Set(k abi.DealID, value *DealState) error {
func (t *DealMetaArray) Delete(id abi.DealID) error {
return t.Array.Delete(uint64(id))
}

///// Provider verified claims map /////

// A specialization of a map to provider verified claims.
// It is an error to query for a key that doesn't exist.
type ProviderVerifiedClaims struct {
*Map
}

type ProviderVerifiedClaim struct {
// The epoch until which rewards were last processed for the provider.
LastClaimEpoch abi.ChainEpoch
// The provider's active verified deal space at the end of LastClaimEpoch.
VerifiedDealSpace abi.StoragePower
// Events since LastClaimEpoch, keyed by epoch.
DeltaQueue cid.Cid // AMT[epoch]big.Int
}

// Interprets a store as a provider verified claims map with root `r`.
func AsProviderVerifiedClaims(s Store, r cid.Cid) (*ProviderVerifiedClaims, error) {
pvc, err := AsMap(s, r, ProviderVerifiedClaimsHamtBitwidth)
if err != nil {
return nil, err
}
return &ProviderVerifiedClaims{pvc}, nil
}

func (pvc *ProviderVerifiedClaims) Add(s Store, provider address.Address, epoch abi.ChainEpoch, size abi.StoragePower) error {
var providerClaim ProviderVerifiedClaim
if found, err := pvc.Get(abi.AddrKey(provider), &providerClaim); err != nil {
return err
} else if !found {
return xerrors.Errorf("no verified claim entry for %v", provider)
}
deltaQueue, err := AsStoragePowerDeltaQueue(s, providerClaim.DeltaQueue)
if err != nil {
return err
}

if err = deltaQueue.Add(epoch, size); err != nil {
return err
}
if providerClaim.DeltaQueue, err = deltaQueue.Root(); err != nil {
return err
}
if err = pvc.Put(abi.AddrKey(provider), &providerClaim); err != nil {
return err
}
return nil
}

///// Provider event queue array /////

// A provider event queue is an ordered collection of events keyed by epoch, implemented as an AMT with
// array values (supporting multiple events at one epoch).
// An array value will be efficient while the number of events per epoch is small, or written in batch.
type ProviderEventQueue struct {
*Array
}

//type ProviderEventQueueEntry struct {
// Events []VerifiedDealEvent
//}
//
//type VerifiedDealEvent struct {
// EventType VerifiedDealEventType
// VerifiedSpace abi.StoragePower
//}
//
//// Interprets a store as a provider event queue with root `r`.
//func AsProviderEventQueue(s Store, r cid.Cid) (*ProviderEventQueue, error) {
// array, err := AsArray(s, r, ProviderEventQueueAmtBitwidth)
// if err != nil {
// return nil, err
// }
// return &ProviderEventQueue{array}, nil
//}
//
//func (q *ProviderEventQueue) Enqueue(epoch abi.ChainEpoch, eventType VerifiedDealEventType, size abi.StoragePower) error {
// var queueEntry ProviderEventQueueEntry
// _, err := q.Get(uint64(epoch), &queueEntry)
// if err != nil {
// return err
// }
//
// queueEntry.Events = append(queueEntry.Events, VerifiedDealEvent{
// EventType: eventType,
// VerifiedSpace: size,
// })
//
// if err := q.Set(uint64(epoch), &queueEntry); err != nil {
// return err
// }
// return nil
//}

///// Storage power delta queue array /////

type StoragePowerDeltaQueue struct {
*Array
}

// Interprets a store as a queue with root `r`.
func AsStoragePowerDeltaQueue(s Store, r cid.Cid) (*StoragePowerDeltaQueue, error) {
array, err := AsArray(s, r, StoragePowerDeltaQueueAmtBitwidth)
if err != nil {
return nil, err
}
return &StoragePowerDeltaQueue{array}, nil
}

// Adds `size` to the entry at `epoch`. The entry is taken to be zero if absent.
func (q *StoragePowerDeltaQueue) Add(epoch abi.ChainEpoch, size abi.StoragePower) error {
queueEntry := big.Zero()
_, err := q.Get(uint64(epoch), &queueEntry)
if err != nil {
return err
}

queueEntry = big.Add(queueEntry, size)

if err := q.Set(uint64(epoch), &queueEntry); err != nil {
return err
}
return nil
}

///// Verified reward history array ///

type VerifiedRewardHistory struct {
*Array
}

type VerifiedRewardHistoryEntry struct {
TotalVerifiedSpace abi.StoragePower
TotalReward abi.TokenAmount
}

func AsVerifiedRewardHistory(s Store, r cid.Cid) (*VerifiedRewardHistory, error) {
array, err := AsArray(s, r, VerifiedRewardsHistoryAmtBitwidth)
if err != nil {
return nil, err
}
return &VerifiedRewardHistory{array}, nil
}

func (a *VerifiedRewardHistory) Set(epoch abi.ChainEpoch, totalVerifiedSpace abi.StoragePower, totalReward abi.TokenAmount) error {
value := VerifiedRewardHistoryEntry{
TotalVerifiedSpace: totalVerifiedSpace,
TotalReward: totalReward,
}
return a.Array.Set(uint64(epoch), &value)
}

//func (p ProviderEventQueueEntry) MarshalCBOR(w io.Writer) error {
// panic("implement me") // FIXME
//}
//
//func (p ProviderEventQueueEntry) UnmarshalCBOR(r io.Reader) error {
// panic("implement me") // FIXME
//}

func (p ProviderVerifiedClaim) UnmarshalCBOR(r io.Reader) error {
panic("implement me") // FIXME
}

func (p ProviderVerifiedClaim) MarshalCBOR(w io.Writer) error {
panic("implement me") // FIXME
}

func (v VerifiedRewardHistoryEntry) MarshalCBOR(w io.Writer) error {
panic("implement me") // FIXME
}
Loading