package market import ( "github.com/ipfs/go-cid" actorstypes "github.com/filecoin-project/go-state-types/actors" "unicode/utf8" "github.com/filecoin-project/go-state-types/network" "golang.org/x/xerrors" "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/go-state-types/cbor" cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/go-state-types/manifest" markettypes "github.com/filecoin-project/go-state-types/builtin/v9/market" verifregtypes "github.com/filecoin-project/go-state-types/builtin/v9/verifreg" {{range .versions}} {{if (le . 7)}} builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin" {{end}} {{end}} builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" ) var ( Address = builtintypes.StorageMarketActorAddr Methods = builtintypes.MethodsMarket ) func Load(store adt.Store, act *types.Actor) (State, error) { if name, av, ok := actors.GetActorMetaByCode(act.Code); ok { if name != manifest.MarketKey { return nil, xerrors.Errorf("actor code is not market: %s", name) } switch av { {{range .versions}} {{if (ge . 8)}} case actorstypes.Version{{.}}: return load{{.}}(store, act.Head) {{end}} {{end}} } } switch act.Code { {{range .versions}} {{if (le . 7)}} case builtin{{.}}.StorageMarketActorCodeID: return load{{.}}(store, act.Head) {{end}} {{end}} } return nil, xerrors.Errorf("unknown actor code %s", act.Code) } func MakeState(store adt.Store, av actorstypes.Version) (State, error) { switch av { {{range .versions}} case actorstypes.Version{{.}}: return make{{.}}(store) {{end}} } return nil, xerrors.Errorf("unknown actor version %d", av) } type State interface { cbor.Marshaler Code() cid.Cid ActorKey() string ActorVersion() actorstypes.Version BalancesChanged(State) (bool, error) EscrowTable() (BalanceTable, error) LockedTable() (BalanceTable, error) TotalLocked() (abi.TokenAmount, error) StatesChanged(State) (bool, error) States() (DealStates, error) ProposalsChanged(State) (bool, error) Proposals() (DealProposals, error) VerifyDealsForActivation( minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch, ) (weight, verifiedWeight abi.DealWeight, err error) NextID() (abi.DealID, error) GetState() interface{} GetAllocationIdForPendingDeal(dealId abi.DealID) (verifregtypes.AllocationId, error) } type BalanceTable interface { ForEach(cb func(address.Address, abi.TokenAmount) error) error Get(key address.Address) (abi.TokenAmount, error) } type DealStates interface { ForEach(cb func(id abi.DealID, ds DealState) error) error Get(id abi.DealID) (DealState, bool, error) array() adt.Array decode(*cbg.Deferred) (DealState, error) } type DealProposals interface { ForEach(cb func(id abi.DealID, dp markettypes.DealProposal) error) error Get(id abi.DealID) (*markettypes.DealProposal, bool, error) array() adt.Array decode(*cbg.Deferred) (*markettypes.DealProposal, error) } type PublishStorageDealsReturn interface { DealIDs() ([]abi.DealID, error) // Note that this index is based on the batch of deals that were published, NOT the DealID IsDealValid(index uint64) (bool, int, error) } func DecodePublishStorageDealsReturn(b []byte, nv network.Version) (PublishStorageDealsReturn, error) { av, err := actorstypes.VersionForNetwork(nv) if err != nil { return nil, err } switch av { {{range .versions}} case actorstypes.Version{{.}}: return decodePublishStorageDealsReturn{{.}}(b) {{end}} } return nil, xerrors.Errorf("unknown actor version %d", av) } type DealProposal = markettypes.DealProposal type DealLabel = markettypes.DealLabel type DealState interface { SectorStartEpoch() abi.ChainEpoch // -1 if not yet included in proven sector LastUpdatedEpoch() abi.ChainEpoch // -1 if deal state never updated SlashEpoch() abi.ChainEpoch // -1 if deal never slashed Equals(other DealState) bool } func DealStatesEqual(a, b DealState) bool { return DealStatesEqual(a, b) } type DealStateChanges struct { Added []DealIDState Modified []DealStateChange Removed []DealIDState } type DealIDState struct { ID abi.DealID Deal DealState } // DealStateChange is a change in deal state from -> to type DealStateChange struct { ID abi.DealID From DealState To DealState } type DealProposalChanges struct { Added []ProposalIDState Removed []ProposalIDState } type ProposalIDState struct { ID abi.DealID Proposal markettypes.DealProposal } type emptyDealState struct{} func (e *emptyDealState) SectorStartEpoch() abi.ChainEpoch { return -1 } func (e *emptyDealState) LastUpdatedEpoch() abi.ChainEpoch { return -1 } func (e *emptyDealState) SlashEpoch() abi.ChainEpoch { return -1 } func (e *emptyDealState) Equals(other DealState) bool { if e.SectorStartEpoch() != other.SectorStartEpoch() { return false } if e.LastUpdatedEpoch() != other.LastUpdatedEpoch() { return false } if e.SlashEpoch() != other.SlashEpoch() { return false } return true } func EmptyDealState() DealState { return &emptyDealState{} } // returns the earned fees and pending fees for a given deal func GetDealFees(deal markettypes.DealProposal, height abi.ChainEpoch) (abi.TokenAmount, abi.TokenAmount) { tf := big.Mul(deal.StoragePricePerEpoch, big.NewInt(int64(deal.EndEpoch-deal.StartEpoch))) ef := big.Mul(deal.StoragePricePerEpoch, big.NewInt(int64(height-deal.StartEpoch))) if ef.LessThan(big.Zero()) { ef = big.Zero() } if ef.GreaterThan(tf) { ef = tf } return ef, big.Sub(tf, ef) } func IsDealActive(state DealState) bool { return state.SectorStartEpoch() > -1 && state.SlashEpoch() == -1 } func labelFromGoString(s string) (markettypes.DealLabel, error) { if utf8.ValidString(s) { return markettypes.NewLabelFromString(s) } else { return markettypes.NewLabelFromBytes([]byte(s)) } } func AllCodes() []cid.Cid { return []cid.Cid{ {{range .versions}} (&state{{.}}{}).Code(), {{- end}} } }