feat(market): update state diffing for market actor

Update to abstract actor for markets state diffing. Also move the diff adt functions inside the
abstract actors
This commit is contained in:
hannahhoward 2020-09-16 19:13:12 -07:00
parent 7115485b0a
commit 80b6994fe2
7 changed files with 373 additions and 215 deletions

View File

@ -1,10 +1,9 @@
package state package adt
import ( import (
"bytes" "bytes"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/util/adt"
typegen "github.com/whyrusleeping/cbor-gen" typegen "github.com/whyrusleeping/cbor-gen"
) )
@ -27,7 +26,7 @@ type AdtArrayDiff interface {
// - All values that exist in curArr nnd not in prevArr are passed to adtArrayDiff.Add() // - All values that exist in curArr nnd not in prevArr are passed to adtArrayDiff.Add()
// - All values that exist in preArr and in curArr are passed to AdtArrayDiff.Modify() // - All values that exist in preArr and in curArr are passed to AdtArrayDiff.Modify()
// - It is the responsibility of AdtArrayDiff.Modify() to determine if the values it was passed have been modified. // - It is the responsibility of AdtArrayDiff.Modify() to determine if the values it was passed have been modified.
func DiffAdtArray(preArr, curArr *adt.Array, out AdtArrayDiff) error { func DiffAdtArray(preArr, curArr Array, out AdtArrayDiff) error {
prevVal := new(typegen.Deferred) prevVal := new(typegen.Deferred)
if err := preArr.ForEach(prevVal, func(i int64) error { if err := preArr.ForEach(prevVal, func(i int64) error {
curVal := new(typegen.Deferred) curVal := new(typegen.Deferred)
@ -76,7 +75,7 @@ type AdtMapDiff interface {
Remove(key string, val *typegen.Deferred) error Remove(key string, val *typegen.Deferred) error
} }
func DiffAdtMap(preMap, curMap *adt.Map, out AdtMapDiff) error { func DiffAdtMap(preMap, curMap Map, out AdtMapDiff) error {
prevVal := new(typegen.Deferred) prevVal := new(typegen.Deferred)
if err := preMap.ForEach(prevVal, func(key string) error { if err := preMap.ForEach(prevVal, func(key string) error {
curVal := new(typegen.Deferred) curVal := new(typegen.Deferred)

View File

@ -1,4 +1,4 @@
package state package adt
import ( import (
"bytes" "bytes"
@ -13,7 +13,7 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/runtime" "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/util/adt" v0adt "github.com/filecoin-project/specs-actors/actors/util/adt"
bstore "github.com/filecoin-project/lotus/lib/blockstore" bstore "github.com/filecoin-project/lotus/lib/blockstore"
) )
@ -22,8 +22,8 @@ func TestDiffAdtArray(t *testing.T) {
ctxstoreA := newContextStore() ctxstoreA := newContextStore()
ctxstoreB := newContextStore() ctxstoreB := newContextStore()
arrA := adt.MakeEmptyArray(ctxstoreA) arrA := v0adt.MakeEmptyArray(ctxstoreA)
arrB := adt.MakeEmptyArray(ctxstoreB) arrB := v0adt.MakeEmptyArray(ctxstoreB)
require.NoError(t, arrA.Set(0, runtime.CBORBytes([]byte{0}))) // delete require.NoError(t, arrA.Set(0, runtime.CBORBytes([]byte{0}))) // delete
@ -76,8 +76,8 @@ func TestDiffAdtMap(t *testing.T) {
ctxstoreA := newContextStore() ctxstoreA := newContextStore()
ctxstoreB := newContextStore() ctxstoreB := newContextStore()
mapA := adt.MakeEmptyMap(ctxstoreA) mapA := v0adt.MakeEmptyMap(ctxstoreA)
mapB := adt.MakeEmptyMap(ctxstoreB) mapB := v0adt.MakeEmptyMap(ctxstoreB)
require.NoError(t, mapA.Put(abi.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete require.NoError(t, mapA.Put(abi.UIntKey(0), runtime.CBORBytes([]byte{0}))) // delete
@ -292,12 +292,9 @@ func (t *TestDiffArray) Remove(key uint64, val *typegen.Deferred) error {
return nil return nil
} }
func newContextStore() *contextStore { func newContextStore() Store {
ctx := context.Background() ctx := context.Background()
bs := bstore.NewTemporarySync() bs := bstore.NewTemporarySync()
store := cbornode.NewCborStore(bs) store := cbornode.NewCborStore(bs)
return &contextStore{ return WrapStore(ctx, store)
ctx: ctx,
cst: store,
}
} }

View File

@ -29,9 +29,14 @@ func Load(store adt.Store, act *types.Actor) (st State, err error) {
type State interface { type State interface {
cbor.Marshaler cbor.Marshaler
BalancesChanged(State) bool
EscrowTable() (BalanceTable, error) EscrowTable() (BalanceTable, error)
LockedTable() (BalanceTable, error) LockedTable() (BalanceTable, error)
TotalLocked() (abi.TokenAmount, error) TotalLocked() (abi.TokenAmount, error)
StatesChanged(State) bool
States() (DealStates, error)
ProposalsChanged(State) bool
Proposals() (DealProposals, error)
VerifyDealsForActivation( VerifyDealsForActivation(
minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch, minerAddr address.Address, deals []abi.DealID, currEpoch, sectorExpiry abi.ChainEpoch,
) (weight, verifiedWeight abi.DealWeight, err error) ) (weight, verifiedWeight abi.DealWeight, err error)
@ -40,3 +45,50 @@ type State interface {
type BalanceTable interface { type BalanceTable interface {
Get(key address.Address) (abi.TokenAmount, error) Get(key address.Address) (abi.TokenAmount, error)
} }
type DealStates interface {
GetDeal(key abi.DealID) (DealState, error)
Diff(DealStates) (*DealStateChanges, error)
}
type DealProposals interface {
Diff(DealProposals) (*DealProposalChanges, error)
}
type DealState interface {
SectorStartEpoch() abi.ChainEpoch
SlashEpoch() abi.ChainEpoch
LastUpdatedEpoch() abi.ChainEpoch
Equals(DealState) bool
}
type DealProposal interface {
}
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 DealProposal
}

View File

@ -1,11 +1,17 @@
package market package market
import ( import (
"bytes"
"errors"
"fmt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/util/adt" v0adt "github.com/filecoin-project/specs-actors/actors/util/adt"
typegen "github.com/whyrusleeping/cbor-gen"
) )
type v0State struct { type v0State struct {
@ -19,12 +25,58 @@ func (s *v0State) TotalLocked() (abi.TokenAmount, error) {
return fml, nil return fml, nil
} }
func (s *v0State) BalancesChanged(otherState State) bool {
v0otherState, ok := otherState.(*v0State)
if !ok {
// there's no way to compare differnt versions of the state, so let's
// just say that means the state of balances has changed
return true
}
return !s.State.EscrowTable.Equals(v0otherState.State.EscrowTable) || !s.State.LockedTable.Equals(v0otherState.State.LockedTable)
}
func (s *v0State) StatesChanged(otherState State) bool {
v0otherState, ok := otherState.(*v0State)
if !ok {
// there's no way to compare differnt versions of the state, so let's
// just say that means the state of balances has changed
return true
}
return !s.State.States.Equals(v0otherState.State.States)
}
func (s *v0State) States() (DealStates, error) {
stateArray, err := v0adt.AsArray(s.store, s.State.States)
if err != nil {
return nil, err
}
return &v0DealStates{stateArray}, nil
}
func (s *v0State) ProposalsChanged(otherState State) bool {
v0otherState, ok := otherState.(*v0State)
if !ok {
// there's no way to compare differnt versions of the state, so let's
// just say that means the state of balances has changed
return true
}
return !s.State.Proposals.Equals(v0otherState.State.Proposals)
}
func (s *v0State) Proposals() (DealProposals, error) {
proposalArray, err := v0adt.AsArray(s.store, s.State.Proposals)
if err != nil {
return nil, err
}
return &v0DealProposals{proposalArray}, nil
}
func (s *v0State) EscrowTable() (BalanceTable, error) { func (s *v0State) EscrowTable() (BalanceTable, error) {
return adt.AsBalanceTable(s.store, s.State.EscrowTable) return v0adt.AsBalanceTable(s.store, s.State.EscrowTable)
} }
func (s *v0State) LockedTable() (BalanceTable, error) { func (s *v0State) LockedTable() (BalanceTable, error) {
return adt.AsBalanceTable(s.store, s.State.LockedTable) return v0adt.AsBalanceTable(s.store, s.State.LockedTable)
} }
func (s *v0State) VerifyDealsForActivation( func (s *v0State) VerifyDealsForActivation(
@ -32,3 +84,146 @@ func (s *v0State) VerifyDealsForActivation(
) (weight, verifiedWeight abi.DealWeight, err error) { ) (weight, verifiedWeight abi.DealWeight, err error) {
return market.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch) return market.ValidateDealsForActivation(&s.State, s.store, deals, minerAddr, sectorExpiry, currEpoch)
} }
type v0DealStates struct {
adt.Array
}
func (s *v0DealStates) GetDeal(dealID abi.DealID) (DealState, error) {
var deal market.DealState
found, err := s.Array.Get(uint64(dealID), &deal)
if err != nil {
return nil, err
}
if !found {
return nil, nil
}
return &v0DealState{deal}, nil
}
func (s *v0DealStates) Diff(other DealStates) (*DealStateChanges, error) {
v0other, ok := other.(*v0DealStates)
if !ok {
// TODO handle this if possible on a case by case basis but for now, just fail
return nil, errors.New("cannot compare deal states across versions")
}
results := new(DealStateChanges)
if err := adt.DiffAdtArray(s, v0other, &v0MarketStatesDiffer{results}); err != nil {
return nil, fmt.Errorf("diffing deal states: %w", err)
}
return results, nil
}
type v0MarketStatesDiffer struct {
Results *DealStateChanges
}
func (d *v0MarketStatesDiffer) Add(key uint64, val *typegen.Deferred) error {
ds := new(v0DealState)
err := ds.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
d.Results.Added = append(d.Results.Added, DealIDState{abi.DealID(key), ds})
return nil
}
func (d *v0MarketStatesDiffer) Modify(key uint64, from, to *typegen.Deferred) error {
dsFrom := new(v0DealState)
if err := dsFrom.UnmarshalCBOR(bytes.NewReader(from.Raw)); err != nil {
return err
}
dsTo := new(v0DealState)
if err := dsTo.UnmarshalCBOR(bytes.NewReader(to.Raw)); err != nil {
return err
}
if *dsFrom != *dsTo {
d.Results.Modified = append(d.Results.Modified, DealStateChange{abi.DealID(key), dsFrom, dsTo})
}
return nil
}
func (d *v0MarketStatesDiffer) Remove(key uint64, val *typegen.Deferred) error {
ds := new(v0DealState)
err := ds.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
d.Results.Removed = append(d.Results.Removed, DealIDState{abi.DealID(key), ds})
return nil
}
type v0DealState struct {
market.DealState
}
func (ds *v0DealState) SectorStartEpoch() abi.ChainEpoch {
return ds.DealState.SectorStartEpoch
}
func (ds *v0DealState) SlashEpoch() abi.ChainEpoch {
return ds.DealState.SlashEpoch
}
func (ds *v0DealState) LastUpdatedEpoch() abi.ChainEpoch {
return ds.DealState.LastUpdatedEpoch
}
func (ds *v0DealState) Equals(other DealState) bool {
v0other, ok := other.(*v0DealState)
return ok && *ds == *v0other
}
type v0DealProposals struct {
adt.Array
}
func (s *v0DealProposals) Diff(other DealProposals) (*DealProposalChanges, error) {
v0other, ok := other.(*v0DealProposals)
if !ok {
// TODO handle this if possible on a case by case basis but for now, just fail
return nil, errors.New("cannot compare deal proposals across versions")
}
results := new(DealProposalChanges)
if err := adt.DiffAdtArray(s, v0other, &v0MarketProposalsDiffer{results}); err != nil {
return nil, fmt.Errorf("diffing deal proposals: %w", err)
}
return results, nil
}
type v0MarketProposalsDiffer struct {
Results *DealProposalChanges
}
type v0DealProposal struct {
market.DealProposal
}
func (d *v0MarketProposalsDiffer) Add(key uint64, val *typegen.Deferred) error {
dp := new(v0DealProposal)
err := dp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
d.Results.Added = append(d.Results.Added, ProposalIDState{abi.DealID(key), dp})
return nil
}
func (d *v0MarketProposalsDiffer) Modify(key uint64, from, to *typegen.Deferred) error {
// short circuit, DealProposals are static
return nil
}
func (d *v0MarketProposalsDiffer) Remove(key uint64, val *typegen.Deferred) error {
dp := new(v0DealProposal)
err := dp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
d.Results.Removed = append(d.Results.Removed, ProposalIDState{abi.DealID(key), dp})
return nil
}

View File

@ -7,12 +7,13 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych" "github.com/filecoin-project/lotus/chain/actors/builtin/paych"
"github.com/filecoin-project/specs-actors/actors/builtin" "github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt" v0adt "github.com/filecoin-project/specs-actors/actors/util/adt"
cbor "github.com/ipfs/go-ipld-cbor" cbor "github.com/ipfs/go-ipld-cbor"
typegen "github.com/whyrusleeping/cbor-gen" typegen "github.com/whyrusleeping/cbor-gen"
@ -69,26 +70,26 @@ func (sp *StatePredicates) OnActorStateChanged(addr address.Address, diffStateFu
} }
} }
type DiffStorageMarketStateFunc func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) type DiffStorageMarketStateFunc func(ctx context.Context, oldState market.State, newState market.State) (changed bool, user UserData, err error)
// OnStorageMarketActorChanged calls diffStorageMarketState when the state changes for the market actor // OnStorageMarketActorChanged calls diffStorageMarketState when the state changes for the market actor
func (sp *StatePredicates) OnStorageMarketActorChanged(diffStorageMarketState DiffStorageMarketStateFunc) DiffTipSetKeyFunc { func (sp *StatePredicates) OnStorageMarketActorChanged(diffStorageMarketState DiffStorageMarketStateFunc) DiffTipSetKeyFunc {
return sp.OnActorStateChanged(builtin.StorageMarketActorAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) { return sp.OnActorStateChanged(builtin.StorageMarketActorAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
var oldState market.State oldState, err := market.Load(adt.WrapStore(ctx, sp.cst), oldActorState)
if err := sp.cst.Get(ctx, oldActorState.Head, &oldState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
var newState market.State newState, err := market.Load(adt.WrapStore(ctx, sp.cst), newActorState)
if err := sp.cst.Get(ctx, newActorState.Head, &newState); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
return diffStorageMarketState(ctx, &oldState, &newState) return diffStorageMarketState(ctx, oldState, newState)
}) })
} }
type BalanceTables struct { type BalanceTables struct {
EscrowTable *adt.BalanceTable EscrowTable market.BalanceTable
LockedTable *adt.BalanceTable LockedTable market.BalanceTable
} }
// DiffBalanceTablesFunc compares two balance tables // DiffBalanceTablesFunc compares two balance tables
@ -96,32 +97,27 @@ type DiffBalanceTablesFunc func(ctx context.Context, oldBalanceTable, newBalance
// OnBalanceChanged runs when the escrow table for available balances changes // OnBalanceChanged runs when the escrow table for available balances changes
func (sp *StatePredicates) OnBalanceChanged(diffBalances DiffBalanceTablesFunc) DiffStorageMarketStateFunc { func (sp *StatePredicates) OnBalanceChanged(diffBalances DiffBalanceTablesFunc) DiffStorageMarketStateFunc {
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState market.State, newState market.State) (changed bool, user UserData, err error) {
if oldState.EscrowTable.Equals(newState.EscrowTable) && oldState.LockedTable.Equals(newState.LockedTable) { if !oldState.BalancesChanged(newState) {
return false, nil, nil return false, nil, nil
} }
ctxStore := &contextStore{ oldEscrowRoot, err := oldState.EscrowTable()
ctx: ctx,
cst: sp.cst,
}
oldEscrowRoot, err := adt.AsBalanceTable(ctxStore, oldState.EscrowTable)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
oldLockedRoot, err := adt.AsBalanceTable(ctxStore, oldState.LockedTable) oldLockedRoot, err := oldState.LockedTable()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newEscrowRoot, err := adt.AsBalanceTable(ctxStore, newState.EscrowTable) newEscrowRoot, err := newState.EscrowTable()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newLockedRoot, err := adt.AsBalanceTable(ctxStore, newState.LockedTable) newLockedRoot, err := newState.LockedTable()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -130,25 +126,22 @@ func (sp *StatePredicates) OnBalanceChanged(diffBalances DiffBalanceTablesFunc)
} }
} }
type DiffAdtArraysFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot *adt.Array) (changed bool, user UserData, err error) type DiffDealStatesFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot market.DealStates) (changed bool, user UserData, err error)
type DiffDealProposalsFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot market.DealProposals) (changed bool, user UserData, err error)
type DiffAdtArraysFunc func(ctx context.Context, oldDealStateRoot, newDealStateRoot adt.Array) (changed bool, user UserData, err error)
// OnDealStateChanged calls diffDealStates when the market deal state changes // OnDealStateChanged calls diffDealStates when the market deal state changes
func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffAdtArraysFunc) DiffStorageMarketStateFunc { func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffDealStatesFunc) DiffStorageMarketStateFunc {
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState market.State, newState market.State) (changed bool, user UserData, err error) {
if oldState.States.Equals(newState.States) { if !oldState.StatesChanged(newState) {
return false, nil, nil return false, nil, nil
} }
ctxStore := &contextStore{ oldRoot, err := oldState.States()
ctx: ctx,
cst: sp.cst,
}
oldRoot, err := adt.AsArray(ctxStore, oldState.States)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newRoot, err := adt.AsArray(ctxStore, newState.States) newRoot, err := newState.States()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -158,22 +151,17 @@ func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffAdtArraysFunc)
} }
// OnDealProposalChanged calls diffDealProps when the market proposal state changes // OnDealProposalChanged calls diffDealProps when the market proposal state changes
func (sp *StatePredicates) OnDealProposalChanged(diffDealProps DiffAdtArraysFunc) DiffStorageMarketStateFunc { func (sp *StatePredicates) OnDealProposalChanged(diffDealProps DiffDealProposalsFunc) DiffStorageMarketStateFunc {
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) { return func(ctx context.Context, oldState market.State, newState market.State) (changed bool, user UserData, err error) {
if oldState.Proposals.Equals(newState.Proposals) { if !oldState.ProposalsChanged(newState) {
return false, nil, nil return false, nil, nil
} }
ctxStore := &contextStore{ oldRoot, err := oldState.Proposals()
ctx: ctx,
cst: sp.cst,
}
oldRoot, err := adt.AsArray(ctxStore, oldState.Proposals)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newRoot, err := adt.AsArray(ctxStore, newState.Proposals) newRoot, err := newState.Proposals()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -182,51 +170,14 @@ func (sp *StatePredicates) OnDealProposalChanged(diffDealProps DiffAdtArraysFunc
} }
} }
var _ AdtArrayDiff = &MarketDealProposalChanges{}
type MarketDealProposalChanges struct {
Added []ProposalIDState
Removed []ProposalIDState
}
type ProposalIDState struct {
ID abi.DealID
Proposal market.DealProposal
}
func (m *MarketDealProposalChanges) Add(key uint64, val *typegen.Deferred) error {
dp := new(market.DealProposal)
err := dp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, ProposalIDState{abi.DealID(key), *dp})
return nil
}
func (m *MarketDealProposalChanges) Modify(key uint64, from, to *typegen.Deferred) error {
// short circuit, DealProposals are static
return nil
}
func (m *MarketDealProposalChanges) Remove(key uint64, val *typegen.Deferred) error {
dp := new(market.DealProposal)
err := dp.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, ProposalIDState{abi.DealID(key), *dp})
return nil
}
// OnDealProposalAmtChanged detects changes in the deal proposal AMT for all deal proposals and returns a MarketProposalsChanges structure containing: // OnDealProposalAmtChanged detects changes in the deal proposal AMT for all deal proposals and returns a MarketProposalsChanges structure containing:
// - Added Proposals // - Added Proposals
// - Modified Proposals // - Modified Proposals
// - Removed Proposals // - Removed Proposals
func (sp *StatePredicates) OnDealProposalAmtChanged() DiffAdtArraysFunc { func (sp *StatePredicates) OnDealProposalAmtChanged() DiffDealProposalsFunc {
return func(ctx context.Context, oldDealProps, newDealProps *adt.Array) (changed bool, user UserData, err error) { return func(ctx context.Context, oldDealProps, newDealProps market.DealProposals) (changed bool, user UserData, err error) {
proposalChanges := new(MarketDealProposalChanges) proposalChanges, err := oldDealProps.Diff(newDealProps)
if err := DiffAdtArray(oldDealProps, newDealProps, proposalChanges); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -238,64 +189,14 @@ func (sp *StatePredicates) OnDealProposalAmtChanged() DiffAdtArraysFunc {
} }
} }
var _ AdtArrayDiff = &MarketDealStateChanges{}
type MarketDealStateChanges struct {
Added []DealIDState
Modified []DealStateChange
Removed []DealIDState
}
type DealIDState struct {
ID abi.DealID
Deal market.DealState
}
func (m *MarketDealStateChanges) Add(key uint64, val *typegen.Deferred) error {
ds := new(market.DealState)
err := ds.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Added = append(m.Added, DealIDState{abi.DealID(key), *ds})
return nil
}
func (m *MarketDealStateChanges) Modify(key uint64, from, to *typegen.Deferred) error {
dsFrom := new(market.DealState)
if err := dsFrom.UnmarshalCBOR(bytes.NewReader(from.Raw)); err != nil {
return err
}
dsTo := new(market.DealState)
if err := dsTo.UnmarshalCBOR(bytes.NewReader(to.Raw)); err != nil {
return err
}
if *dsFrom != *dsTo {
m.Modified = append(m.Modified, DealStateChange{abi.DealID(key), dsFrom, dsTo})
}
return nil
}
func (m *MarketDealStateChanges) Remove(key uint64, val *typegen.Deferred) error {
ds := new(market.DealState)
err := ds.UnmarshalCBOR(bytes.NewReader(val.Raw))
if err != nil {
return err
}
m.Removed = append(m.Removed, DealIDState{abi.DealID(key), *ds})
return nil
}
// OnDealStateAmtChanged detects changes in the deal state AMT for all deal states and returns a MarketDealStateChanges structure containing: // OnDealStateAmtChanged detects changes in the deal state AMT for all deal states and returns a MarketDealStateChanges structure containing:
// - Added Deals // - Added Deals
// - Modified Deals // - Modified Deals
// - Removed Deals // - Removed Deals
func (sp *StatePredicates) OnDealStateAmtChanged() DiffAdtArraysFunc { func (sp *StatePredicates) OnDealStateAmtChanged() DiffDealStatesFunc {
return func(ctx context.Context, oldDealStates, newDealStates *adt.Array) (changed bool, user UserData, err error) { return func(ctx context.Context, oldDealStates, newDealStates market.DealStates) (changed bool, user UserData, err error) {
dealStateChanges := new(MarketDealStateChanges) dealStateChanges, err := oldDealStates.Diff(newDealStates)
if err := DiffAdtArray(oldDealStates, newDealStates, dealStateChanges); err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -313,37 +214,31 @@ type ChangedDeals map[abi.DealID]DealStateChange
// DealStateChange is a change in deal state from -> to // DealStateChange is a change in deal state from -> to
type DealStateChange struct { type DealStateChange struct {
ID abi.DealID ID abi.DealID
From *market.DealState From market.DealState
To *market.DealState To market.DealState
} }
// DealStateChangedForIDs detects changes in the deal state AMT for the given deal IDs // DealStateChangedForIDs detects changes in the deal state AMT for the given deal IDs
func (sp *StatePredicates) DealStateChangedForIDs(dealIds []abi.DealID) DiffAdtArraysFunc { func (sp *StatePredicates) DealStateChangedForIDs(dealIds []abi.DealID) DiffDealStatesFunc {
return func(ctx context.Context, oldDealStateArray, newDealStateArray *adt.Array) (changed bool, user UserData, err error) { return func(ctx context.Context, oldDealStates, newDealStates market.DealStates) (changed bool, user UserData, err error) {
changedDeals := make(ChangedDeals) changedDeals := make(ChangedDeals)
for _, dealID := range dealIds { for _, dealID := range dealIds {
var oldDealPtr, newDealPtr *market.DealState
var oldDeal, newDeal market.DealState
// If the deal has been removed, we just set it to nil // If the deal has been removed, we just set it to nil
found, err := oldDealStateArray.Get(uint64(dealID), &oldDeal) oldDeal, err := oldDealStates.GetDeal(dealID)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
if found {
oldDealPtr = &oldDeal
}
found, err = newDealStateArray.Get(uint64(dealID), &newDeal) newDeal, err := newDealStates.GetDeal(dealID)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
if found {
newDealPtr = &newDeal
}
if oldDeal != newDeal { existenceChanged := (oldDeal == nil) != (newDeal == nil)
changedDeals[dealID] = DealStateChange{dealID, oldDealPtr, newDealPtr} valueChanged := (oldDeal != nil && newDeal != nil) && !oldDeal.Equals(newDeal)
if existenceChanged || valueChanged {
changedDeals[dealID] = DealStateChange{dealID, oldDeal, newDeal}
} }
} }
if len(changedDeals) > 0 { if len(changedDeals) > 0 {
@ -441,7 +336,7 @@ type MinerSectorChanges struct {
Removed []miner.SectorOnChainInfo Removed []miner.SectorOnChainInfo
} }
var _ AdtArrayDiff = &MinerSectorChanges{} var _ adt.AdtArrayDiff = &MinerSectorChanges{}
type SectorExtensions struct { type SectorExtensions struct {
From miner.SectorOnChainInfo From miner.SectorOnChainInfo
@ -508,17 +403,17 @@ func (sp *StatePredicates) OnMinerSectorChange() DiffMinerActorStateFunc {
return false, nil, nil return false, nil, nil
} }
oldSectors, err := adt.AsArray(ctxStore, oldState.Sectors) oldSectors, err := v0adt.AsArray(ctxStore, oldState.Sectors)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newSectors, err := adt.AsArray(ctxStore, newState.Sectors) newSectors, err := v0adt.AsArray(ctxStore, newState.Sectors)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
if err := DiffAdtArray(oldSectors, newSectors, sectorChanges); err != nil { if err := adt.DiffAdtArray(oldSectors, newSectors, sectorChanges); err != nil {
return false, nil, err return false, nil, err
} }
@ -584,17 +479,17 @@ func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc {
return false, nil, nil return false, nil, nil
} }
oldPrecommits, err := adt.AsMap(ctxStore, oldState.PreCommittedSectors) oldPrecommits, err := v0adt.AsMap(ctxStore, oldState.PreCommittedSectors)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newPrecommits, err := adt.AsMap(ctxStore, newState.PreCommittedSectors) newPrecommits, err := v0adt.AsMap(ctxStore, newState.PreCommittedSectors)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
if err := DiffAdtMap(oldPrecommits, newPrecommits, precommitChanges); err != nil { if err := adt.DiffAdtMap(oldPrecommits, newPrecommits, precommitChanges); err != nil {
return false, nil, err return false, nil, err
} }
@ -763,17 +658,17 @@ func (sp *StatePredicates) OnAddressMapChange() DiffInitActorStateFunc {
return false, nil, nil return false, nil, nil
} }
oldAddrs, err := adt.AsMap(ctxStore, oldState.AddressMap) oldAddrs, err := v0adt.AsMap(ctxStore, oldState.AddressMap)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
newAddrs, err := adt.AsMap(ctxStore, newState.AddressMap) newAddrs, err := v0adt.AsMap(ctxStore, newState.AddressMap)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
if err := DiffAdtMap(oldAddrs, newAddrs, addressChanges); err != nil { if err := adt.DiffAdtMap(oldAddrs, newAddrs, addressChanges); err != nil {
return false, nil, err return false, nil, err
} }

View File

@ -16,7 +16,10 @@ import (
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/lotus/chain/actors/builtin/market"
v0builtin "github.com/filecoin-project/specs-actors/actors/builtin"
v0market "github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner" "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/specs-actors/actors/util/adt"
tutils "github.com/filecoin-project/specs-actors/support/testing" tutils "github.com/filecoin-project/specs-actors/support/testing"
@ -69,22 +72,22 @@ func TestMarketPredicates(t *testing.T) {
bs := bstore.NewTemporarySync() bs := bstore.NewTemporarySync()
store := adt.WrapStore(ctx, cbornode.NewCborStore(bs)) store := adt.WrapStore(ctx, cbornode.NewCborStore(bs))
oldDeal1 := &market.DealState{ oldDeal1 := &v0market.DealState{
SectorStartEpoch: 1, SectorStartEpoch: 1,
LastUpdatedEpoch: 2, LastUpdatedEpoch: 2,
SlashEpoch: 0, SlashEpoch: 0,
} }
oldDeal2 := &market.DealState{ oldDeal2 := &v0market.DealState{
SectorStartEpoch: 4, SectorStartEpoch: 4,
LastUpdatedEpoch: 5, LastUpdatedEpoch: 5,
SlashEpoch: 0, SlashEpoch: 0,
} }
oldDeals := map[abi.DealID]*market.DealState{ oldDeals := map[abi.DealID]*v0market.DealState{
abi.DealID(1): oldDeal1, abi.DealID(1): oldDeal1,
abi.DealID(2): oldDeal2, abi.DealID(2): oldDeal2,
} }
oldProp1 := &market.DealProposal{ oldProp1 := &v0market.DealProposal{
PieceCID: dummyCid, PieceCID: dummyCid,
PieceSize: 0, PieceSize: 0,
VerifiedDeal: false, VerifiedDeal: false,
@ -96,7 +99,7 @@ func TestMarketPredicates(t *testing.T) {
ProviderCollateral: big.Zero(), ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(), ClientCollateral: big.Zero(),
} }
oldProp2 := &market.DealProposal{ oldProp2 := &v0market.DealProposal{
PieceCID: dummyCid, PieceCID: dummyCid,
PieceSize: 0, PieceSize: 0,
VerifiedDeal: false, VerifiedDeal: false,
@ -108,7 +111,7 @@ func TestMarketPredicates(t *testing.T) {
ProviderCollateral: big.Zero(), ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(), ClientCollateral: big.Zero(),
} }
oldProps := map[abi.DealID]*market.DealProposal{ oldProps := map[abi.DealID]*v0market.DealProposal{
abi.DealID(1): oldProp1, abi.DealID(1): oldProp1,
abi.DealID(2): oldProp2, abi.DealID(2): oldProp2,
} }
@ -122,7 +125,7 @@ func TestMarketPredicates(t *testing.T) {
oldStateC := createMarketState(ctx, t, store, oldDeals, oldProps, oldBalances) oldStateC := createMarketState(ctx, t, store, oldDeals, oldProps, oldBalances)
newDeal1 := &market.DealState{ newDeal1 := &v0market.DealState{
SectorStartEpoch: 1, SectorStartEpoch: 1,
LastUpdatedEpoch: 3, LastUpdatedEpoch: 3,
SlashEpoch: 0, SlashEpoch: 0,
@ -131,19 +134,19 @@ func TestMarketPredicates(t *testing.T) {
// deal 2 removed // deal 2 removed
// added // added
newDeal3 := &market.DealState{ newDeal3 := &v0market.DealState{
SectorStartEpoch: 1, SectorStartEpoch: 1,
LastUpdatedEpoch: 2, LastUpdatedEpoch: 2,
SlashEpoch: 3, SlashEpoch: 3,
} }
newDeals := map[abi.DealID]*market.DealState{ newDeals := map[abi.DealID]*v0market.DealState{
abi.DealID(1): newDeal1, abi.DealID(1): newDeal1,
// deal 2 was removed // deal 2 was removed
abi.DealID(3): newDeal3, abi.DealID(3): newDeal3,
} }
// added // added
newProp3 := &market.DealProposal{ newProp3 := &v0market.DealProposal{
PieceCID: dummyCid, PieceCID: dummyCid,
PieceSize: 0, PieceSize: 0,
VerifiedDeal: false, VerifiedDeal: false,
@ -155,7 +158,7 @@ func TestMarketPredicates(t *testing.T) {
ProviderCollateral: big.Zero(), ProviderCollateral: big.Zero(),
ClientCollateral: big.Zero(), ClientCollateral: big.Zero(),
} }
newProps := map[abi.DealID]*market.DealProposal{ newProps := map[abi.DealID]*v0market.DealProposal{
abi.DealID(1): oldProp1, // 1 was persisted abi.DealID(1): oldProp1, // 1 was persisted
// prop 2 was removed // prop 2 was removed
abi.DealID(3): newProp3, // new abi.DealID(3): newProp3, // new
@ -178,8 +181,8 @@ func TestMarketPredicates(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
api := newMockAPI(bs) api := newMockAPI(bs)
api.setActor(oldState.Key(), &types.Actor{Head: oldStateC}) api.setActor(oldState.Key(), &types.Actor{Code: v0builtin.StorageMarketActorCodeID, Head: oldStateC})
api.setActor(newState.Key(), &types.Actor{Head: newStateC}) api.setActor(newState.Key(), &types.Actor{Code: v0builtin.StorageMarketActorCodeID, Head: newStateC})
t.Run("deal ID predicate", func(t *testing.T) { t.Run("deal ID predicate", func(t *testing.T) {
preds := NewStatePredicates(api) preds := NewStatePredicates(api)
@ -203,11 +206,11 @@ func TestMarketPredicates(t *testing.T) {
require.Contains(t, changedDealIDs, abi.DealID(1)) require.Contains(t, changedDealIDs, abi.DealID(1))
require.Contains(t, changedDealIDs, abi.DealID(2)) require.Contains(t, changedDealIDs, abi.DealID(2))
deal1 := changedDealIDs[abi.DealID(1)] deal1 := changedDealIDs[abi.DealID(1)]
if deal1.From.LastUpdatedEpoch != 2 || deal1.To.LastUpdatedEpoch != 3 { if deal1.From.LastUpdatedEpoch() != 2 || deal1.To.LastUpdatedEpoch() != 3 {
t.Fatal("Unexpected change to LastUpdatedEpoch") t.Fatal("Unexpected change to LastUpdatedEpoch")
} }
deal2 := changedDealIDs[abi.DealID(2)] deal2 := changedDealIDs[abi.DealID(2)]
if deal2.From.LastUpdatedEpoch != 5 || deal2.To != nil { if deal2.From.LastUpdatedEpoch() != 5 || deal2.To != nil {
t.Fatal("Expected To to be nil") t.Fatal("Expected To to be nil")
} }
@ -230,11 +233,17 @@ func TestMarketPredicates(t *testing.T) {
require.False(t, changed) require.False(t, changed)
// Test that OnDealStateChanged does not call the callback if the state has not changed // Test that OnDealStateChanged does not call the callback if the state has not changed
diffDealStateFn := preds.OnDealStateChanged(func(context.Context, *adt.Array, *adt.Array) (bool, UserData, error) { diffDealStateFn := preds.OnDealStateChanged(func(context.Context, market.DealStates, market.DealStates) (bool, UserData, error) {
t.Fatal("No state change so this should not be called") t.Fatal("No state change so this should not be called")
return false, nil, nil return false, nil, nil
}) })
marketState := createEmptyMarketState(t, store) v0marketState := createEmptyMarketState(t, store)
marketCid, err := store.Put(ctx, v0marketState)
require.NoError(t, err)
marketState, err := market.Load(store, &types.Actor{
Code: v0builtin.StorageMarketActorCodeID,
Head: marketCid,
})
changed, _, err = diffDealStateFn(ctx, marketState, marketState) changed, _, err = diffDealStateFn(ctx, marketState, marketState)
require.NoError(t, err) require.NoError(t, err)
require.False(t, changed) require.False(t, changed)
@ -252,18 +261,18 @@ func TestMarketPredicates(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, changed) require.True(t, changed)
changedDeals, ok := valArr.(*MarketDealStateChanges) changedDeals, ok := valArr.(*market.DealStateChanges)
require.True(t, ok) require.True(t, ok)
require.Len(t, changedDeals.Added, 1) require.Len(t, changedDeals.Added, 1)
require.Equal(t, abi.DealID(3), changedDeals.Added[0].ID) require.Equal(t, abi.DealID(3), changedDeals.Added[0].ID)
require.Equal(t, *newDeal3, changedDeals.Added[0].Deal) require.True(t, dealEquality(*newDeal3, changedDeals.Added[0].Deal))
require.Len(t, changedDeals.Removed, 1) require.Len(t, changedDeals.Removed, 1)
require.Len(t, changedDeals.Modified, 1) require.Len(t, changedDeals.Modified, 1)
require.Equal(t, abi.DealID(1), changedDeals.Modified[0].ID) require.Equal(t, abi.DealID(1), changedDeals.Modified[0].ID)
require.Equal(t, newDeal1, changedDeals.Modified[0].To) require.True(t, dealEquality(*newDeal1, changedDeals.Modified[0].To))
require.Equal(t, oldDeal1, changedDeals.Modified[0].From) require.True(t, dealEquality(*oldDeal1, changedDeals.Modified[0].From))
require.Equal(t, abi.DealID(2), changedDeals.Removed[0].ID) require.Equal(t, abi.DealID(2), changedDeals.Removed[0].ID)
}) })
@ -279,17 +288,15 @@ func TestMarketPredicates(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, changed) require.True(t, changed)
changedProps, ok := valArr.(*MarketDealProposalChanges) changedProps, ok := valArr.(*market.DealProposalChanges)
require.True(t, ok) require.True(t, ok)
require.Len(t, changedProps.Added, 1) require.Len(t, changedProps.Added, 1)
require.Equal(t, abi.DealID(3), changedProps.Added[0].ID) require.Equal(t, abi.DealID(3), changedProps.Added[0].ID)
require.Equal(t, *newProp3, changedProps.Added[0].Proposal)
// proposals cannot be modified -- no modified testing // proposals cannot be modified -- no modified testing
require.Len(t, changedProps.Removed, 1) require.Len(t, changedProps.Removed, 1)
require.Equal(t, abi.DealID(2), changedProps.Removed[0].ID) require.Equal(t, abi.DealID(2), changedProps.Removed[0].ID)
require.Equal(t, *oldProp2, changedProps.Removed[0].Proposal)
}) })
t.Run("balances predicate", func(t *testing.T) { t.Run("balances predicate", func(t *testing.T) {
@ -342,7 +349,13 @@ func TestMarketPredicates(t *testing.T) {
t.Fatal("No state change so this should not be called") t.Fatal("No state change so this should not be called")
return false, nil, nil return false, nil, nil
}) })
marketState := createEmptyMarketState(t, store) v0marketState := createEmptyMarketState(t, store)
marketCid, err := store.Put(ctx, v0marketState)
require.NoError(t, err)
marketState, err := market.Load(store, &types.Actor{
Code: v0builtin.StorageMarketActorCodeID,
Head: marketCid,
})
changed, _, err = diffDealBalancesFn(ctx, marketState, marketState) changed, _, err = diffDealBalancesFn(ctx, marketState, marketState)
require.NoError(t, err) require.NoError(t, err)
require.False(t, changed) require.False(t, changed)
@ -450,7 +463,7 @@ type balance struct {
locked abi.TokenAmount locked abi.TokenAmount
} }
func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market.DealState, props map[abi.DealID]*market.DealProposal, balances map[address.Address]balance) cid.Cid { func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*v0market.DealState, props map[abi.DealID]*v0market.DealProposal, balances map[address.Address]balance) cid.Cid {
dealRootCid := createDealAMT(ctx, t, store, deals) dealRootCid := createDealAMT(ctx, t, store, deals)
propRootCid := createProposalAMT(ctx, t, store, props) propRootCid := createProposalAMT(ctx, t, store, props)
balancesCids := createBalanceTable(ctx, t, store, balances) balancesCids := createBalanceTable(ctx, t, store, balances)
@ -465,15 +478,15 @@ func createMarketState(ctx context.Context, t *testing.T, store adt.Store, deals
return stateC return stateC
} }
func createEmptyMarketState(t *testing.T, store adt.Store) *market.State { func createEmptyMarketState(t *testing.T, store adt.Store) *v0market.State {
emptyArrayCid, err := adt.MakeEmptyArray(store).Root() emptyArrayCid, err := adt.MakeEmptyArray(store).Root()
require.NoError(t, err) require.NoError(t, err)
emptyMap, err := adt.MakeEmptyMap(store).Root() emptyMap, err := adt.MakeEmptyMap(store).Root()
require.NoError(t, err) require.NoError(t, err)
return market.ConstructState(emptyArrayCid, emptyMap, emptyMap) return v0market.ConstructState(emptyArrayCid, emptyMap, emptyMap)
} }
func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*market.DealState) cid.Cid { func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map[abi.DealID]*v0market.DealState) cid.Cid {
root := adt.MakeEmptyArray(store) root := adt.MakeEmptyArray(store)
for dealID, dealState := range deals { for dealID, dealState := range deals {
err := root.Set(uint64(dealID), dealState) err := root.Set(uint64(dealID), dealState)
@ -484,7 +497,7 @@ func createDealAMT(ctx context.Context, t *testing.T, store adt.Store, deals map
return rootCid return rootCid
} }
func createProposalAMT(ctx context.Context, t *testing.T, store adt.Store, props map[abi.DealID]*market.DealProposal) cid.Cid { func createProposalAMT(ctx context.Context, t *testing.T, store adt.Store, props map[abi.DealID]*v0market.DealProposal) cid.Cid {
root := adt.MakeEmptyArray(store) root := adt.MakeEmptyArray(store)
for dealID, prop := range props { for dealID, prop := range props {
err := root.Set(uint64(dealID), prop) err := root.Set(uint64(dealID), prop)
@ -607,3 +620,9 @@ func newSectorPreCommitInfo(sectorNo abi.SectorNumber, sealed cid.Cid, expiratio
Expiration: expiration, Expiration: expiration,
} }
} }
func dealEquality(expected v0market.DealState, actual market.DealState) bool {
return expected.LastUpdatedEpoch == actual.LastUpdatedEpoch() &&
expected.SectorStartEpoch == actual.SectorStartEpoch() &&
expected.SlashEpoch == actual.SlashEpoch()
}

View File

@ -8,6 +8,7 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/events/state" "github.com/filecoin-project/lotus/chain/events/state"
) )
@ -293,14 +294,14 @@ func (p *Processor) updateMarketActorDealProposals(ctx context.Context, marketTi
if !changed { if !changed {
continue continue
} }
changes, ok := val.(*state.MarketDealStateChanges) changes, ok := val.(*market.DealStateChanges)
if !ok { if !ok {
return xerrors.Errorf("Unknown type returned by Deal State AMT predicate: %T", val) return xerrors.Errorf("Unknown type returned by Deal State AMT predicate: %T", val)
} }
for _, modified := range changes.Modified { for _, modified := range changes.Modified {
if modified.From.SlashEpoch != modified.To.SlashEpoch { if modified.From.SlashEpoch() != modified.To.SlashEpoch() {
if _, err := stmt.Exec(modified.To.SlashEpoch, modified.ID); err != nil { if _, err := stmt.Exec(modified.To.SlashEpoch(), modified.ID); err != nil {
return err return err
} }
} }