feat: add market deal state & proposal predicates
- detects changes in the market deal proposal and market deal state amts.
This commit is contained in:
parent
1254f9de0c
commit
bf6b76a4fb
@ -4,13 +4,11 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
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"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/go-amt-ipld/v2"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||||
@ -87,20 +85,25 @@ func (sp *StatePredicates) OnStorageMarketActorChanged(diffStorageMarketState Di
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiffDealStatesFunc func(ctx context.Context, oldDealStateRoot *amt.Root, newDealStateRoot *amt.Root) (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 state changes
|
// OnDealStateChanged calls diffDealStates when the market deal state changes
|
||||||
func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffDealStatesFunc) DiffStorageMarketStateFunc {
|
func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffAdtArraysFunc) 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.States.Equals(newState.States) {
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
oldRoot, err := amt.LoadAMT(ctx, sp.cst, oldState.States)
|
ctxStore := &contextStore{
|
||||||
|
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 := amt.LoadAMT(ctx, sp.cst, newState.States)
|
newRoot, err := adt.AsArray(ctxStore, newState.States)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
@ -109,31 +112,188 @@ func (sp *StatePredicates) OnDealStateChanged(diffDealStates DiffDealStatesFunc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnDealProposalChanged calls diffDealProps when the market proposal state changes
|
||||||
|
func (sp *StatePredicates) OnDealProposalChanged(diffDealProps DiffAdtArraysFunc) DiffStorageMarketStateFunc {
|
||||||
|
return func(ctx context.Context, oldState *market.State, newState *market.State) (changed bool, user UserData, err error) {
|
||||||
|
if oldState.Proposals.Equals(newState.Proposals) {
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxStore := &contextStore{
|
||||||
|
ctx: ctx,
|
||||||
|
cst: sp.cst,
|
||||||
|
}
|
||||||
|
|
||||||
|
oldRoot, err := adt.AsArray(ctxStore, oldState.Proposals)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
newRoot, err := adt.AsArray(ctxStore, newState.Proposals)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return diffDealProps(ctx, oldRoot, newRoot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
// - Added Proposals
|
||||||
|
// - Modified Proposals
|
||||||
|
// - Removed Proposals
|
||||||
|
func (sp *StatePredicates) OnDealProposalAmtChanged() DiffAdtArraysFunc {
|
||||||
|
return func(ctx context.Context, oldDealProps, newDealProps *adt.Array) (changed bool, user UserData, err error) {
|
||||||
|
proposalChanges := new(MarketDealProposalChanges)
|
||||||
|
if err := DiffAdtArray(oldDealProps, newDealProps, proposalChanges); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(proposalChanges.Added)+len(proposalChanges.Removed) == 0 {
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, proposalChanges, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
// - Added Deals
|
||||||
|
// - Modified Deals
|
||||||
|
// - Removed Deals
|
||||||
|
func (sp *StatePredicates) OnDealStateAmtChanged() DiffAdtArraysFunc {
|
||||||
|
return func(ctx context.Context, oldDealStates, newDealStates *adt.Array) (changed bool, user UserData, err error) {
|
||||||
|
dealStateChanges := new(MarketDealStateChanges)
|
||||||
|
if err := DiffAdtArray(oldDealStates, newDealStates, dealStateChanges); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(dealStateChanges.Added)+len(dealStateChanges.Modified)+len(dealStateChanges.Removed) == 0 {
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, dealStateChanges, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ChangedDeals is a set of changes to deal state
|
// ChangedDeals is a set of changes to deal state
|
||||||
type ChangedDeals map[abi.DealID]DealStateChange
|
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 {
|
||||||
From market.DealState
|
ID abi.DealID
|
||||||
To market.DealState
|
From *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) DiffDealStatesFunc {
|
func (sp *StatePredicates) DealStateChangedForIDs(dealIds []abi.DealID) DiffAdtArraysFunc {
|
||||||
return func(ctx context.Context, oldDealStateRoot *amt.Root, newDealStateRoot *amt.Root) (changed bool, user UserData, err error) {
|
return func(ctx context.Context, oldDealStateArray, newDealStateArray *adt.Array) (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
|
var oldDeal, newDeal market.DealState
|
||||||
err := oldDealStateRoot.Get(ctx, uint64(dealID), &oldDeal)
|
|
||||||
|
_, err := oldDealStateArray.Get(uint64(dealID), &oldDeal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
err = newDealStateRoot.Get(ctx, uint64(dealID), &newDeal)
|
oldDealPtr = &oldDeal
|
||||||
|
|
||||||
|
_, err = newDealStateArray.Get(uint64(dealID), &newDeal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
|
newDealPtr = &newDeal
|
||||||
|
|
||||||
if oldDeal != newDeal {
|
if oldDeal != newDeal {
|
||||||
changedDeals[dealID] = DealStateChange{oldDeal, newDeal}
|
changedDeals[dealID] = DealStateChange{dealID, oldDealPtr, newDealPtr}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(changedDeals) > 0 {
|
if len(changedDeals) > 0 {
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"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/builtin/miner"
|
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||||
|
"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"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -65,75 +66,137 @@ func (m mockAPI) setActor(tsk types.TipSetKey, act *types.Actor) {
|
|||||||
m.ts[tsk] = act
|
m.ts[tsk] = act
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPredicates(t *testing.T) {
|
func TestMarketPredicates(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
bs := bstore.NewBlockstore(ds_sync.MutexWrap(ds.NewMapDatastore()))
|
||||||
store := cbornode.NewCborStore(bs)
|
store := cbornode.NewCborStore(bs)
|
||||||
|
|
||||||
oldDeals := map[abi.DealID]*market.DealState{
|
oldDeal1 := &market.DealState{
|
||||||
abi.DealID(1): {
|
|
||||||
SectorStartEpoch: 1,
|
SectorStartEpoch: 1,
|
||||||
LastUpdatedEpoch: 2,
|
LastUpdatedEpoch: 2,
|
||||||
SlashEpoch: 0,
|
SlashEpoch: 0,
|
||||||
},
|
}
|
||||||
abi.DealID(2): {
|
oldDeal2 := &market.DealState{
|
||||||
SectorStartEpoch: 4,
|
SectorStartEpoch: 4,
|
||||||
LastUpdatedEpoch: 5,
|
LastUpdatedEpoch: 5,
|
||||||
SlashEpoch: 0,
|
SlashEpoch: 0,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
oldStateC := createMarketState(ctx, t, store, oldDeals)
|
oldDeals := map[abi.DealID]*market.DealState{
|
||||||
|
abi.DealID(1): oldDeal1,
|
||||||
|
abi.DealID(2): oldDeal2,
|
||||||
|
}
|
||||||
|
|
||||||
newDeals := map[abi.DealID]*market.DealState{
|
oldProp1 := &market.DealProposal{
|
||||||
abi.DealID(1): {
|
PieceCID: dummyCid,
|
||||||
|
PieceSize: 0,
|
||||||
|
VerifiedDeal: false,
|
||||||
|
Client: tutils.NewIDAddr(t, 1),
|
||||||
|
Provider: tutils.NewIDAddr(t, 1),
|
||||||
|
StartEpoch: 1,
|
||||||
|
EndEpoch: 2,
|
||||||
|
StoragePricePerEpoch: big.Zero(),
|
||||||
|
ProviderCollateral: big.Zero(),
|
||||||
|
ClientCollateral: big.Zero(),
|
||||||
|
}
|
||||||
|
oldProp2 := &market.DealProposal{
|
||||||
|
PieceCID: dummyCid,
|
||||||
|
PieceSize: 0,
|
||||||
|
VerifiedDeal: false,
|
||||||
|
Client: tutils.NewIDAddr(t, 1),
|
||||||
|
Provider: tutils.NewIDAddr(t, 1),
|
||||||
|
StartEpoch: 2,
|
||||||
|
EndEpoch: 3,
|
||||||
|
StoragePricePerEpoch: big.Zero(),
|
||||||
|
ProviderCollateral: big.Zero(),
|
||||||
|
ClientCollateral: big.Zero(),
|
||||||
|
}
|
||||||
|
oldProps := map[abi.DealID]*market.DealProposal{
|
||||||
|
abi.DealID(1): oldProp1,
|
||||||
|
abi.DealID(2): oldProp2,
|
||||||
|
}
|
||||||
|
|
||||||
|
oldStateC := createMarketState(ctx, t, store, oldDeals, oldProps)
|
||||||
|
|
||||||
|
newDeal1 := &market.DealState{
|
||||||
SectorStartEpoch: 1,
|
SectorStartEpoch: 1,
|
||||||
LastUpdatedEpoch: 3,
|
LastUpdatedEpoch: 3,
|
||||||
SlashEpoch: 0,
|
SlashEpoch: 0,
|
||||||
},
|
}
|
||||||
abi.DealID(2): {
|
newDeal2 := &market.DealState{
|
||||||
SectorStartEpoch: 4,
|
SectorStartEpoch: 4,
|
||||||
LastUpdatedEpoch: 6,
|
LastUpdatedEpoch: 6,
|
||||||
SlashEpoch: 6,
|
SlashEpoch: 6,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
newStateC := createMarketState(ctx, t, store, newDeals)
|
// added
|
||||||
|
newDeal3 := &market.DealState{
|
||||||
|
SectorStartEpoch: 1,
|
||||||
|
LastUpdatedEpoch: 2,
|
||||||
|
SlashEpoch: 3,
|
||||||
|
}
|
||||||
|
newDeals := map[abi.DealID]*market.DealState{
|
||||||
|
abi.DealID(1): newDeal1,
|
||||||
|
abi.DealID(2): newDeal2,
|
||||||
|
abi.DealID(3): newDeal3,
|
||||||
|
}
|
||||||
|
|
||||||
miner, err := address.NewFromString("t00")
|
// added
|
||||||
|
newProp3 := &market.DealProposal{
|
||||||
|
PieceCID: dummyCid,
|
||||||
|
PieceSize: 0,
|
||||||
|
VerifiedDeal: false,
|
||||||
|
Client: tutils.NewIDAddr(t, 1),
|
||||||
|
Provider: tutils.NewIDAddr(t, 1),
|
||||||
|
StartEpoch: 4,
|
||||||
|
EndEpoch: 4,
|
||||||
|
StoragePricePerEpoch: big.Zero(),
|
||||||
|
ProviderCollateral: big.Zero(),
|
||||||
|
ClientCollateral: big.Zero(),
|
||||||
|
}
|
||||||
|
newProps := map[abi.DealID]*market.DealProposal{
|
||||||
|
abi.DealID(1): oldProp1, // 1 was persisted
|
||||||
|
// prop 2 was removed
|
||||||
|
abi.DealID(3): newProp3, // new
|
||||||
|
// NB: DealProposals cannot be modified, so don't test that case.
|
||||||
|
}
|
||||||
|
newStateC := createMarketState(ctx, t, store, newDeals, newProps)
|
||||||
|
|
||||||
|
minerAddr, err := address.NewFromString("t00")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
oldState, err := mockTipset(miner, 1)
|
oldState, err := mockTipset(minerAddr, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
newState, err := mockTipset(miner, 2)
|
newState, err := mockTipset(minerAddr, 2)
|
||||||
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{Head: oldStateC})
|
||||||
api.setActor(newState.Key(), &types.Actor{Head: newStateC})
|
api.setActor(newState.Key(), &types.Actor{Head: newStateC})
|
||||||
|
|
||||||
|
t.Run("deal ID predicate", func(t *testing.T) {
|
||||||
preds := NewStatePredicates(api)
|
preds := NewStatePredicates(api)
|
||||||
|
|
||||||
dealIds := []abi.DealID{abi.DealID(1), abi.DealID(2)}
|
dealIds := []abi.DealID{abi.DealID(1), abi.DealID(2)}
|
||||||
diffFn := preds.OnStorageMarketActorChanged(preds.OnDealStateChanged(preds.DealStateChangedForIDs(dealIds)))
|
diffIDFn := preds.OnStorageMarketActorChanged(preds.OnDealStateChanged(preds.DealStateChangedForIDs(dealIds)))
|
||||||
|
|
||||||
// Diff a state against itself: expect no change
|
// Diff a state against itself: expect no change
|
||||||
changed, _, err := diffFn(ctx, oldState.Key(), oldState.Key())
|
changed, _, err := diffIDFn(ctx, oldState.Key(), oldState.Key())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.False(t, changed)
|
require.False(t, changed)
|
||||||
|
|
||||||
// Diff old state against new state
|
// Diff old state against new state
|
||||||
changed, val, err := diffFn(ctx, oldState.Key(), newState.Key())
|
changed, valIDs, err := diffIDFn(ctx, oldState.Key(), newState.Key())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, changed)
|
require.True(t, changed)
|
||||||
|
|
||||||
changedDeals, ok := val.(ChangedDeals)
|
changedDealIDs, ok := valIDs.(ChangedDeals)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Len(t, changedDeals, 2)
|
require.Len(t, changedDealIDs, 2)
|
||||||
require.Contains(t, changedDeals, abi.DealID(1))
|
require.Contains(t, changedDealIDs, abi.DealID(1))
|
||||||
require.Contains(t, changedDeals, abi.DealID(2))
|
require.Contains(t, changedDealIDs, abi.DealID(2))
|
||||||
deal1 := changedDeals[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 := changedDeals[abi.DealID(2)]
|
deal2 := changedDealIDs[abi.DealID(2)]
|
||||||
if deal2.From.SlashEpoch != 0 || deal2.To.SlashEpoch != 6 {
|
if deal2.From.SlashEpoch != 0 || deal2.To.SlashEpoch != 6 {
|
||||||
t.Fatal("Unexpected change to SlashEpoch")
|
t.Fatal("Unexpected change to SlashEpoch")
|
||||||
}
|
}
|
||||||
@ -150,7 +213,7 @@ func TestPredicates(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, *amt.Root, *amt.Root) (bool, UserData, error) {
|
diffDealStateFn := preds.OnDealStateChanged(func(context.Context, *adt.Array, *adt.Array) (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
|
||||||
})
|
})
|
||||||
@ -158,6 +221,61 @@ func TestPredicates(t *testing.T) {
|
|||||||
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("deal state array predicate", func(t *testing.T) {
|
||||||
|
preds := NewStatePredicates(api)
|
||||||
|
diffArrFn := preds.OnStorageMarketActorChanged(preds.OnDealStateChanged(preds.OnDealStateAmtChanged()))
|
||||||
|
|
||||||
|
changed, _, err := diffArrFn(ctx, oldState.Key(), oldState.Key())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, changed)
|
||||||
|
|
||||||
|
changed, valArr, err := diffArrFn(ctx, oldState.Key(), newState.Key())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, changed)
|
||||||
|
|
||||||
|
changedDeals, ok := valArr.(*MarketDealStateChanges)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Len(t, changedDeals.Added, 1)
|
||||||
|
require.Equal(t, abi.DealID(3), changedDeals.Added[0].ID)
|
||||||
|
require.Equal(t, *newDeal3, changedDeals.Added[0].Deal)
|
||||||
|
|
||||||
|
require.Len(t, changedDeals.Removed, 0)
|
||||||
|
|
||||||
|
require.Len(t, changedDeals.Modified, 2)
|
||||||
|
require.Equal(t, abi.DealID(1), changedDeals.Modified[0].ID)
|
||||||
|
require.Equal(t, newDeal1, changedDeals.Modified[0].To)
|
||||||
|
require.Equal(t, oldDeal1, changedDeals.Modified[0].From)
|
||||||
|
|
||||||
|
require.Equal(t, abi.DealID(2), changedDeals.Modified[1].ID)
|
||||||
|
require.Equal(t, oldDeal2, changedDeals.Modified[1].From)
|
||||||
|
require.Equal(t, newDeal2, changedDeals.Modified[1].To)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("deal proposal array predicate", func(t *testing.T) {
|
||||||
|
preds := NewStatePredicates(api)
|
||||||
|
diffArrFn := preds.OnStorageMarketActorChanged(preds.OnDealProposalChanged(preds.OnDealProposalAmtChanged()))
|
||||||
|
changed, _, err := diffArrFn(ctx, oldState.Key(), oldState.Key())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, changed)
|
||||||
|
|
||||||
|
changed, valArr, err := diffArrFn(ctx, oldState.Key(), newState.Key())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, changed)
|
||||||
|
|
||||||
|
changedProps, ok := valArr.(*MarketDealProposalChanges)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Len(t, changedProps.Added, 1)
|
||||||
|
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
|
||||||
|
|
||||||
|
require.Len(t, changedProps.Removed, 1)
|
||||||
|
require.Equal(t, abi.DealID(2), changedProps.Removed[0].ID)
|
||||||
|
require.Equal(t, *oldProp2, changedProps.Removed[0].Proposal)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMinerSectorChange(t *testing.T) {
|
func TestMinerSectorChange(t *testing.T) {
|
||||||
@ -208,14 +326,15 @@ func TestMinerSectorChange(t *testing.T) {
|
|||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
require.Equal(t, len(sectorChanges.Added), 1)
|
require.Equal(t, len(sectorChanges.Added), 1)
|
||||||
require.Equal(t, sectorChanges.Added[0], si3)
|
require.Equal(t, 1, len(sectorChanges.Added))
|
||||||
|
require.Equal(t, si3, sectorChanges.Added[0])
|
||||||
|
|
||||||
require.Equal(t, len(sectorChanges.Removed), 1)
|
require.Equal(t, 1, len(sectorChanges.Removed))
|
||||||
require.Equal(t, sectorChanges.Removed[0], si0)
|
require.Equal(t, si0, sectorChanges.Removed[0])
|
||||||
|
|
||||||
require.Equal(t, len(sectorChanges.Extended), 1)
|
require.Equal(t, 1, len(sectorChanges.Extended))
|
||||||
require.Equal(t, sectorChanges.Extended[0].From, si1)
|
require.Equal(t, si1, sectorChanges.Extended[0].From)
|
||||||
require.Equal(t, sectorChanges.Extended[0].To, si1Ext)
|
require.Equal(t, si1Ext, sectorChanges.Extended[0].To)
|
||||||
|
|
||||||
change, val, err = minerDiffFn(ctx, oldState.Key(), oldState.Key())
|
change, val, err = minerDiffFn(ctx, oldState.Key(), oldState.Key())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -230,20 +349,20 @@ func TestMinerSectorChange(t *testing.T) {
|
|||||||
sectorChanges, ok = val.(*MinerSectorChanges)
|
sectorChanges, ok = val.(*MinerSectorChanges)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
require.Equal(t, len(sectorChanges.Added), 1)
|
require.Equal(t, 1, len(sectorChanges.Added))
|
||||||
require.Equal(t, sectorChanges.Added[0], si0)
|
require.Equal(t, si0, sectorChanges.Added[0])
|
||||||
|
|
||||||
require.Equal(t, len(sectorChanges.Removed), 1)
|
require.Equal(t, 1, len(sectorChanges.Removed))
|
||||||
require.Equal(t, sectorChanges.Removed[0], si3)
|
require.Equal(t, si3, sectorChanges.Removed[0])
|
||||||
|
|
||||||
require.Equal(t, len(sectorChanges.Extended), 1)
|
require.Equal(t, 1, len(sectorChanges.Extended))
|
||||||
require.Equal(t, sectorChanges.Extended[0].To, si1)
|
require.Equal(t, si1, sectorChanges.Extended[0].To)
|
||||||
require.Equal(t, sectorChanges.Extended[0].From, si1Ext)
|
require.Equal(t, si1Ext, sectorChanges.Extended[0].From)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockTipset(miner address.Address, timestamp uint64) (*types.TipSet, error) {
|
func mockTipset(minerAddr address.Address, timestamp uint64) (*types.TipSet, error) {
|
||||||
return types.NewTipSet([]*types.BlockHeader{{
|
return types.NewTipSet([]*types.BlockHeader{{
|
||||||
Miner: miner,
|
Miner: minerAddr,
|
||||||
Height: 5,
|
Height: 5,
|
||||||
ParentStateRoot: dummyCid,
|
ParentStateRoot: dummyCid,
|
||||||
Messages: dummyCid,
|
Messages: dummyCid,
|
||||||
@ -254,11 +373,13 @@ func mockTipset(miner address.Address, timestamp uint64) (*types.TipSet, error)
|
|||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMarketState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, deals map[abi.DealID]*market.DealState) cid.Cid {
|
func createMarketState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, deals map[abi.DealID]*market.DealState, props map[abi.DealID]*market.DealProposal) cid.Cid {
|
||||||
rootCid := createDealAMT(ctx, t, store, deals)
|
dealRootCid := createDealAMT(ctx, t, store, deals)
|
||||||
|
propRootCid := createProposalAMT(ctx, t, store, props)
|
||||||
|
|
||||||
state := createEmptyMarketState(t, store)
|
state := createEmptyMarketState(t, store)
|
||||||
state.States = rootCid
|
state.States = dealRootCid
|
||||||
|
state.Proposals = propRootCid
|
||||||
|
|
||||||
stateC, err := store.Put(ctx, state)
|
stateC, err := store.Put(ctx, state)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -284,6 +405,17 @@ func createDealAMT(ctx context.Context, t *testing.T, store *cbornode.BasicIpldS
|
|||||||
return rootCid
|
return rootCid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createProposalAMT(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, props map[abi.DealID]*market.DealProposal) cid.Cid {
|
||||||
|
root := amt.NewAMT(store)
|
||||||
|
for dealID, prop := range props {
|
||||||
|
err := root.Set(ctx, uint64(dealID), prop)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
rootCid, err := root.Flush(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return rootCid
|
||||||
|
}
|
||||||
|
|
||||||
func createMinerState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, owner, worker address.Address, sectors []miner.SectorOnChainInfo) cid.Cid {
|
func createMinerState(ctx context.Context, t *testing.T, store *cbornode.BasicIpldStore, owner, worker address.Address, sectors []miner.SectorOnChainInfo) cid.Cid {
|
||||||
rootCid := createSectorsAMT(ctx, t, store, sectors)
|
rootCid := createSectorsAMT(ctx, t, store, sectors)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user