Skip to content

Commit 3d4abd9

Browse files
committed
feat(miner): externalise SectorOnChainInfo from AMT
1 parent 5f30872 commit 3d4abd9

File tree

5 files changed

+162
-9
lines changed

5 files changed

+162
-9
lines changed

builtin/v15/miner/miner_types.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,13 @@ func (sa Sectors) Get(sectorNumber abi.SectorNumber) (info *SectorOnChainInfo, f
317317
return &res, true, nil
318318
}
319319

320+
func (sa Sectors) ForEach(cb func(abi.SectorNumber, *SectorOnChainInfo) error) error {
321+
var sector SectorOnChainInfo
322+
return sa.Array.ForEach(&sector, func(i int64) error {
323+
return cb(abi.SectorNumber(i), &sector)
324+
})
325+
}
326+
320327
// VestingFunds represents the vesting table state for the miner.
321328
// It is a slice of (VestingEpoch, VestingAmount).
322329
// The slice will always be sorted by the VestingEpoch.

builtin/v16/migration/miner.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package migration
2+
3+
import (
4+
"context"
5+
6+
"github.com/filecoin-project/go-state-types/abi"
7+
miner15 "github.com/filecoin-project/go-state-types/builtin/v15/miner"
8+
miner16 "github.com/filecoin-project/go-state-types/builtin/v16/miner"
9+
"github.com/filecoin-project/go-state-types/builtin/v16/util/adt"
10+
"github.com/filecoin-project/go-state-types/migration"
11+
"github.com/ipfs/go-cid"
12+
cbor "github.com/ipfs/go-ipld-cbor"
13+
"golang.org/x/xerrors"
14+
)
15+
16+
type minerMigrator struct {
17+
OutCodeCID cid.Cid
18+
}
19+
20+
func newMinerMigrator(_ context.Context, _ cbor.IpldStore, outCode cid.Cid) (*minerMigrator, error) {
21+
return &minerMigrator{
22+
OutCodeCID: outCode,
23+
}, nil
24+
}
25+
26+
func (m *minerMigrator) MigrateState(ctx context.Context, store cbor.IpldStore, in migration.ActorMigrationInput) (result *migration.ActorMigrationResult, err error) {
27+
var inState miner15.State
28+
if err := store.Get(ctx, in.Head, &inState); err != nil {
29+
return nil, xerrors.Errorf("failed to load miner state for %s: %w", in.Address, err)
30+
}
31+
32+
ctxStore := adt.WrapStore(ctx, store)
33+
34+
inSectors, err := miner15.LoadSectors(ctxStore, inState.Sectors)
35+
if err != nil {
36+
return nil, xerrors.Errorf("failed to load sectors array: %w", err)
37+
}
38+
39+
arr, err := adt.MakeEmptyArray(ctxStore, miner16.SectorsAmtBitwidth)
40+
if err != nil {
41+
return nil, xerrors.Errorf("failed to create sectors array: %w", err)
42+
}
43+
outSectors := miner16.Sectors{Array: arr, Store: ctxStore}
44+
45+
inSectors.ForEach(func(sn abi.SectorNumber, soci *miner15.SectorOnChainInfo) error {
46+
return outSectors.Set(sn, &miner16.SectorOnChainInfo{
47+
SectorNumber: soci.SectorNumber,
48+
SealProof: soci.SealProof,
49+
SealedCID: soci.SealedCID,
50+
DealIDs: soci.DealIDs,
51+
Activation: soci.Activation,
52+
Expiration: soci.Expiration,
53+
DealWeight: soci.DealWeight,
54+
VerifiedDealWeight: soci.VerifiedDealWeight,
55+
InitialPledge: soci.InitialPledge,
56+
ExpectedDayReward: soci.ExpectedDayReward,
57+
ExpectedStoragePledge: soci.ExpectedStoragePledge,
58+
PowerBaseEpoch: soci.PowerBaseEpoch,
59+
ReplacedDayReward: soci.ReplacedDayReward,
60+
SectorKeyCID: soci.SectorKeyCID,
61+
Flags: miner16.SectorOnChainInfoFlags(soci.Flags),
62+
})
63+
})
64+
65+
outSectorsRoot, err := outSectors.Root()
66+
if err != nil {
67+
return nil, xerrors.Errorf("failed to flush sectors: %w", err)
68+
}
69+
70+
// TODO: implement cached migrator with diff, see v13 for example
71+
72+
outState := miner16.State{
73+
Info: inState.Info,
74+
PreCommitDeposits: inState.PreCommitDeposits,
75+
LockedFunds: inState.LockedFunds,
76+
VestingFunds: inState.VestingFunds,
77+
FeeDebt: inState.FeeDebt,
78+
InitialPledge: inState.InitialPledge,
79+
PreCommittedSectors: inState.PreCommittedSectors,
80+
PreCommittedSectorsCleanUp: inState.PreCommittedSectorsCleanUp,
81+
AllocatedSectors: inState.AllocatedSectors,
82+
Sectors: outSectorsRoot,
83+
ProvingPeriodStart: inState.ProvingPeriodStart,
84+
CurrentDeadline: inState.CurrentDeadline,
85+
Deadlines: inState.Deadlines,
86+
EarlyTerminations: inState.EarlyTerminations,
87+
DeadlineCronActive: inState.DeadlineCronActive,
88+
}
89+
90+
newHead, err := store.Put(ctx, &outState)
91+
if err != nil {
92+
return nil, xerrors.Errorf("failed to put new state: %w", err)
93+
}
94+
95+
return &migration.ActorMigrationResult{
96+
NewCodeCID: m.MigratedCodeCID(),
97+
NewHead: newHead,
98+
}, nil
99+
}
100+
101+
func (m *minerMigrator) MigratedCodeCID() cid.Cid {
102+
return m.OutCodeCID
103+
}
104+
105+
func (m *minerMigrator) Deferred() bool {
106+
return false
107+
}
108+
109+
var _ migration.ActorMigration = (*minerMigrator)(nil)

