@@ -475,6 +475,10 @@ func DefaultUpgradeSchedule(cf *ChainFork, upgradeHeight *config.ForkUpgradeConf
475475 Height : upgradeHeight .UpgradeTockHeight ,
476476 Network : network .Version26 ,
477477 Migration : nil ,
478+ }, {
479+ Height : upgradeHeight .UpgradeTockFixHeight ,
480+ Network : network .Version26 ,
481+ Migration : cf .UpgradeActorsV16Fix ,
478482 },
479483 }
480484
@@ -2787,6 +2791,10 @@ var (
27872791
27882792 calibnetv13BuggyManifestCID1 = cid .MustParse ("bafy2bzacea4firkyvt2zzdwqjrws5pyeluaesh6uaid246tommayr4337xpmi" )
27892793 calibnetv13CorrectManifestCID1 = cid .MustParse ("bafy2bzacect4ktyujrwp6mjlsitnpvuw2pbuppz6w52sfljyo4agjevzm75qs" )
2794+
2795+ // Some v16.0.0 bundles are included in the v16 bundles tarball along with the v16.0.1 bundles.
2796+ // But the v16.0.0 ones have a -v16.0.0.car suffix instead of just .car.
2797+ v1600BundleSuffix = "v16.0.0"
27902798)
27912799
27922800func (c * ChainFork ) upgradeActorsV12Common (
@@ -3661,9 +3669,50 @@ func (c *ChainFork) upgradeActorsV16Common(
36613669) (cid.Cid , error ) {
36623670 writeStore := blockstoreutil .NewAutobatch (ctx , c .bs , units .GiB / 4 )
36633671 adtStore := adt .WrapStore (ctx , cbor .NewCborStore (writeStore ))
3664- // ensure that the manifest is loaded in the blockstore
3665- if err := actors .LoadBundles (ctx , writeStore , actorstypes .Version16 ); err != nil {
3666- return cid .Undef , fmt .Errorf ("failed to load manifest bundle: %w" , err )
3672+
3673+ manifest , ok := actors .GetManifest (actorstypes .Version16 )
3674+ if ! ok {
3675+ return cid .Undef , fmt .Errorf ("no manifest CID for v16 upgrade" )
3676+ }
3677+
3678+ if c .forkUpgrade .UpgradeTockFixHeight > 0 {
3679+ // If there is a UpgradeTockFixHeight height set, then we are expected to load v16.0.0 here and
3680+ // then UpgradeTockFixHeight will take care of setting the actors to v16.0.1. If it's not set
3681+ // then there's nothing to fix and we'll proceed as normal.
3682+
3683+ var initState init12.State
3684+ if actorsIn , err := vmstate .LoadState (ctx , adtStore , root ); err != nil {
3685+ return cid .Undef , fmt .Errorf ("loading state tree: %w" , err )
3686+ } else if initActor , found , err := actorsIn .GetActor (ctx , builtin .InitActorAddr ); err != nil || ! found {
3687+ return cid .Undef , fmt .Errorf ("failed to get system actor: %w" , err )
3688+ } else if err := adtStore .Get (ctx , initActor .Head , & initState ); err != nil {
3689+ return cid .Undef , fmt .Errorf ("failed to get system actor state: %w" , err )
3690+ }
3691+
3692+ // The v16.0.0 bundle is embedded in the v16 tarball, we just need to load it with the right
3693+ // name (builtin-actors-<network>-v16.0.0.car).
3694+ embedded , ok := actors .GetEmbeddedBuiltinActorsBundle (actorstypes .Version16 , fmt .Sprintf ("%s-%s" , initState .NetworkName , v1600BundleSuffix ))
3695+ if ! ok {
3696+ return cid .Undef , fmt .Errorf ("didn't find v16.0.0 %s bundle with suffix %s" , initState .NetworkName , v1600BundleSuffix )
3697+ }
3698+
3699+ var err error
3700+ manifest , err = actors .LoadBundle (ctx , writeStore , bytes .NewReader (embedded ))
3701+ if err != nil {
3702+ return cid .Undef , fmt .Errorf ("failed to load buggy calibnet bundle: %w" , err )
3703+ }
3704+
3705+ // Sanity check that we loaded what we were supposed to
3706+ if metadata := actors .BuggyBuiltinActorsMetadataForNetwork (initState .NetworkName , actorstypes .Version16 ); metadata == nil {
3707+ return cid .Undef , fmt .Errorf ("didn't find expected v16.0.0 bundle metadata for %s" , initState .NetworkName )
3708+ } else if manifest != metadata .ManifestCid {
3709+ return cid .Undef , fmt .Errorf ("didn't load expected v16.0.0 bundle manifest: %s != %s" , manifest , metadata .ManifestCid )
3710+ }
3711+ } else {
3712+ // ensure that the manifest is loaded in the blockstore
3713+ if err := actors .LoadBundles (ctx , c .bs , actorstypes .Version16 ); err != nil {
3714+ return cid .Undef , fmt .Errorf ("failed to load manifest bundle: %w" , err )
3715+ }
36673716 }
36683717
36693718 // Load the state root.
@@ -3679,11 +3728,6 @@ func (c *ChainFork) upgradeActorsV16Common(
36793728 )
36803729 }
36813730
3682- manifest , ok := actors .GetManifest (actorstypes .Version16 )
3683- if ! ok {
3684- return cid .Undef , fmt .Errorf ("no manifest CID for v16 upgrade" )
3685- }
3686-
36873731 // Perform the migration
36883732 newHamtRoot , err := nv25 .MigrateStateTree (ctx , adtStore , manifest , stateRoot .Actors , epoch , config ,
36893733 migrationLogger {}, cache )
@@ -3713,6 +3757,185 @@ func (c *ChainFork) upgradeActorsV16Common(
37133757 return newRoot , nil
37143758}
37153759
3760+ // UpgradeActorsV16Fix should _not_ be used on mainnet. It performs an upgrade to v16.0.1 on top of
3761+ // the existing v16.0.0 that was already deployed.
3762+ // The actual mainnet upgrade is performed with UpgradeActorsV16 with the v16.0.1 bundle.
3763+ // This upgrade performs an inefficient form of the migration that go-state-types normally performs.
3764+ func (c * ChainFork ) UpgradeActorsV16Fix (
3765+ ctx context.Context ,
3766+ cache MigrationCache ,
3767+ root cid.Cid ,
3768+ epoch abi.ChainEpoch ,
3769+ ts * types.TipSet ,
3770+ ) (cid.Cid , error ) {
3771+ stateStore := c .bs
3772+ adtStore := adt .WrapStore (ctx , cbor .NewCborStore (stateStore ))
3773+
3774+ // Get the real v16 manifest, which should be for v16.0.1
3775+ manifestCid , ok := actors .GetManifest (actorstypes .Version16 )
3776+ if ! ok {
3777+ return cid .Undef , fmt .Errorf ("no manifest CID for v16 upgrade" )
3778+ }
3779+ // ensure that the manifest is loaded in the blockstore, it will load the correct v16.0.1 bundle
3780+ if err := actors .LoadBundles (ctx , stateStore , actorstypes .Version16 ); err != nil {
3781+ return cid .Undef , fmt .Errorf ("failed to load manifest bundle: %w" , err )
3782+ }
3783+
3784+ // Load input state tree
3785+ actorsIn , err := vmstate .LoadState (ctx , adtStore , root )
3786+ if err != nil {
3787+ return cid .Undef , fmt .Errorf ("loading state tree: %w" , err )
3788+ }
3789+
3790+ // load old manifest data
3791+ oldSystemActor , found , err := actorsIn .GetActor (ctx , builtin .SystemActorAddr )
3792+ if err != nil {
3793+ return cid .Undef , fmt .Errorf ("failed to get system actor: %w" , err )
3794+ }
3795+ if ! found {
3796+ return cid .Undef , fmt .Errorf ("system actor not found" )
3797+ }
3798+ // load old manifest data directly from the system actor
3799+ var oldManifestData manifest.ManifestData
3800+ var oldSystemState system12.State
3801+ if err := adtStore .Get (ctx , oldSystemActor .Head , & oldSystemState ); err != nil {
3802+ return cid .Undef , fmt .Errorf ("failed to get system actor state: %w" , err )
3803+ } else if err := adtStore .Get (ctx , oldSystemState .BuiltinActors , & oldManifestData ); err != nil {
3804+ return cid .Undef , fmt .Errorf ("failed to get old manifest data: %w" , err )
3805+ }
3806+
3807+ // load new manifest from the blockstore
3808+ var newManifest manifest.Manifest
3809+ if err := adtStore .Get (ctx , manifestCid , & newManifest ); err != nil {
3810+ return cid .Undef , fmt .Errorf ("error reading actor manifest: %w" , err )
3811+ } else if err := newManifest .Load (ctx , adtStore ); err != nil {
3812+ return cid .Undef , fmt .Errorf ("error loading actor manifest: %w" , err )
3813+ }
3814+
3815+ // build an actor CID mapping
3816+ codeMapping := make (map [cid.Cid ]cid.Cid , len (oldManifestData .Entries ))
3817+ for _ , oldEntry := range oldManifestData .Entries {
3818+ newCID , ok := newManifest .Get (oldEntry .Name )
3819+ if ! ok {
3820+ return cid .Undef , fmt .Errorf ("missing manifest entry for %s" , oldEntry .Name )
3821+ }
3822+ codeMapping [oldEntry .Code ] = newCID
3823+ }
3824+
3825+ // Create empty state tree
3826+ actorsOut , err := vmstate .NewState (adtStore , actorsIn .Version ())
3827+ if err != nil {
3828+ return cid .Undef , fmt .Errorf ("failed to create new tree: %w" , err )
3829+ }
3830+
3831+ // Perform the migration
3832+ err = actorsIn .ForEach (func (a address.Address , actor * types.Actor ) error {
3833+ newCid , ok := codeMapping [actor .Code ]
3834+ if ! ok {
3835+ return fmt .Errorf ("didn't find mapping for %s" , actor .Code )
3836+ }
3837+
3838+ return actorsOut .SetActor (ctx , a , & types.Actor {
3839+ Code : newCid ,
3840+ Head : actor .Head ,
3841+ Nonce : actor .Nonce ,
3842+ Balance : actor .Balance ,
3843+ DelegatedAddress : actor .DelegatedAddress ,
3844+ })
3845+ })
3846+ if err != nil {
3847+ return cid .Undef , fmt .Errorf ("failed to perform migration: %w" , err )
3848+ }
3849+
3850+ // Setup the system actor with the new manifest, fetching it from actorsOut where it's already
3851+ // had its code CID changed, changing the manifest, then writing back to actorsOut
3852+ newSystemActor , found , err := actorsOut .GetActor (ctx , builtin .SystemActorAddr )
3853+ if err != nil {
3854+ return cid .Undef , fmt .Errorf ("failed to get system actor: %w" , err )
3855+ }
3856+ if ! found {
3857+ return cid .Undef , fmt .Errorf ("system actor not found" )
3858+ }
3859+ var newSystemState system12.State
3860+ if err := adtStore .Get (ctx , newSystemActor .Head , & newSystemState ); err != nil {
3861+ return cid .Undef , fmt .Errorf ("failed to get system actor state: %w" , err )
3862+ } else if err := adtStore .Get (ctx , newSystemState .BuiltinActors , & oldManifestData ); err != nil {
3863+ return cid .Undef , fmt .Errorf ("failed to get old manifest data: %w" , err )
3864+ }
3865+ newSystemState .BuiltinActors = newManifest .Data
3866+ newSystemHead , err := adtStore .Put (ctx , & newSystemState )
3867+ if err != nil {
3868+ return cid .Undef , fmt .Errorf ("failed to put new system state: %w" , err )
3869+ }
3870+ newSystemActor .Head = newSystemHead
3871+ if err = actorsOut .SetActor (ctx , builtin .SystemActorAddr , newSystemActor ); err != nil {
3872+ return cid .Undef , fmt .Errorf ("failed to put new system actor: %w" , err )
3873+ }
3874+
3875+ // Sanity check that the migration worked by re-iterating over the old tree and checking
3876+ // against the new tree's actors.
3877+
3878+ // initState for networkName
3879+ var initState init12.State
3880+ if actorsIn , err := vmstate .LoadState (ctx , adtStore , root ); err != nil {
3881+ return cid .Undef , fmt .Errorf ("loading state tree: %w" , err )
3882+ } else if initActor , found , err := actorsIn .GetActor (ctx , builtin .InitActorAddr ); err != nil || ! found {
3883+ return cid .Undef , fmt .Errorf ("failed to get system actor: %v" , err )
3884+ } else if err := adtStore .Get (ctx , initActor .Head , & initState ); err != nil {
3885+ return cid .Undef , fmt .Errorf ("failed to get system actor state: %w" , err )
3886+ }
3887+
3888+ v1600metadata := actors .BuggyBuiltinActorsMetadataForNetwork (initState .NetworkName , actorstypes .Version16 )
3889+ if v1600metadata == nil {
3890+ return cid .Undef , fmt .Errorf ("expected v16.0.0 metadata for network %s" , initState .NetworkName )
3891+ }
3892+
3893+ err = actorsIn .ForEach (func (a address.Address , inActor * types.Actor ) error {
3894+ outActor , found , err := actorsOut .GetActor (ctx , a )
3895+ if err != nil {
3896+ return fmt .Errorf ("failed to get actor in outTree: %w" , err )
3897+ }
3898+ if ! found {
3899+ return fmt .Errorf ("actor %s not found in outTree" , a )
3900+ }
3901+
3902+ if inActor .Nonce != outActor .Nonce {
3903+ return fmt .Errorf ("mismatched nonce for actor %s" , a )
3904+ } else if ! inActor .Balance .Equals (outActor .Balance ) {
3905+ return fmt .Errorf ("mismatched balance for actor %s: %d != %d" , a , inActor .Balance , outActor .Balance )
3906+ } else if inActor .DelegatedAddress != outActor .DelegatedAddress && inActor .DelegatedAddress .String () != outActor .DelegatedAddress .String () {
3907+ return fmt .Errorf ("mismatched address for actor %s: %s != %s" , a , inActor .DelegatedAddress , outActor .DelegatedAddress )
3908+ } else if inActor .Head != outActor .Head && a != builtin .SystemActorAddr {
3909+ return fmt .Errorf ("mismatched head for actor %s" , a )
3910+ }
3911+
3912+ // Check that the actor code has changed to the new expected value; work backward by getting the
3913+ // actor name from the new code CID.
3914+ if actorName , version , ok := actors .GetActorMetaByCode (outActor .Code ); ! ok {
3915+ return fmt .Errorf ("failed to get actor meta for code %s" , outActor .Code )
3916+ } else if version != actorstypes .Version16 {
3917+ return fmt .Errorf ("unexpected actor version for %s: %d" , actorName , version )
3918+ } else if oldCode , ok := v1600metadata .Actors [actorName ]; ! ok {
3919+ return fmt .Errorf ("missing actor %s in v16.0.0 metadata" , actorName )
3920+ } else if oldCode != inActor .Code {
3921+ return fmt .Errorf ("unexpected actor code for %s: %s != %s" , actorName , oldCode , outActor .Code )
3922+ }
3923+
3924+ return nil
3925+ })
3926+ if err != nil {
3927+ return cid .Undef , fmt .Errorf ("failed to sanity check migration: %w" , err )
3928+ }
3929+
3930+ // Persist the result.
3931+ newRoot , err := actorsOut .Flush (ctx )
3932+ if err != nil {
3933+ return cid .Undef , fmt .Errorf ("failed to persist new state root: %w" , err )
3934+ }
3935+
3936+ return newRoot , nil
3937+ }
3938+
37163939func (c * ChainFork ) GetForkUpgrade () * config.ForkUpgradeConfig {
37173940 return c .forkUpgrade
37183941}
0 commit comments