Skip to content

Commit b4577fb

Browse files
committed
create function for migrating builtin actors with only code changes
1 parent fe5b63f commit b4577fb

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

chain/consensus/filcns/upgrades.go

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@ package filcns
22

33
import (
44
"context"
5+
"fmt"
56
"runtime"
67
"time"
78

9+
system8 "github.com/filecoin-project/go-state-types/builtin/v8/system"
10+
11+
"github.com/filecoin-project/go-state-types/manifest"
12+
13+
"github.com/filecoin-project/lotus/chain/actors/builtin/system"
14+
815
"github.com/filecoin-project/specs-actors/v8/actors/migration/nv16"
916

1017
"github.com/docker/go-units"
@@ -33,6 +40,9 @@ import (
3340
"github.com/filecoin-project/specs-actors/v3/actors/migration/nv10"
3441
"github.com/filecoin-project/specs-actors/v4/actors/migration/nv12"
3542
"github.com/filecoin-project/specs-actors/v5/actors/migration/nv13"
43+
manifest8 "github.com/filecoin-project/specs-actors/v8/actors/builtin/manifest"
44+
states8 "github.com/filecoin-project/specs-actors/v8/actors/states"
45+
adt8 "github.com/filecoin-project/specs-actors/v8/actors/util/adt"
3646

3747
"github.com/filecoin-project/lotus/blockstore"
3848
"github.com/filecoin-project/lotus/build"
@@ -1431,6 +1441,149 @@ func upgradeActorsV8Common(
14311441
return newRoot, nil
14321442
}
14331443

1444+
func UpgradeActorsCode(ctx context.Context, sm *stmgr.StateManager, newActorsManifestCid cid.Cid, root cid.Cid) (cid.Cid, error) { // nolint
1445+
buf := blockstore.NewTieredBstore(sm.ChainStore().StateBlockstore(), blockstore.NewMemorySync())
1446+
store := store.ActorStore(ctx, buf)
1447+
adtStore := adt8.WrapStore(ctx, store)
1448+
1449+
// Load the state root.
1450+
var stateRoot types.StateRoot
1451+
if err := store.Get(ctx, root, &stateRoot); err != nil {
1452+
return cid.Undef, xerrors.Errorf("failed to decode state root: %w", err)
1453+
}
1454+
1455+
if stateRoot.Version != types.StateTreeVersion4 {
1456+
return cid.Undef, xerrors.Errorf(
1457+
"expected state root version 4 for actors code upgrade, got %d",
1458+
stateRoot.Version,
1459+
)
1460+
}
1461+
1462+
actorsIn, err := states8.LoadTree(adtStore, stateRoot.Actors)
1463+
systemActor, ok, err := actorsIn.GetActor(system.Address)
1464+
if !ok {
1465+
return cid.Undef, xerrors.Errorf("failed to get system actor: %w", err)
1466+
}
1467+
systemActorType := types.Actor{
1468+
Code: systemActor.Code,
1469+
Head: systemActor.Head,
1470+
Nonce: systemActor.CallSeqNum,
1471+
Balance: systemActor.Balance,
1472+
}
1473+
systemActorState, err := system.Load(store, &systemActorType)
1474+
oldActorsManifestCid := systemActorState.GetBuiltinActors()
1475+
1476+
// load old manifest
1477+
var oldManifest manifest8.Manifest
1478+
if err := adtStore.Get(ctx, oldActorsManifestCid, &oldManifest); err != nil {
1479+
return cid.Undef, xerrors.Errorf("error reading old actor manifest: %w", err)
1480+
}
1481+
if err := oldManifest.Load(ctx, adtStore); err != nil {
1482+
return cid.Undef, xerrors.Errorf("error loading old actor manifest: %w", err)
1483+
}
1484+
1485+
// load new manifest
1486+
var newManifest manifest8.Manifest
1487+
if err := adtStore.Get(ctx, newActorsManifestCid, &newManifest); err != nil {
1488+
return cid.Undef, xerrors.Errorf("error reading new actor manifest: %w", err)
1489+
}
1490+
if err := newManifest.Load(ctx, adtStore); err != nil {
1491+
return cid.Undef, xerrors.Errorf("error loading new actor manifest: %w", err)
1492+
}
1493+
1494+
// Maps prior version code CIDs to migration functions.
1495+
migrations := make(map[cid.Cid]cid.Cid)
1496+
1497+
newManifestData := manifest.ManifestData{}
1498+
if err := store.Get(ctx, newManifest.Data, &newManifestData); err != nil {
1499+
return cid.Undef, xerrors.Errorf("error loading new manifest data: %w", err)
1500+
}
1501+
1502+
for _, entry := range newManifestData.Entries {
1503+
oldCodeCid, ok := oldManifest.Get(entry.Name)
1504+
if !ok {
1505+
return cid.Undef, xerrors.Errorf("code cid for %s actor not found in manifest", entry.Name)
1506+
}
1507+
migrations[oldCodeCid] = entry.Code
1508+
}
1509+
1510+
if len(migrations) != 11 {
1511+
panic(fmt.Sprintf("incomplete migration specification with %d code CIDs", len(migrations)))
1512+
}
1513+
startTime := time.Now()
1514+
1515+
// Load output state tree
1516+
actorsOut, err := states8.NewTree(adtStore)
1517+
if err != nil {
1518+
return cid.Undef, err
1519+
}
1520+
1521+
// Insert migrated records in output state tree.
1522+
err = actorsIn.ForEach(func(addr address.Address, actorIn *states8.Actor) error {
1523+
var newActor states8.Actor
1524+
newCid, ok := migrations[actorIn.Code]
1525+
if !ok {
1526+
return xerrors.Errorf("new code cid for system actor not found in migrations for actor %s", addr)
1527+
}
1528+
if addr == system.Address {
1529+
newSystemState := system8.State{BuiltinActors: newManifest.Data}
1530+
systemStateHead, err := store.Put(ctx, &newSystemState)
1531+
if err != nil {
1532+
return xerrors.Errorf("could not get system actor state head", err)
1533+
}
1534+
newActor = states8.Actor{
1535+
Code: newCid,
1536+
Head: systemStateHead,
1537+
CallSeqNum: actorIn.CallSeqNum,
1538+
Balance: actorIn.Balance,
1539+
}
1540+
} else {
1541+
newActor = states8.Actor{
1542+
Code: newCid,
1543+
Head: actorIn.Head,
1544+
CallSeqNum: actorIn.CallSeqNum,
1545+
Balance: actorIn.Balance,
1546+
}
1547+
}
1548+
err = actorsOut.SetActor(addr, &newActor)
1549+
if err != nil {
1550+
return xerrors.Errorf("could not set actor at address %s: %w", addr, err)
1551+
}
1552+
1553+
return nil
1554+
})
1555+
1556+
elapsed := time.Since(startTime)
1557+
log.Infof("All done after %v. Flushing state tree root.", elapsed)
1558+
newHamtRoot, err := actorsOut.Flush()
1559+
if err != nil {
1560+
return cid.Undef, xerrors.Errorf("failed to flush new actors: %w", err)
1561+
}
1562+
1563+
// Persist the result.
1564+
newRoot, err := store.Put(ctx, &types.StateRoot{
1565+
Version: types.StateTreeVersion4,
1566+
Actors: newHamtRoot,
1567+
Info: stateRoot.Info,
1568+
})
1569+
if err != nil {
1570+
return cid.Undef, xerrors.Errorf("failed to persist new state root: %w", err)
1571+
}
1572+
1573+
// Persist the new tree.
1574+
1575+
{
1576+
from := buf
1577+
to := buf.Read()
1578+
1579+
if err := vm.Copy(ctx, from, to, newRoot); err != nil {
1580+
return cid.Undef, xerrors.Errorf("copying migrated tree: %w", err)
1581+
}
1582+
}
1583+
1584+
return newRoot, nil
1585+
}
1586+
14341587
type migrationLogger struct{}
14351588

14361589
func (ml migrationLogger) Log(level rt.LogLevel, msg string, args ...interface{}) {

0 commit comments

Comments
 (0)