builtin/v16/migration/top.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ func MigrateStateTree(ctx context.Context, store cbor.IpldStore, newManifestCID
9090
return cid.Undef, xerrors.Errorf("incomplete migration specification with %d code CIDs, need %d", len(migrations)+len(deferredCodeIDs), len(oldManifestData.Entries))
9191
}
9292

93+
miner16Cid, ok := newManifest.Get(manifest.MinerKey)
94+
if !ok {
95+
return cid.Undef, xerrors.Errorf("code cid for miner actor not found in new manifest")
96+
}
97+
98+
minerMig, err := newMinerMigrator(ctx, store, miner16Cid)
99+
if err != nil {
100+
return cid.Undef, xerrors.Errorf("failed to create miner migrator: %w", err)
101+
}
102+
103+
migrations[miner16Cid] = migration.CachedMigration(cache, minerMig)
104+
93105
actorsOut, err := migration.RunMigration(ctx, cfg, cache, store, log, actorsIn, migrations)
94106
if err != nil {
95107
return cid.Undef, xerrors.Errorf("failed to run migration: %w", err)

builtin/v16/miner/miner_state.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ type State struct {
4747
//
4848
// Sectors are removed from this AMT when the partition to which the
4949
// sector belongs is compacted.
50-
Sectors cid.Cid // Array, AMT[SectorNumber]SectorOnChainInfo (sparse)
50+
Sectors cid.Cid // Array, AMT[SectorNumber]*SectorOnChainInfo (sparse)
5151

5252
// DEPRECATED. This field will change names and no longer be updated every proving period in a future upgrade
5353
// The first epoch in this miner's current proving period. This is the first epoch in which a PoSt for a

builtin/v16/miner/miner_types.go

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,31 +272,32 @@ func LoadExpirationQueue(store adt.Store, root cid.Cid, quant builtin.QuantSpec,
272272
}
273273
return ExpirationQueue{arr, quant}, nil
274274
}
275+
275276
func LoadSectors(store adt.Store, root cid.Cid) (Sectors, error) {
276277
sectorsArr, err := adt.AsArray(store, root, SectorsAmtBitwidth)
277278
if err != nil {
278279
return Sectors{}, err
279280
}
280-
return Sectors{sectorsArr}, nil
281+
return Sectors{sectorsArr, store}, nil
281282
}
282283

283284
// Sectors is a helper type for accessing/modifying a miner's sectors. It's safe
284285
// to pass this object around as needed.
285286
type Sectors struct {
286287
*adt.Array
288+
adt.Store
287289
}
288290

289291
func (sa Sectors) Load(sectorNos bitfield.BitField) ([]*SectorOnChainInfo, error) {
290292
var sectorInfos []*SectorOnChainInfo
291293
if err := sectorNos.ForEach(func(i uint64) error {
292-
var sectorOnChain SectorOnChainInfo
293-
found, err := sa.Array.Get(i, &sectorOnChain)
294-
if err != nil {
294+
if si, found, err := sa.Get(abi.SectorNumber(i)); err != nil {
295295
return xc.ErrIllegalState.Wrapf("failed to load sector %v: %w", abi.SectorNumber(i), err)
296296
} else if !found {
297297
return xc.ErrNotFound.Wrapf("can't find sector %d", i)
298+
} else {
299+
sectorInfos = append(sectorInfos, si)
298300
}
299-
sectorInfos = append(sectorInfos, &sectorOnChain)
300301
return nil
301302
}); err != nil {
302303
// Keep the underlying error code, unless the error was from
@@ -308,15 +309,39 @@ func (sa Sectors) Load(sectorNos bitfield.BitField) ([]*SectorOnChainInfo, error
308309
}
309310

310311
func (sa Sectors) Get(sectorNumber abi.SectorNumber) (info *SectorOnChainInfo, found bool, err error) {
311-
var res SectorOnChainInfo
312-
if found, err := sa.Array.Get(uint64(sectorNumber), &res); err != nil {
313-
return nil, false, xerrors.Errorf("failed to get sector %d: %w", sectorNumber, err)
312+
var c cbg.CborCid
313+
if found, err := sa.Array.Get(uint64(sectorNumber), &c); err != nil {
314+
return nil, false, xerrors.Errorf("failed to get sector link %d: %w", sectorNumber, err)
314315
} else if !found {
315316
return nil, false, nil
316317
}
318+
var res SectorOnChainInfo
319+
if err := sa.Store.Get(sa.Store.Context(), cid.Cid(c), &res); err != nil {
320+
return nil, false, xerrors.Errorf("failed to load sector %d: %w", sectorNumber, err)
321+
}
317322
return &res, true, nil
318323
}
319324

325+
func (sa Sectors) ForEach(cb func(abi.SectorNumber, *SectorOnChainInfo) error) error {
326+
var c cbg.CborCid
327+
return sa.Array.ForEach(&c, func(i int64) error {
328+
var info SectorOnChainInfo
329+
if err := sa.Store.Get(sa.Store.Context(), cid.Cid(c), &info); err != nil {
330+
return err
331+
}
332+
return cb(abi.SectorNumber(i), &info)
333+
})
334+
}
335+
336+
func (sa Sectors) Set(sectorNumber abi.SectorNumber, info *SectorOnChainInfo) error {
337+
c, err := sa.Store.Put(sa.Store.Context(), info)
338+
if err != nil {
339+
return xerrors.Errorf("failed to store sector info: %w", err)
340+
}
341+
cb := cbg.CborCid(c)
342+
return sa.Array.Set(uint64(sectorNumber), &cb)
343+
}
344+
320345
// VestingFunds represents the vesting table state for the miner.
321346
// It is a slice of (VestingEpoch, VestingAmount).
322347
// The slice will always be sorted by the VestingEpoch.

0 commit comments

Comments
 (0)