decouple network version and upgrades

Not all upgrades require network version bumps.
This commit is contained in:
Steven Allen 2020-10-02 17:09:56 -07:00
parent ed86ac14a1
commit c5de617af6
6 changed files with 117 additions and 48 deletions

View File

@ -38,17 +38,70 @@ type UpgradeFunc func(context.Context, *StateManager, ExecCallback, cid.Cid, *ty
type Upgrade struct {
Height abi.ChainEpoch
Network network.Version
Migration UpgradeFunc
}
type UpgradeSchedule map[network.Version]Upgrade
type UpgradeSchedule []Upgrade
var DefaultUpgradeSchedule = UpgradeSchedule{
network.Version1: {build.UpgradeBreezeHeight, UpgradeFaucetBurnRecovery},
network.Version2: {build.UpgradeSmokeHeight, nil},
network.Version3: {build.UpgradeIgnitionHeight, UpgradeIgnition},
network.Version4: {build.UpgradeActorsV2Height, UpgradeActorsV2},
network.Version5: {build.UpgradeLiftoffHeight, UpgradeLiftoff},
func DefaultUpgradeSchedule() UpgradeSchedule {
var us UpgradeSchedule
for _, u := range []Upgrade{{
Height: build.UpgradeBreezeHeight,
Network: network.Version1,
Migration: UpgradeFaucetBurnRecovery,
}, {
Height: build.UpgradeSmokeHeight,
Network: network.Version2,
Migration: nil,
}, {
Height: build.UpgradeIgnitionHeight,
Network: network.Version3,
Migration: UpgradeIgnition,
}, {
Height: build.UpgradeActorsV2Height,
Network: network.Version4,
Migration: UpgradeActorsV2,
}, {
Height: build.UpgradeLiftoffHeight,
Network: network.Version4,
Migration: UpgradeLiftoff,
}} {
if u.Height < 0 {
// upgrade disabled
continue
}
us = append(us, u)
}
return us
}
func (us UpgradeSchedule) Validate() error {
// Make sure we're not trying to upgrade to version 0.
for _, u := range us {
if u.Network <= 0 {
return xerrors.Errorf("cannot upgrade to version <= 0: %d", u.Network)
}
}
// Make sure all the upgrades make sense.
for i := 1; i < len(us); i++ {
prev := &us[i-1]
curr := &us[i]
if !(prev.Network <= curr.Network) {
return xerrors.Errorf("cannot downgrade from version %d to version %d", prev.Network, curr.Network)
}
// Make sure the heights make sense.
if prev.Height < 0 {
// Previous upgrade was disabled.
continue
}
if !(prev.Height < curr.Height) {
return xerrors.Errorf("upgrade heights must be strictly increasing: upgrade %d was at height %d, followed by upgrade %d at height %d", i-1, prev.Height, i, curr.Height)
}
}
return nil
}
func (sm *StateManager) handleStateForks(ctx context.Context, root cid.Cid, height abi.ChainEpoch, cb ExecCallback, ts *types.TipSet) (cid.Cid, error) {

View File

@ -115,10 +115,11 @@ func TestForkHeightTriggers(t *testing.T) {
t.Fatal(err)
}
sm := NewStateManagerWithUpgradeSchedule(
cg.ChainStore(),
UpgradeSchedule{
1: {Height: testForkHeight, Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback,
sm, err := NewStateManagerWithUpgradeSchedule(
cg.ChainStore(), UpgradeSchedule{{
Network: 1,
Height: testForkHeight,
Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback,
root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
cst := ipldcbor.NewCborStore(sm.ChainStore().Blockstore())
@ -151,8 +152,10 @@ func TestForkHeightTriggers(t *testing.T) {
}
return st.Flush(ctx)
}},
})
}}})
if err != nil {
t.Fatal(err)
}
inv := vm.NewActorRegistry()
inv.Register(nil, testActor{})

View File

@ -39,12 +39,18 @@ import (
var log = logging.Logger("statemgr")
type versionSpec struct {
networkVersion network.Version
atOrBelow abi.ChainEpoch
}
type StateManager struct {
cs *store.ChainStore
// Sorted network upgrade epochs (starting at version 1).
// -1 means the version is skipped.
networkVersions []abi.ChainEpoch
// Determines the network version at any given epoch.
networkVersions []versionSpec
latestVersion network.Version
// Maps chain epochs to upgrade functions.
stateMigrations map[abi.ChainEpoch]UpgradeFunc
@ -58,39 +64,49 @@ type StateManager struct {
}
func NewStateManager(cs *store.ChainStore) *StateManager {
return NewStateManagerWithUpgradeSchedule(cs, DefaultUpgradeSchedule)
sm, err := NewStateManagerWithUpgradeSchedule(cs, DefaultUpgradeSchedule())
if err != nil {
panic(fmt.Sprintf("default upgrade schedule is invalid: %s", err))
}
return sm
}
func NewStateManagerWithUpgradeSchedule(cs *store.ChainStore, us UpgradeSchedule) *StateManager {
func NewStateManagerWithUpgradeSchedule(cs *store.ChainStore, us UpgradeSchedule) (*StateManager, error) {
// If we have upgrades, make sure they're in-order and make sense.
if err := us.Validate(); err != nil {
return nil, err
}
stateMigrations := make(map[abi.ChainEpoch]UpgradeFunc, len(us))
networkVersions := make([]abi.ChainEpoch, 0, len(stateMigrations))
// Iterate version by version, to make sure we handle skipped version numbers.
// Always skip version 0.
for i, version := 0, network.Version(1); i < len(us); version++ {
upgrade, ok := us[version]
if ok {
// We've processed an upgrade.
i++
var networkVersions []versionSpec
lastVersion := network.Version0
if len(us) > 0 {
// If we have any upgrades, process them and create a version
// schedule.
for _, upgrade := range us {
if upgrade.Migration != nil {
stateMigrations[upgrade.Height] = upgrade.Migration
}
networkVersions = append(networkVersions, versionSpec{
networkVersion: lastVersion,
atOrBelow: upgrade.Height,
})
lastVersion = upgrade.Network
}
epoch := abi.ChainEpoch(-1)
if ok && upgrade.Height >= 0 {
epoch = upgrade.Height
stateMigrations[epoch] = upgrade.Migration
}
networkVersions = append(networkVersions, epoch)
} else {
// Otherwise, go directly to the latest version.
lastVersion = build.NewestNetworkVersion
}
return &StateManager{
networkVersions: networkVersions,
latestVersion: lastVersion,
stateMigrations: stateMigrations,
newVM: vm.NewVM,
cs: cs,
stCache: make(map[string][]cid.Cid),
compWait: make(map[string]chan struct{}),
}
}, nil
}
func cidsToKey(cids []cid.Cid) string {
@ -1294,13 +1310,12 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha
func (sm *StateManager) GetNtwkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
// The epochs here are the _last_ epoch for every version, or -1 if the
// version is disabled.
for v, epoch := range sm.networkVersions {
if epoch >= 0 && height <= epoch {
// Use the _previous_ version
return network.Version(v)
for _, spec := range sm.networkVersions {
if height <= spec.atOrBelow {
return spec.networkVersion
}
}
return network.Version(len(sm.networkVersions))
return sm.latestVersion
}
func (sm *StateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {

4
go.mod
View File

@ -33,12 +33,12 @@ require (
github.com/filecoin-project/go-multistore v0.0.3
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
github.com/filecoin-project/go-state-types v0.0.0-20201001162932-93a412d8e9fa
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe
github.com/filecoin-project/go-statestore v0.1.0
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
github.com/filecoin-project/specs-actors v0.9.12
github.com/filecoin-project/specs-actors/v2 v2.0.0-20201001041506-c7ff44a3ce9b
github.com/filecoin-project/specs-actors/v2 v2.0.0-20201002200957-bdd876b3bbe9
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
github.com/filecoin-project/test-vectors/schema v0.0.3
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1

6
go.sum
View File

@ -263,8 +263,6 @@ github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go
github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab h1:cEDC5Ei8UuT99hPWhCjA72SM9AuRtnpvdSTIYbnzN8I=
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
github.com/filecoin-project/go-state-types v0.0.0-20201001162932-93a412d8e9fa h1:WVxLrmc6w5naeX3QikfRvc1G7EFfBZbhXuzM8Lj2J+o=
github.com/filecoin-project/go-state-types v0.0.0-20201001162932-93a412d8e9fa/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
@ -276,8 +274,8 @@ github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07
github.com/filecoin-project/specs-actors v0.9.7/go.mod h1:wM2z+kwqYgXn5Z7scV1YHLyd1Q1cy0R8HfTIWQ0BFGU=
github.com/filecoin-project/specs-actors v0.9.12 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk=
github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao=
github.com/filecoin-project/specs-actors/v2 v2.0.0-20201001041506-c7ff44a3ce9b h1:8JRxR0rKdiuCHIDKi7Zbs+/jiygr6eXEX47QXhjX+kA=
github.com/filecoin-project/specs-actors/v2 v2.0.0-20201001041506-c7ff44a3ce9b/go.mod h1:52FuQUNDXq2WDg+6+UOhkqBuNc2e62h9BCIB67Bluxg=
github.com/filecoin-project/specs-actors/v2 v2.0.0-20201002200957-bdd876b3bbe9 h1:UXVcGwUD9GJYNcgfGbf7ok790wrunvUhl5ZlgApGhGs=
github.com/filecoin-project/specs-actors/v2 v2.0.0-20201002200957-bdd876b3bbe9/go.mod h1:52FuQUNDXq2WDg+6+UOhkqBuNc2e62h9BCIB67Bluxg=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
github.com/filecoin-project/test-vectors/schema v0.0.3 h1:1zuBo25B3016inbygYLgYFdpJ2m1BDTbAOCgABRleiU=

View File

@ -259,7 +259,7 @@ func Online() Option {
Override(new(ffiwrapper.Verifier), ffiwrapper.ProofVerifier),
Override(new(vm.SyscallBuilder), vm.Syscalls),
Override(new(*store.ChainStore), modules.ChainStore),
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule),
Override(new(stmgr.UpgradeSchedule), stmgr.DefaultUpgradeSchedule()),
Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
Override(new(*wallet.Wallet), wallet.NewWallet),
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),