@@ -2,9 +2,16 @@ package filcns
22
33import (
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+
14341587type migrationLogger struct {}
14351588
14361589func (ml migrationLogger ) Log (level rt.LogLevel , msg string , args ... interface {}) {
0 commit comments