diff --git a/tasks/actorstate/miner/sector_events.go b/tasks/actorstate/miner/sector_events.go index 46ce08a1d..f4ef0efac 100644 --- a/tasks/actorstate/miner/sector_events.go +++ b/tasks/actorstate/miner/sector_events.go @@ -13,6 +13,7 @@ import ( "github.com/filecoin-project/lily/model" minermodel "github.com/filecoin-project/lily/model/actors/miner" "github.com/filecoin-project/lily/tasks/actorstate" + "github.com/filecoin-project/lily/tasks/actorstate/miner/extraction" ) type SectorEventsExtractor struct{} @@ -25,27 +26,27 @@ func (SectorEventsExtractor) Extract(ctx context.Context, a actorstate.ActorInfo span.SetAttributes(a.Attributes()...) } - ec, err := NewMinerStateExtractionContext(ctx, a, node) + extState, err := extraction.LoadMinerStates(ctx, a, node) if err != nil { return nil, fmt.Errorf("creating miner state extraction context: %w", err) } var sectorChanges *miner.SectorChanges var preCommitChanges *miner.PreCommitChanges - if !ec.HasPreviousState() { + if extState.ParentState() == nil { // If the miner doesn't have previous state list all of its current sectors and precommits - sectors, err := ec.CurrState.LoadSectors(nil) + sectors, err := extState.CurrentState().LoadSectors(nil) if err != nil { return nil, fmt.Errorf("loading miner sectors: %w", err) } sectorChanges = miner.MakeSectorChanges() - for i, sector := range sectors { - sectorChanges.Added[i] = *sector + for _, sector := range sectors { + sectorChanges.Added = append(sectorChanges.Added, *sector) } preCommitChanges = miner.MakePreCommitChanges() - if err = ec.CurrState.ForEachPrecommittedSector(func(info miner.SectorPreCommitOnChainInfo) error { + if err = extState.CurrentState().ForEachPrecommittedSector(func(info miner.SectorPreCommitOnChainInfo) error { preCommitChanges.Added = append(preCommitChanges.Added, info) return nil }); err != nil { @@ -54,18 +55,23 @@ func (SectorEventsExtractor) Extract(ctx context.Context, a actorstate.ActorInfo } else { // If the miner has previous state compute the list of new sectors and precommit in its current state. - preCommitChanges, err = node.DiffPreCommits(ctx, a.Address, a.Current, a.Executed, ec.PrevState, ec.CurrState) + preCommitChanges, err = node.DiffPreCommits(ctx, a.Address, a.Current, a.Executed, extState.ParentState(), extState.CurrentState()) if err != nil { return nil, err } - sectorChanges, err = node.DiffSectors(ctx, a.Address, a.Current, a.Executed, ec.PrevState, ec.CurrState) + sectorChanges, err = node.DiffSectors(ctx, a.Address, a.Current, a.Executed, extState.ParentState(), extState.CurrentState()) if err != nil { return nil, err } } - sectorEventModel, err := extractSectorEvents(ctx, a, ec, sectorChanges, preCommitChanges) + dlDiff, err := miner.DiffDeadlines(extState.ParentState(), extState.CurrentState()) + if err != nil { + return nil, err + } + + sectorEventModel, err := ExtractSectorEvents(ctx, extState, sectorChanges, preCommitChanges, dlDiff) if err != nil { return nil, err } @@ -73,18 +79,18 @@ func (SectorEventsExtractor) Extract(ctx context.Context, a actorstate.ActorInfo return sectorEventModel, nil } -func extractSectorEvents(ctx context.Context, a actorstate.ActorInfo, ec *MinerStateExtractionContext, sc *miner.SectorChanges, pc *miner.PreCommitChanges) (minermodel.MinerSectorEventList, error) { - ctx, span := otel.Tracer("").Start(ctx, "extractMinerSectorEvents") +func ExtractSectorEvents(ctx context.Context, extState extraction.State, sc *miner.SectorChanges, pc *miner.PreCommitChanges, dlDiff miner.DeadlinesDiff) (minermodel.MinerSectorEventList, error) { + ctx, span := otel.Tracer("").Start(ctx, "ExtractSectorEvents") defer span.End() - partitionEvents, err := extractMinerPartitionsDiff(ctx, a, ec) + partitionEvents, err := ExtractMinerPartitionsDiff(ctx, extState, dlDiff) if err != nil { return nil, fmt.Errorf("extracting miner partition diff: %w", err) } - sectorEvents := extractMinerSectorEvents(a, sc) + sectorEvents := ExtractMinerSectorEvents(extState, sc) - preCommitEvents := extractMinerPreCommitEvents(a, pc) + preCommitEvents := ExtractMinerPreCommitEvents(extState, pc) out := make(minermodel.MinerSectorEventList, 0, len(partitionEvents)+len(sectorEvents)+len(preCommitEvents)) out = append(out, partitionEvents...) @@ -94,7 +100,7 @@ func extractSectorEvents(ctx context.Context, a actorstate.ActorInfo, ec *MinerS return out, nil } -func extractMinerSectorEvents(a actorstate.ActorInfo, sectors *miner.SectorChanges) minermodel.MinerSectorEventList { +func ExtractMinerSectorEvents(extState extraction.State, sectors *miner.SectorChanges) minermodel.MinerSectorEventList { out := make(minermodel.MinerSectorEventList, 0, len(sectors.Added)+len(sectors.Extended)+len(sectors.Snapped)) // track sector add and commit-capacity add @@ -104,9 +110,9 @@ func extractMinerSectorEvents(a actorstate.ActorInfo, sectors *miner.SectorChang event = minermodel.CommitCapacityAdded } out = append(out, &minermodel.MinerSectorEvent{ - Height: int64(a.Current.Height()), - MinerID: a.Address.String(), - StateRoot: a.Current.ParentState().String(), + Height: int64(extState.CurrentTipSet().Height()), + MinerID: extState.Address().String(), + StateRoot: extState.CurrentTipSet().ParentState().String(), SectorID: uint64(add.SectorNumber), Event: event, }) @@ -115,9 +121,9 @@ func extractMinerSectorEvents(a actorstate.ActorInfo, sectors *miner.SectorChang // sector extension events for _, mod := range sectors.Extended { out = append(out, &minermodel.MinerSectorEvent{ - Height: int64(a.Current.Height()), - MinerID: a.Address.String(), - StateRoot: a.Current.ParentState().String(), + Height: int64(extState.CurrentTipSet().Height()), + MinerID: extState.Address().String(), + StateRoot: extState.CurrentTipSet().ParentState().String(), SectorID: uint64(mod.To.SectorNumber), Event: minermodel.SectorExtended, }) @@ -126,9 +132,9 @@ func extractMinerSectorEvents(a actorstate.ActorInfo, sectors *miner.SectorChang // sector snapped events for _, snap := range sectors.Snapped { out = append(out, &minermodel.MinerSectorEvent{ - Height: int64(a.Current.Height()), - MinerID: a.Address.String(), - StateRoot: a.Current.ParentState().String(), + Height: int64(extState.CurrentTipSet().Height()), + MinerID: extState.Address().String(), + StateRoot: extState.CurrentTipSet().ParentState().String(), SectorID: uint64(snap.To.SectorNumber), Event: minermodel.SectorSnapped, }) @@ -137,14 +143,14 @@ func extractMinerSectorEvents(a actorstate.ActorInfo, sectors *miner.SectorChang return out } -func extractMinerPreCommitEvents(a actorstate.ActorInfo, preCommits *miner.PreCommitChanges) minermodel.MinerSectorEventList { +func ExtractMinerPreCommitEvents(extState extraction.State, preCommits *miner.PreCommitChanges) minermodel.MinerSectorEventList { out := make(minermodel.MinerSectorEventList, len(preCommits.Added)) // track precommit addition for i, add := range preCommits.Added { out[i] = &minermodel.MinerSectorEvent{ - Height: int64(a.Current.Height()), - MinerID: a.Address.String(), - StateRoot: a.Current.ParentState().String(), + Height: int64(extState.CurrentTipSet().Height()), + MinerID: extState.Address().String(), + StateRoot: extState.CurrentTipSet().ParentState().String(), SectorID: uint64(add.Info.SectorNumber), Event: minermodel.PreCommitAdded, } @@ -153,20 +159,15 @@ func extractMinerPreCommitEvents(a actorstate.ActorInfo, preCommits *miner.PreCo return out } -func extractMinerPartitionsDiff(ctx context.Context, a actorstate.ActorInfo, ec *MinerStateExtractionContext) (minermodel.MinerSectorEventList, error) { - _, span := otel.Tracer("").Start(ctx, "extractMinerPartitionDiff") // nolint: ineffassign,staticcheck +func ExtractMinerPartitionsDiff(ctx context.Context, extState extraction.State, dlDiff miner.DeadlinesDiff) (minermodel.MinerSectorEventList, error) { + _, span := otel.Tracer("").Start(ctx, "ExtractMinerPartitionsDiff") // nolint: ineffassign,staticcheck defer span.End() // short circuit genesis state. - if !ec.HasPreviousState() { + if extState.ParentState() == nil { return nil, nil } - dlDiff, err := miner.DiffDeadlines(ec.PrevState, ec.CurrState) - if err != nil { - return nil, err - } - if dlDiff == nil { return nil, nil } @@ -176,6 +177,7 @@ func extractMinerPartitionsDiff(ctx context.Context, a actorstate.ActorInfo, ec recovered := bitfield.New() recovering := bitfield.New() + var err error for _, deadline := range dlDiff { for _, partition := range deadline { removed, err = bitfield.MergeBitFields(removed, partition.Removed) @@ -198,7 +200,7 @@ func extractMinerPartitionsDiff(ctx context.Context, a actorstate.ActorInfo, ec } // build an index of removed sector expiration's for comparison below. - removedSectors, err := ec.CurrState.LoadSectors(&removed) + removedSectors, err := extState.CurrentState().LoadSectors(&removed) if err != nil { return nil, fmt.Errorf("fetching miners removed sectors: %w", err) } @@ -213,13 +215,13 @@ func extractMinerPartitionsDiff(ctx context.Context, a actorstate.ActorInfo, ec if err := removed.ForEach(func(u uint64) error { event := minermodel.SectorTerminated expiration := rmExpireIndex[u] - if expiration == a.Current.Height() { + if expiration == extState.CurrentTipSet().Height() { event = minermodel.SectorExpired } out = append(out, &minermodel.MinerSectorEvent{ - Height: int64(a.Current.Height()), - MinerID: a.Address.String(), - StateRoot: a.Current.ParentState().String(), + Height: int64(extState.CurrentTipSet().Height()), + MinerID: extState.Address().String(), + StateRoot: extState.CurrentTipSet().ParentState().String(), SectorID: u, Event: event, }) @@ -231,9 +233,9 @@ func extractMinerPartitionsDiff(ctx context.Context, a actorstate.ActorInfo, ec // track recovering sectors if err := recovering.ForEach(func(u uint64) error { out = append(out, &minermodel.MinerSectorEvent{ - Height: int64(a.Current.Height()), - MinerID: a.Address.String(), - StateRoot: a.Current.ParentState().String(), + Height: int64(extState.CurrentTipSet().Height()), + MinerID: extState.Address().String(), + StateRoot: extState.CurrentTipSet().ParentState().String(), SectorID: u, Event: minermodel.SectorRecovering, }) @@ -245,9 +247,9 @@ func extractMinerPartitionsDiff(ctx context.Context, a actorstate.ActorInfo, ec // track faulted sectors if err := faulted.ForEach(func(u uint64) error { out = append(out, &minermodel.MinerSectorEvent{ - Height: int64(a.Current.Height()), - MinerID: a.Address.String(), - StateRoot: a.Current.ParentState().String(), + Height: int64(extState.CurrentTipSet().Height()), + MinerID: extState.Address().String(), + StateRoot: extState.CurrentTipSet().ParentState().String(), SectorID: u, Event: minermodel.SectorFaulted, }) @@ -259,9 +261,9 @@ func extractMinerPartitionsDiff(ctx context.Context, a actorstate.ActorInfo, ec // track recovered sectors if err := recovered.ForEach(func(u uint64) error { out = append(out, &minermodel.MinerSectorEvent{ - Height: int64(a.Current.Height()), - MinerID: a.Address.String(), - StateRoot: a.Current.ParentState().String(), + Height: int64(extState.CurrentTipSet().Height()), + MinerID: extState.Address().String(), + StateRoot: extState.CurrentTipSet().ParentState().String(), SectorID: u, Event: minermodel.SectorRecovered, }) diff --git a/tasks/actorstate/miner/sector_events_test.go b/tasks/actorstate/miner/sector_events_test.go new file mode 100644 index 000000000..d1af5d33b --- /dev/null +++ b/tasks/actorstate/miner/sector_events_test.go @@ -0,0 +1,502 @@ +package miner_test + +import ( + "context" + "sort" + "testing" + + "github.com/filecoin-project/go-bitfield" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + "github.com/ipfs/go-cid" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/lily/chain/actors/builtin/miner" + minerstatemocks "github.com/filecoin-project/lily/chain/actors/builtin/miner/mocks" + minermodel "github.com/filecoin-project/lily/model/actors/miner" + minerex "github.com/filecoin-project/lily/tasks/actorstate/miner" + "github.com/filecoin-project/lily/tasks/actorstate/miner/extraction/mocks" + "github.com/filecoin-project/lily/testutil" +) + +func TestExtractMinerPreCommitEvents(t *testing.T) { + minerContext := new(mocks.MockMinerState) + ts := testutil.MustFakeTipSet(t, 10) + addr := testutil.MustMakeAddress(t, 100) + minerContext.On("CurrentTipSet").Return(ts) + minerContext.On("Address").Return(addr) + fakePrecommitChanges := generateFakeSectorPreCommitChanges(10, 5) + result := minerex.ExtractMinerPreCommitEvents(minerContext, fakePrecommitChanges) + require.NotNil(t, result) + require.Len(t, result, 10) + for i, res := range result { + require.Equal(t, addr.String(), res.MinerID) + require.Equal(t, int64(ts.Height()), res.Height) + require.Equal(t, ts.ParentState().String(), res.StateRoot) + require.Equal(t, minermodel.PreCommitAdded, res.Event) + require.EqualValues(t, fakePrecommitChanges.Added[i].Info.SectorNumber, res.SectorID) + } +} + +func TestExtractMinerPartitionsDiff(t *testing.T) { + ctx := context.Background() + minerContext := new(mocks.MockMinerState) + parentMinerState := new(minerstatemocks.State) + currentMinerState := new(minerstatemocks.State) + ts := testutil.MustFakeTipSet(t, 10) + addr := testutil.MustMakeAddress(t, 100) + minerContext.On("ParentState").Return(parentMinerState) + minerContext.On("CurrentState").Return(currentMinerState) + minerContext.On("CurrentTipSet").Return(ts) + minerContext.On("Address").Return(addr) + numTerminated := uint64(2) + numRecovered := uint64(3) + numFaulted := uint64(4) + numRecovering := uint64(5) + // deadline 0 partition 1 has 2 removed sectors, 3 recovered, 4 faulted, and 5 recovering, total of 14 sector events + fakeDl := generateFakeDeadlinesDiff(0, 1, numTerminated, numRecovered, numFaulted, numRecovering) + currentMinerState.On("LoadSectors", mock.Anything).Return([]*miner.SectorOnChainInfo{}, nil) + result, err := minerex.ExtractMinerPartitionsDiff(ctx, minerContext, fakeDl) + require.NoError(t, err) + require.NotNil(t, result) + require.Len(t, result, int(numTerminated+numRecovered+numFaulted+numRecovering)) + + events := make(map[string][]*minermodel.MinerSectorEvent) + for _, res := range result { + events[res.Event] = append(events[res.Event], res) + } + + terminated := events[minermodel.SectorTerminated] + sort.Slice(terminated, func(i, j int) bool { + return terminated[i].SectorID < terminated[j].SectorID + }) + for i, e := range terminated { + require.Equal(t, minermodel.SectorTerminated, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + recovered := events[minermodel.SectorRecovered] + sort.Slice(recovered, func(i, j int) bool { + return recovered[i].SectorID < recovered[j].SectorID + }) + for i, e := range recovered { + require.Equal(t, minermodel.SectorRecovered, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + faulted := events[minermodel.SectorFaulted] + sort.Slice(faulted, func(i, j int) bool { + return faulted[i].SectorID < faulted[j].SectorID + }) + for i, e := range faulted { + require.Equal(t, minermodel.SectorFaulted, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + recovering := events[minermodel.SectorRecovering] + sort.Slice(recovering, func(i, j int) bool { + return recovering[i].SectorID < recovering[j].SectorID + }) + for i, e := range recovering { + require.Equal(t, minermodel.SectorRecovering, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } +} + +func TestExtractMinerSectorEvents(t *testing.T) { + minerContext := new(mocks.MockMinerState) + ts := testutil.MustFakeTipSet(t, 10) + addr := testutil.MustMakeAddress(t, 100) + minerContext.On("CurrentTipSet").Return(ts) + minerContext.On("Address").Return(addr) + sectorChanges := &miner.SectorChanges{ + // 4 sectors added, 0 and 1 contains deals + Added: generateFakeSectorOnChainInfos(map[uint64][]abi.DealID{ + 0: {0, 1, 2}, + 1: {4, 5, 6}, + 2: {}, + 3: {}, + }), + // 2 sectors extended + Extended: []miner.SectorModification{ + { + From: generateFakeSectorOnChainInfo(0), + To: generateFakeSectorOnChainInfo(0), + }, + { + From: generateFakeSectorOnChainInfo(1), + To: generateFakeSectorOnChainInfo(1), + }, + }, + // 1 sector snapped + Snapped: []miner.SectorModification{ + { + From: generateFakeSectorOnChainInfo(0), + To: generateFakeSectorOnChainInfo(0), + }, + }, + // 6 sectors removed, this value is ignored as sectors can be removed for a variety of reasons. + // sector removal is tested in TestExtractMinerPartitionsDiff + Removed: generateFakeSectorOnChainInfos(map[uint64][]abi.DealID{ + 0: {}, + 1: {}, + 2: {}, + 3: {}, + 4: {}, + 5: {}, + }), + } + result := minerex.ExtractMinerSectorEvents(minerContext, sectorChanges) + require.NotNil(t, result) + require.Len(t, result, 7) + + events := make(map[string][]*minermodel.MinerSectorEvent) + for _, res := range result { + events[res.Event] = append(events[res.Event], res) + } + + added := events[minermodel.SectorAdded] + sort.Slice(added, func(i, j int) bool { + return added[i].SectorID < added[j].SectorID + }) + for i, e := range added { + require.Equal(t, minermodel.SectorAdded, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + cc := events[minermodel.CommitCapacityAdded] + sort.Slice(cc, func(i, j int) bool { + return cc[i].SectorID < cc[j].SectorID + }) + for i, e := range cc { + require.Equal(t, minermodel.CommitCapacityAdded, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i+2, e.SectorID) + } + + extended := events[minermodel.SectorExtended] + sort.Slice(extended, func(i, j int) bool { + return extended[i].SectorID < extended[j].SectorID + }) + for i, e := range extended { + require.Equal(t, minermodel.SectorExtended, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + snapped := events[minermodel.SectorSnapped] + sort.Slice(snapped, func(i, j int) bool { + return snapped[i].SectorID < snapped[j].SectorID + }) + for i, e := range snapped { + require.Equal(t, minermodel.SectorSnapped, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } +} + +func TestExtractSectorEvents(t *testing.T) { + ctx := context.Background() + minerContext := new(mocks.MockMinerState) + parentMinerState := new(minerstatemocks.State) + currentMinerState := new(minerstatemocks.State) + ts := testutil.MustFakeTipSet(t, 10) + addr := testutil.MustMakeAddress(t, 100) + minerContext.On("ParentState").Return(parentMinerState) + minerContext.On("CurrentState").Return(currentMinerState) + minerContext.On("CurrentTipSet").Return(ts) + minerContext.On("Address").Return(addr) + numPrecommitChanges := uint64(10) + fakePrecommitChanges := generateFakeSectorPreCommitChanges(numPrecommitChanges, 5) + numSectorChanges := uint64(7) + sectorChanges := &miner.SectorChanges{ + // 4 sectors added, 0 and 1 contains deals + Added: generateFakeSectorOnChainInfos(map[uint64][]abi.DealID{ + 0: {0, 1, 2}, + 1: {4, 5, 6}, + 2: {}, + 3: {}, + }), + // 2 sectors extended + Extended: []miner.SectorModification{ + { + From: generateFakeSectorOnChainInfo(0), + To: generateFakeSectorOnChainInfo(0), + }, + { + From: generateFakeSectorOnChainInfo(1), + To: generateFakeSectorOnChainInfo(1), + }, + }, + // 1 sector snapped + Snapped: []miner.SectorModification{ + { + From: generateFakeSectorOnChainInfo(0), + To: generateFakeSectorOnChainInfo(0), + }, + }, + // 6 sectors removed, this value is ignored as sectors can be removed for a variety of reasons. + // sector removal is tested in TestExtractMinerPartitionsDiff + Removed: generateFakeSectorOnChainInfos(map[uint64][]abi.DealID{ + 0: {}, + 1: {}, + 2: {}, + 3: {}, + 4: {}, + 5: {}, + }), + } + numTerminated := uint64(2) + numRecovered := uint64(3) + numFaulted := uint64(4) + numRecovering := uint64(5) + // deadline 0 partition 1 has 2 removed sectors, 3 recovered, 4 faulted, and 5 recovering, total of 15 sector events + fakeDl := generateFakeDeadlinesDiff(0, 1, numTerminated, numRecovered, numFaulted, numRecovering) + currentMinerState.On("LoadSectors", mock.Anything).Return([]*miner.SectorOnChainInfo{}, nil) + + result, err := minerex.ExtractSectorEvents(ctx, minerContext, sectorChanges, fakePrecommitChanges, fakeDl) + require.NoError(t, err) + require.NotNil(t, result) + require.Len(t, result, int(numPrecommitChanges+numSectorChanges+numTerminated+numRecovered+numFaulted+numRecovering)) + + events := make(map[string][]*minermodel.MinerSectorEvent) + for _, res := range result { + events[res.Event] = append(events[res.Event], res) + } + + added := events[minermodel.SectorAdded] + sort.Slice(added, func(i, j int) bool { + return added[i].SectorID < added[j].SectorID + }) + for i, e := range added { + require.Equal(t, minermodel.SectorAdded, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + cc := events[minermodel.CommitCapacityAdded] + sort.Slice(cc, func(i, j int) bool { + return cc[i].SectorID < cc[j].SectorID + }) + for i, e := range cc { + require.Equal(t, minermodel.CommitCapacityAdded, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i+2, e.SectorID) + } + + extended := events[minermodel.SectorExtended] + sort.Slice(extended, func(i, j int) bool { + return extended[i].SectorID < extended[j].SectorID + }) + for i, e := range extended { + require.Equal(t, minermodel.SectorExtended, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + snapped := events[minermodel.SectorSnapped] + sort.Slice(snapped, func(i, j int) bool { + return snapped[i].SectorID < snapped[j].SectorID + }) + for i, e := range snapped { + require.Equal(t, minermodel.SectorSnapped, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + terminated := events[minermodel.SectorTerminated] + sort.Slice(terminated, func(i, j int) bool { + return terminated[i].SectorID < terminated[j].SectorID + }) + for i, e := range terminated { + require.Equal(t, minermodel.SectorTerminated, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + recovered := events[minermodel.SectorRecovered] + sort.Slice(recovered, func(i, j int) bool { + return recovered[i].SectorID < recovered[j].SectorID + }) + for i, e := range recovered { + require.Equal(t, minermodel.SectorRecovered, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + faulted := events[minermodel.SectorFaulted] + sort.Slice(faulted, func(i, j int) bool { + return faulted[i].SectorID < faulted[j].SectorID + }) + for i, e := range faulted { + require.Equal(t, minermodel.SectorFaulted, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + recovering := events[minermodel.SectorRecovering] + sort.Slice(recovering, func(i, j int) bool { + return recovering[i].SectorID < recovering[j].SectorID + }) + for i, e := range recovering { + require.Equal(t, minermodel.SectorRecovering, e.Event) + require.Equal(t, int64(ts.Height()), e.Height) + require.Equal(t, addr.String(), e.MinerID) + require.Equal(t, ts.ParentState().String(), e.StateRoot) + require.EqualValues(t, i, e.SectorID) + } + + precommit := events[minermodel.PreCommitAdded] + sort.Slice(precommit, func(i, j int) bool { + return precommit[i].SectorID < precommit[j].SectorID + }) + for i, res := range precommit { + require.Equal(t, addr.String(), res.MinerID) + require.Equal(t, int64(ts.Height()), res.Height) + require.Equal(t, ts.ParentState().String(), res.StateRoot) + require.Equal(t, minermodel.PreCommitAdded, res.Event) + require.EqualValues(t, fakePrecommitChanges.Added[i].Info.SectorNumber, res.SectorID) + } +} + +func generateFakeSectorOnChainInfo(sectorNumber uint64, dealIDs ...abi.DealID) miner.SectorOnChainInfo { + return miner.SectorOnChainInfo{ + SectorNumber: abi.SectorNumber(sectorNumber), + DealIDs: dealIDs, + // faked + SealProof: 0, + SealedCID: cid.Undef, + Activation: 0, + Expiration: 0, + DealWeight: abi.DealWeight{}, + VerifiedDealWeight: abi.DealWeight{}, + InitialPledge: abi.TokenAmount{}, + ExpectedDayReward: abi.TokenAmount{}, + ExpectedStoragePledge: abi.TokenAmount{}, + SectorKeyCID: nil, + } +} + +func generateFakeSectorOnChainInfos(sectors map[uint64][]abi.DealID) []miner.SectorOnChainInfo { + var out []miner.SectorOnChainInfo + for sectorNumber, deals := range sectors { + out = append(out, generateFakeSectorOnChainInfo(sectorNumber, deals...)) + } + return out +} + +func generateFakeSectorPreCommitInfo(sectorNumber uint64) miner.SectorPreCommitInfo { + return miner.SectorPreCommitInfo{ + SealProof: 0, + SectorNumber: abi.SectorNumber(sectorNumber), + SealedCID: cid.Undef, + SealRandEpoch: 0, + DealIDs: []abi.DealID{}, + Expiration: 0, + ReplaceCapacity: false, + ReplaceSectorDeadline: 0, + ReplaceSectorPartition: 0, + ReplaceSectorNumber: 0, + } +} + +func generateFakeSectorPreCommitOnChainInfo(sectorNumber uint64) miner.SectorPreCommitOnChainInfo { + return miner.SectorPreCommitOnChainInfo{ + Info: generateFakeSectorPreCommitInfo(sectorNumber), + PreCommitDeposit: abi.NewTokenAmount(0), + PreCommitEpoch: 0, + DealWeight: big.Zero(), + VerifiedDealWeight: big.Zero(), + } +} + +func generateFakeSectorPreCommitChanges(add uint64, rm uint64) *miner.PreCommitChanges { + added := make([]miner.SectorPreCommitOnChainInfo, add) + removed := make([]miner.SectorPreCommitOnChainInfo, rm) + for i := uint64(0); i < add; i++ { + added[i] = generateFakeSectorPreCommitOnChainInfo(i) + } + for i := uint64(0); i < rm; i++ { + removed[i] = generateFakeSectorPreCommitOnChainInfo(i) + } + + return &miner.PreCommitChanges{ + Added: added, + Removed: removed, + } +} + +func generateFakePartitionDiff(removed, recovered, faulted, recovering uint64) *miner.PartitionDiff { + rm := bitfield.New() + for i := uint64(0); i < removed; i++ { + rm.Set(i) + } + rec := bitfield.New() + for i := uint64(0); i < recovered; i++ { + rec.Set(i) + } + flt := bitfield.New() + for i := uint64(0); i < faulted; i++ { + flt.Set(i) + } + recing := bitfield.New() + for i := uint64(0); i < recovering; i++ { + recing.Set(i) + } + return &miner.PartitionDiff{ + Removed: rm, + Recovered: rec, + Faulted: flt, + Recovering: recing, + } +} + +func generateFakDeadlineDiff(partition uint64, removed, recovered, faulted, recovering uint64) miner.DeadlineDiff { + partDiff := generateFakePartitionDiff(removed, recovered, faulted, recovering) + return map[uint64]*miner.PartitionDiff{ + partition: partDiff, + } +} + +func generateFakeDeadlinesDiff(deadline uint64, partition uint64, removed, recovered, faulted, recovering uint64) miner.DeadlinesDiff { + out := make(map[uint64]miner.DeadlineDiff, 1) + dld := generateFakDeadlineDiff(partition, removed, recovered, faulted, recovering) + out[deadline] = dld + return out +}