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 { type Upgrade struct {
Height abi.ChainEpoch Height abi.ChainEpoch
Network network.Version
Migration UpgradeFunc Migration UpgradeFunc
} }
type UpgradeSchedule map[network.Version]Upgrade type UpgradeSchedule []Upgrade
var DefaultUpgradeSchedule = UpgradeSchedule{ func DefaultUpgradeSchedule() UpgradeSchedule {
network.Version1: {build.UpgradeBreezeHeight, UpgradeFaucetBurnRecovery}, var us UpgradeSchedule
network.Version2: {build.UpgradeSmokeHeight, nil},
network.Version3: {build.UpgradeIgnitionHeight, UpgradeIgnition}, for _, u := range []Upgrade{{
network.Version4: {build.UpgradeActorsV2Height, UpgradeActorsV2}, Height: build.UpgradeBreezeHeight,
network.Version5: {build.UpgradeLiftoffHeight, UpgradeLiftoff}, 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) { 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) t.Fatal(err)
} }
sm := NewStateManagerWithUpgradeSchedule( sm, err := NewStateManagerWithUpgradeSchedule(
cg.ChainStore(), cg.ChainStore(), UpgradeSchedule{{
UpgradeSchedule{ Network: 1,
1: {Height: testForkHeight, Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback, Height: testForkHeight,
Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback,
root cid.Cid, ts *types.TipSet) (cid.Cid, error) { root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
cst := ipldcbor.NewCborStore(sm.ChainStore().Blockstore()) cst := ipldcbor.NewCborStore(sm.ChainStore().Blockstore())
@ -151,8 +152,10 @@ func TestForkHeightTriggers(t *testing.T) {
} }
return st.Flush(ctx) return st.Flush(ctx)
}}, }}})
}) if err != nil {
t.Fatal(err)
}
inv := vm.NewActorRegistry() inv := vm.NewActorRegistry()
inv.Register(nil, testActor{}) inv.Register(nil, testActor{})

View File

@ -39,12 +39,18 @@ import (
var log = logging.Logger("statemgr") var log = logging.Logger("statemgr")
type versionSpec struct {
networkVersion network.Version
atOrBelow abi.ChainEpoch
}
type StateManager struct { type StateManager struct {
cs *store.ChainStore cs *store.ChainStore
// Sorted network upgrade epochs (starting at version 1). // Determines the network version at any given epoch.
// -1 means the version is skipped. networkVersions []versionSpec
networkVersions []abi.ChainEpoch latestVersion network.Version
// Maps chain epochs to upgrade functions. // Maps chain epochs to upgrade functions.
stateMigrations map[abi.ChainEpoch]UpgradeFunc stateMigrations map[abi.ChainEpoch]UpgradeFunc
@ -58,39 +64,49 @@ type StateManager struct {
} }
func NewStateManager(cs *store.ChainStore) *StateManager { 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)) stateMigrations := make(map[abi.ChainEpoch]UpgradeFunc, len(us))
networkVersions := make([]abi.ChainEpoch, 0, len(stateMigrations)) var networkVersions []versionSpec
lastVersion := network.Version0
// Iterate version by version, to make sure we handle skipped version numbers. if len(us) > 0 {
// Always skip version 0. // If we have any upgrades, process them and create a version
for i, version := 0, network.Version(1); i < len(us); version++ { // schedule.
upgrade, ok := us[version] for _, upgrade := range us {
if ok { if upgrade.Migration != nil {
// We've processed an upgrade. stateMigrations[upgrade.Height] = upgrade.Migration
i++ }
networkVersions = append(networkVersions, versionSpec{
networkVersion: lastVersion,
atOrBelow: upgrade.Height,
})
lastVersion = upgrade.Network
} }
} else {
epoch := abi.ChainEpoch(-1) // Otherwise, go directly to the latest version.
if ok && upgrade.Height >= 0 { lastVersion = build.NewestNetworkVersion
epoch = upgrade.Height
stateMigrations[epoch] = upgrade.Migration
}
networkVersions = append(networkVersions, epoch)
} }
return &StateManager{ return &StateManager{
networkVersions: networkVersions, networkVersions: networkVersions,
latestVersion: lastVersion,
stateMigrations: stateMigrations, stateMigrations: stateMigrations,
newVM: vm.NewVM, newVM: vm.NewVM,
cs: cs, cs: cs,
stCache: make(map[string][]cid.Cid), stCache: make(map[string][]cid.Cid),
compWait: make(map[string]chan struct{}), compWait: make(map[string]chan struct{}),
} }, nil
} }
func cidsToKey(cids []cid.Cid) string { 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 { 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 // The epochs here are the _last_ epoch for every version, or -1 if the
// version is disabled. // version is disabled.
for v, epoch := range sm.networkVersions { for _, spec := range sm.networkVersions {
if epoch >= 0 && height <= epoch { if height <= spec.atOrBelow {
// Use the _previous_ version return spec.networkVersion
return network.Version(v)
} }
} }
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) { 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-multistore v0.0.3
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 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-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-statemachine v0.0.0-20200925024713-05bd7c71fbfe
github.com/filecoin-project/go-statestore v0.1.0 github.com/filecoin-project/go-statestore v0.1.0
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b 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 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/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
github.com/filecoin-project/test-vectors/schema v0.0.3 github.com/filecoin-project/test-vectors/schema v0.0.3
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 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-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 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-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-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 h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= 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.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 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk=
github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao= 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-20201002200957-bdd876b3bbe9 h1:UXVcGwUD9GJYNcgfGbf7ok790wrunvUhl5ZlgApGhGs=
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/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 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/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= 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(ffiwrapper.Verifier), ffiwrapper.ProofVerifier),
Override(new(vm.SyscallBuilder), vm.Syscalls), Override(new(vm.SyscallBuilder), vm.Syscalls),
Override(new(*store.ChainStore), modules.ChainStore), 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(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule),
Override(new(*wallet.Wallet), wallet.NewWallet), Override(new(*wallet.Wallet), wallet.NewWallet),
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner), Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),