From 3832644beb7932d44d40339f6a0cadc9cfc20543 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Mon, 30 Sep 2024 17:53:37 +1000 Subject: [PATCH] feat(fip0081): migration and initial testing --- build/buildconstants/params_2k.go | 5 ++ build/buildconstants/params_butterfly.go | 7 ++ build/buildconstants/params_calibnet.go | 10 +++ build/buildconstants/params_interop.go | 7 ++ build/buildconstants/params_mainnet.go | 7 ++ build/buildconstants/params_testground.go | 61 +++++++-------- chain/actors/builtin/builtin.go | 1 + chain/actors/builtin/builtin.go.template | 1 + chain/consensus/filcns/upgrades.go | 42 +++++++---- go.sum | 2 - itests/migration_test.go | 91 ++++++++++++++++++++++- node/impl/full/state.go | 1 - 12 files changed, 185 insertions(+), 50 deletions(-) diff --git a/build/buildconstants/params_2k.go b/build/buildconstants/params_2k.go index 22ccb5d8def..d9972114a99 100644 --- a/build/buildconstants/params_2k.go +++ b/build/buildconstants/params_2k.go @@ -72,6 +72,11 @@ var UpgradeWaffleHeight = abi.ChainEpoch(-26) var UpgradeTuktukHeight = abi.ChainEpoch(200) +// FIP-0081: for the power actor state for pledge calculations. +// UpgradeTuktukPowerRampDurationEpochs ends up in the power actor state after +// Tuktuk migration. along with a RampStartEpoch matching the upgrade height. +var UpgradeTuktukPowerRampDurationEpochs = 200 + // This fix upgrade only ran on calibrationnet const UpgradeWatermelonFixHeight = -100 diff --git a/build/buildconstants/params_butterfly.go b/build/buildconstants/params_butterfly.go index 241dc60e3ad..9f6aa8f02e8 100644 --- a/build/buildconstants/params_butterfly.go +++ b/build/buildconstants/params_butterfly.go @@ -10,6 +10,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + + "github.com/filecoin-project/lotus/chain/actors/builtin" ) var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ @@ -58,6 +60,11 @@ const UpgradeWaffleHeight = -27 // ?????? const UpgradeTuktukHeight = 999999999999999 +// FIP-0081: for the power actor state for pledge calculations. +// UpgradeTuktukPowerRampDurationEpochs ends up in the power actor state after +// Tuktuk migration. along with a RampStartEpoch matching the upgrade height. +var UpgradeTuktukPowerRampDurationEpochs = uint64(builtin.EpochsInYear) + // This fix upgrade only ran on calibrationnet const UpgradeWatermelonFixHeight = -100 diff --git a/build/buildconstants/params_calibnet.go b/build/buildconstants/params_calibnet.go index ca2f9687bfd..73bf104fb54 100644 --- a/build/buildconstants/params_calibnet.go +++ b/build/buildconstants/params_calibnet.go @@ -13,6 +13,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + + "github.com/filecoin-project/lotus/chain/actors/builtin" ) var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ @@ -100,6 +102,14 @@ const UpgradeWaffleHeight = 1779094 // ?????? const UpgradeTuktukHeight = 999999999999999 +// FIP-0081: for the power actor state for pledge calculations. +// UpgradeTuktukPowerRampDurationEpochs ends up in the power actor state after +// Tuktuk migration. along with a RampStartEpoch matching the upgrade height. +// +// For calibrationnet, we set this to 7 days so we can observe and confirm the +// ramp behavior before mainnet upgrade. +var UpgradeTuktukPowerRampDurationEpochs = uint64(builtin.EpochsInDay * 7) + var SupportedProofTypes = []abi.RegisteredSealProof{ abi.RegisteredSealProof_StackedDrg32GiBV1, abi.RegisteredSealProof_StackedDrg64GiBV1, diff --git a/build/buildconstants/params_interop.go b/build/buildconstants/params_interop.go index 2f2131e8717..2579b9b5abc 100644 --- a/build/buildconstants/params_interop.go +++ b/build/buildconstants/params_interop.go @@ -13,6 +13,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + + "github.com/filecoin-project/lotus/chain/actors/builtin" ) var NetworkBundle = "caterpillarnet" @@ -56,6 +58,11 @@ var UpgradeWaffleHeight = abi.ChainEpoch(-27) const UpgradeTuktukHeight = 50 +// FIP-0081: for the power actor state for pledge calculations. +// UpgradeTuktukPowerRampDurationEpochs ends up in the power actor state after +// Tuktuk migration. along with a RampStartEpoch matching the upgrade height. +var UpgradeTuktukPowerRampDurationEpochs = uint64(builtin.EpochsInYear) + // This fix upgrade only ran on calibrationnet const UpgradeWatermelonFixHeight = -1 diff --git a/build/buildconstants/params_mainnet.go b/build/buildconstants/params_mainnet.go index 1ded76d8e5b..fd2584d7d23 100644 --- a/build/buildconstants/params_mainnet.go +++ b/build/buildconstants/params_mainnet.go @@ -14,6 +14,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/network" builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + + "github.com/filecoin-project/lotus/chain/actors/builtin" ) var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ @@ -110,6 +112,11 @@ const UpgradeWaffleHeight abi.ChainEpoch = 4154640 // ?????? var UpgradeTuktukHeight = abi.ChainEpoch(9999999999) +// FIP-0081: for the power actor state for pledge calculations. +// UpgradeTuktukPowerRampDurationEpochs ends up in the power actor state after +// Tuktuk migration. along with a RampStartEpoch matching the upgrade height. +var UpgradeTuktukPowerRampDurationEpochs = uint64(builtin.EpochsInYear) + // This fix upgrade only ran on calibrationnet const UpgradeWatermelonFixHeight abi.ChainEpoch = -1 diff --git a/build/buildconstants/params_testground.go b/build/buildconstants/params_testground.go index 0b83821e171..5cfc30d3e1d 100644 --- a/build/buildconstants/params_testground.go +++ b/build/buildconstants/params_testground.go @@ -76,36 +76,37 @@ var ( UpgradeBreezeHeight abi.ChainEpoch = -1 BreezeGasTampingDuration abi.ChainEpoch = 0 - UpgradeSmokeHeight abi.ChainEpoch = -1 - UpgradeIgnitionHeight abi.ChainEpoch = -2 - UpgradeRefuelHeight abi.ChainEpoch = -3 - UpgradeTapeHeight abi.ChainEpoch = -4 - UpgradeAssemblyHeight abi.ChainEpoch = 10 - UpgradeLiftoffHeight abi.ChainEpoch = -5 - UpgradeKumquatHeight abi.ChainEpoch = -6 - UpgradeCalicoHeight abi.ChainEpoch = -8 - UpgradePersianHeight abi.ChainEpoch = -9 - UpgradeOrangeHeight abi.ChainEpoch = -10 - UpgradeClausHeight abi.ChainEpoch = -11 - UpgradeTrustHeight abi.ChainEpoch = -12 - UpgradeNorwegianHeight abi.ChainEpoch = -13 - UpgradeTurboHeight abi.ChainEpoch = -14 - UpgradeHyperdriveHeight abi.ChainEpoch = -15 - UpgradeChocolateHeight abi.ChainEpoch = -16 - UpgradeOhSnapHeight abi.ChainEpoch = -17 - UpgradeSkyrHeight abi.ChainEpoch = -18 - UpgradeSharkHeight abi.ChainEpoch = -19 - UpgradeHyggeHeight abi.ChainEpoch = -20 - UpgradeLightningHeight abi.ChainEpoch = -21 - UpgradeThunderHeight abi.ChainEpoch = -22 - UpgradeWatermelonHeight abi.ChainEpoch = -23 - UpgradeWatermelonFixHeight abi.ChainEpoch = -24 - UpgradeWatermelonFix2Height abi.ChainEpoch = -25 - UpgradeDragonHeight abi.ChainEpoch = -26 - UpgradePhoenixHeight abi.ChainEpoch = -27 - UpgradeCalibrationDragonFixHeight abi.ChainEpoch = -28 - UpgradeWaffleHeight abi.ChainEpoch = -29 - UpgradeTuktukHeight abi.ChainEpoch = -30 + UpgradeSmokeHeight abi.ChainEpoch = -1 + UpgradeIgnitionHeight abi.ChainEpoch = -2 + UpgradeRefuelHeight abi.ChainEpoch = -3 + UpgradeTapeHeight abi.ChainEpoch = -4 + UpgradeAssemblyHeight abi.ChainEpoch = 10 + UpgradeLiftoffHeight abi.ChainEpoch = -5 + UpgradeKumquatHeight abi.ChainEpoch = -6 + UpgradeCalicoHeight abi.ChainEpoch = -8 + UpgradePersianHeight abi.ChainEpoch = -9 + UpgradeOrangeHeight abi.ChainEpoch = -10 + UpgradeClausHeight abi.ChainEpoch = -11 + UpgradeTrustHeight abi.ChainEpoch = -12 + UpgradeNorwegianHeight abi.ChainEpoch = -13 + UpgradeTurboHeight abi.ChainEpoch = -14 + UpgradeHyperdriveHeight abi.ChainEpoch = -15 + UpgradeChocolateHeight abi.ChainEpoch = -16 + UpgradeOhSnapHeight abi.ChainEpoch = -17 + UpgradeSkyrHeight abi.ChainEpoch = -18 + UpgradeSharkHeight abi.ChainEpoch = -19 + UpgradeHyggeHeight abi.ChainEpoch = -20 + UpgradeLightningHeight abi.ChainEpoch = -21 + UpgradeThunderHeight abi.ChainEpoch = -22 + UpgradeWatermelonHeight abi.ChainEpoch = -23 + UpgradeWatermelonFixHeight abi.ChainEpoch = -24 + UpgradeWatermelonFix2Height abi.ChainEpoch = -25 + UpgradeDragonHeight abi.ChainEpoch = -26 + UpgradePhoenixHeight abi.ChainEpoch = -27 + UpgradeCalibrationDragonFixHeight abi.ChainEpoch = -28 + UpgradeWaffleHeight abi.ChainEpoch = -29 + UpgradeTuktukHeight abi.ChainEpoch = -30 + UpgradeTuktukPowerRampDurationEpochs uint64 = 0 DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index af185cef693..7278b3f0849 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -40,6 +40,7 @@ var ( const ( EpochDurationSeconds = builtin.EpochDurationSeconds EpochsInDay = builtin.EpochsInDay + EpochsInYear = builtin.EpochsInYear SecondsInDay = builtin.SecondsInDay ) diff --git a/chain/actors/builtin/builtin.go.template b/chain/actors/builtin/builtin.go.template index de1ac0578ae..86eb1277588 100644 --- a/chain/actors/builtin/builtin.go.template +++ b/chain/actors/builtin/builtin.go.template @@ -40,6 +40,7 @@ var ( const ( EpochDurationSeconds = builtin.EpochDurationSeconds EpochsInDay = builtin.EpochsInDay + EpochsInYear = builtin.EpochsInYear SecondsInDay = builtin.SecondsInDay ) diff --git a/chain/consensus/filcns/upgrades.go b/chain/consensus/filcns/upgrades.go index e39767d82ce..9445f3e2464 100644 --- a/chain/consensus/filcns/upgrades.go +++ b/chain/consensus/filcns/upgrades.go @@ -2609,34 +2609,45 @@ func PreUpgradeActorsV15(ctx context.Context, sm *stmgr.StateManager, cache stmg workerCount /= 2 } - lbts, lbRoot, err := stmgr.GetLookbackTipSetForRound(ctx, sm, ts, epoch) + _, lbRoot, err := stmgr.GetLookbackTipSetForRound(ctx, sm, ts, epoch) if err != nil { return xerrors.Errorf("error getting lookback ts for premigration: %w", err) } config := migration.Config{ - MaxWorkers: uint(workerCount), - ProgressLogPeriod: time.Minute * 5, + MaxWorkers: uint(workerCount), + ProgressLogPeriod: time.Minute * 5, + PowerRampStartEpoch: int64(buildconstants.UpgradeTuktukHeight), + PowerRampDurationEpochs: buildconstants.UpgradeTuktukPowerRampDurationEpochs, } - _, err = upgradeActorsV15Common(ctx, sm, cache, lbRoot, epoch, lbts, config) + _, err = upgradeActorsV15Common(ctx, sm, cache, lbRoot, epoch, config) return err } -func UpgradeActorsV15(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, cb stmgr.ExecMonitor, - root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) { +func UpgradeActorsV15( + ctx context.Context, + sm *stmgr.StateManager, + cache stmgr.MigrationCache, + cb stmgr.ExecMonitor, + root cid.Cid, + epoch abi.ChainEpoch, + ts *types.TipSet, +) (cid.Cid, error) { // Use all the CPUs except 2. workerCount := MigrationMaxWorkerCount - 3 if workerCount <= 0 { workerCount = 1 } config := migration.Config{ - MaxWorkers: uint(workerCount), - JobQueueSize: 1000, - ResultQueueSize: 100, - ProgressLogPeriod: 10 * time.Second, + MaxWorkers: uint(workerCount), + JobQueueSize: 1000, + ResultQueueSize: 100, + ProgressLogPeriod: 10 * time.Second, + PowerRampStartEpoch: int64(epoch), + PowerRampDurationEpochs: buildconstants.UpgradeTuktukPowerRampDurationEpochs, } - newRoot, err := upgradeActorsV15Common(ctx, sm, cache, root, epoch, ts, config) + newRoot, err := upgradeActorsV15Common(ctx, sm, cache, root, epoch, config) if err != nil { return cid.Undef, xerrors.Errorf("migrating actors vXX state: %w", err) } @@ -2644,8 +2655,10 @@ func UpgradeActorsV15(ctx context.Context, sm *stmgr.StateManager, cache stmgr.M } func upgradeActorsV15Common( - ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, - root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet, + ctx context.Context, + sm *stmgr.StateManager, + cache stmgr.MigrationCache, + root cid.Cid, epoch abi.ChainEpoch, config migration.Config, ) (cid.Cid, error) { writeStore := blockstore.NewAutobatch(ctx, sm.ChainStore().StateBlockstore(), units.GiB/4) @@ -2674,8 +2687,7 @@ func upgradeActorsV15Common( } // Perform the migration - newHamtRoot, err := nv24.MigrateStateTree(ctx, adtStore, manifest, stateRoot.Actors, epoch, config, - migrationLogger{}, cache) + newHamtRoot, err := nv24.MigrateStateTree(ctx, adtStore, manifest, stateRoot.Actors, epoch, config, migrationLogger{}, cache) if err != nil { return cid.Undef, xerrors.Errorf("upgrading to actors vXX+1: %w", err) } diff --git a/go.sum b/go.sum index ea52a7f8063..f3655e1fd13 100644 --- a/go.sum +++ b/go.sum @@ -292,8 +292,6 @@ github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.15.0-dev.0.20240930015632-1fa1b9336831 h1:2uM70AEdo1vS3GEo3k5NjttH3kQM2+Z75a7nmlqRNCw= -github.com/filecoin-project/go-state-types v0.15.0-dev.0.20240930015632-1fa1b9336831/go.mod h1:YcWoJE/24XGEL6w9FjUoMBu7+eHEkgwKnkGZkTBX9TE= github.com/filecoin-project/go-state-types v0.15.0-dev.0.20240930040600-f1e9746dbeaa h1:bFoshr5ETGO0UWCeBD4LLwkk/BVCvwLO5gpgOojB268= github.com/filecoin-project/go-state-types v0.15.0-dev.0.20240930040600-f1e9746dbeaa/go.mod h1:YcWoJE/24XGEL6w9FjUoMBu7+eHEkgwKnkGZkTBX9TE= github.com/filecoin-project/go-statemachine v1.0.3 h1:N07o6alys+V1tNoSTi4WuuoeNC4erS/6jE74+NsgQuk= diff --git a/itests/migration_test.go b/itests/migration_test.go index d6a8a962c9f..3408998a2f7 100644 --- a/itests/migration_test.go +++ b/itests/migration_test.go @@ -18,7 +18,7 @@ import ( miner11 "github.com/filecoin-project/go-state-types/builtin/v11/miner" power11 "github.com/filecoin-project/go-state-types/builtin/v11/power" adt11 "github.com/filecoin-project/go-state-types/builtin/v11/util/adt" - account "github.com/filecoin-project/go-state-types/builtin/v15/account" + account14 "github.com/filecoin-project/go-state-types/builtin/v14/account" markettypes "github.com/filecoin-project/go-state-types/builtin/v9/market" migration "github.com/filecoin-project/go-state-types/builtin/v9/migration/test" miner9 "github.com/filecoin-project/go-state-types/builtin/v9/miner" @@ -31,11 +31,13 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/build/buildconstants" "github.com/filecoin-project/lotus/chain/actors" builtin2 "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/builtin/datacap" "github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/actors/builtin/power" "github.com/filecoin-project/lotus/chain/actors/builtin/system" "github.com/filecoin-project/lotus/chain/actors/builtin/verifreg" "github.com/filecoin-project/lotus/chain/consensus/filcns" @@ -894,6 +896,91 @@ func TestMigrationNV23(t *testing.T) { require.True(t, f090ActorPost.Code.Equals(accountNV23)) f090StatePost, err := clientApi.StateReadState(ctx, f090Addr, types.EmptyTSK) require.NoError(t, err) - state := f090StatePost.State.(*account.State) + state := f090StatePost.State.(*account14.State) require.Equal(t, state.Address, f090Addr) } + +func TestMigrationNV24(t *testing.T) { + req := require.New(t) + + kit.QuietMiningLogs() + + nv24epoch := abi.ChainEpoch(100) + buildconstants.UpgradeTuktukPowerRampDurationEpochs = 200 + + testClient, _, ens := kit.EnsembleMinimal( + t, + kit.MockProofs(), + kit.UpgradeSchedule(stmgr.Upgrade{ + Network: network.Version23, + Height: -1, + }, stmgr.Upgrade{ + Network: network.Version24, + Height: nv24epoch, + Migration: filcns.UpgradeActorsV15, + }, + )) + + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + clientApi := testClient.FullNode.(*impl.FullNodeAPI) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + testClient.WaitTillChain(ctx, kit.HeightAtLeast(nv24epoch+5)) + + bs := blockstore.NewAPIBlockstore(testClient) + ctxStore := gstStore.WrapBlockStore(ctx, bs) + + preMigrationTs, err := clientApi.ChainGetTipSetByHeight(ctx, nv24epoch-1, types.EmptyTSK) + req.NoError(err) + + root := preMigrationTs.Blocks()[0].ParentStateRoot + preStateTree, err := state.LoadStateTree(ctxStore, root) + req.NoError(err) + req.Equal(types.StateTreeVersion5, preStateTree.Version()) + + // FIP-0081 pledge ramp settings are unset before migration + powerActor, err := preStateTree.GetActor(builtin.StoragePowerActorAddr) + req.NoError(err) + powerState, err := power.Load(ctxStore, powerActor) + req.NoError(err) + req.Equal(int64(0), powerState.RampStartEpoch()) + req.Equal(uint64(0), powerState.RampDurationEpochs()) + + // Get state after the migration + postMigrationTs, err := clientApi.ChainHead(ctx) + req.NoError(err) + postStateTree, err := state.LoadStateTree(ctxStore, postMigrationTs.Blocks()[0].ParentStateRoot) + req.NoError(err) + + // Check the new system actor + systemAct, err := postStateTree.GetActor(builtin.SystemActorAddr) + req.NoError(err) + systemCode, ok := actors.GetActorCodeID(actorstypes.Version15, manifest.SystemKey) + req.True(ok) + req.Equal(systemCode, systemAct.Code) + + // FIP-0081 pledge ramp settings are set after migration + powerActor, err = postStateTree.GetActor(builtin.StoragePowerActorAddr) + req.NoError(err) + powerState, err = power.Load(ctxStore, powerActor) + req.NoError(err) + req.Equal(int64(nv24epoch), powerState.RampStartEpoch()) + req.Equal(uint64(200), powerState.RampDurationEpochs()) + + // TODO: test pledge API + + preMigrationPledge, err := clientApi.StateMinerInitialPledgeForSector(ctx, abi.ChainEpoch(builtin.EpochsInYear), abi.SectorSize(2<<10), 0, preMigrationTs.Key()) + req.NoError(err) + + for i := 0; ; i++ { + head := testClient.WaitTillChain(ctx, kit.HeightAtLeast(nv24epoch+abi.ChainEpoch(i*5))) + if head.Height() > nv24epoch+200 { + break + } + postMigrationPledge, err := clientApi.StateMinerInitialPledgeForSector(ctx, abi.ChainEpoch(builtin.EpochsInYear), abi.SectorSize(2<<10), 0, head.Key()) + req.NoError(err) + t.Logf("@%d: preMigrationPledge: %s, postMigrationPledge: %s", head.Height(), preMigrationPledge, postMigrationPledge) + } +} diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 1406e70f106..d325dcb596c 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1660,7 +1660,6 @@ func (a *StateAPI) StateMinerInitialPledgeForSector(ctx context.Context, sectorD } return types.BigDiv(types.BigMul(initialPledge, initialPledgeNum), initialPledgeDen), nil - } func (a *StateAPI) StateMinerAvailableBalance(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (types.BigInt, error) {