From caec7d778999a2426e211361dd9630cc78e89738 Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Wed, 17 May 2023 17:32:00 +0200 Subject: [PATCH 01/16] initial forking poc --- blockchain/blockchain_test.go | 8 +- blockchain/testing.go | 11 +- chain/params.go | 140 +++++++++---- command/genesis/params.go | 2 +- command/genesis/polybft_params.go | 2 +- command/server/init.go | 2 +- consensus/ibft/fork/hooks_test.go | 2 +- consensus/polybft/polybft.go | 38 +++- consensus/polybft/system_state_test.go | 2 +- forkmanager/fork.go | 43 ++++ forkmanager/fork_manager.go | 233 +++++++++++++++++++++ tests/state_test.go | 4 +- tests/testing.go | 2 +- txpool/txpool_test.go | 4 +- validators/store/contract/contract_test.go | 2 +- 15 files changed, 440 insertions(+), 55 deletions(-) create mode 100644 forkmanager/fork.go create mode 100644 forkmanager/fork_manager.go diff --git a/blockchain/blockchain_test.go b/blockchain/blockchain_test.go index b8de3dcffd..6d20dab9f9 100644 --- a/blockchain/blockchain_test.go +++ b/blockchain/blockchain_test.go @@ -1366,12 +1366,14 @@ func TestBlockchain_CalculateBaseFee(t *testing.T) { t.Parallel() fork := chain.Fork(5) + forksAvailable := &chain.AvailableForks{ + London: &fork, + } + blockchain := Blockchain{ config: &chain.Chain{ Params: &chain.Params{ - Forks: &chain.Forks{ - London: &fork, - }, + Forks: forksAvailable.ToForks(), }, Genesis: &chain.Genesis{ BaseFeeEM: test.elasticityMultiplier, diff --git a/blockchain/testing.go b/blockchain/testing.go index 2f3b510cd0..cafa8561c0 100644 --- a/blockchain/testing.go +++ b/blockchain/testing.go @@ -97,13 +97,14 @@ func NewTestBlockchain(t *testing.T, headers []*types.Header) *Blockchain { Number: 0, GasLimit: 0, } + forksAvail := &chain.AvailableForks{ + EIP155: chain.NewFork(0), + Homestead: chain.NewFork(0), + } config := &chain.Chain{ Genesis: genesis, Params: &chain.Params{ - Forks: &chain.Forks{ - EIP155: chain.NewFork(0), - Homestead: chain.NewFork(0), - }, + Forks: forksAvail.ToForks(), BlockGasTarget: defaultBlockGasTarget, }, } @@ -150,7 +151,7 @@ func NewMockBlockchain( GasLimit: 0, }, Params: &chain.Params{ - Forks: chain.AllForksEnabled, + Forks: chain.AllForksEnabled.ToForks(), }, } mockStorage = storage.NewMockStorage() diff --git a/chain/params.go b/chain/params.go index 62edcc2768..ebff9f20d3 100644 --- a/chain/params.go +++ b/chain/params.go @@ -3,7 +3,9 @@ package chain import ( "errors" "math/big" + "reflect" "sort" + "strings" "github.com/0xPolygon/polygon-edge/types" ) @@ -74,70 +76,123 @@ func (p *Params) GetEngine() string { return "" } -// Forks specifies when each fork is activated -type Forks struct { - Homestead *Fork `json:"homestead,omitempty"` - Byzantium *Fork `json:"byzantium,omitempty"` - Constantinople *Fork `json:"constantinople,omitempty"` - Petersburg *Fork `json:"petersburg,omitempty"` - Istanbul *Fork `json:"istanbul,omitempty"` - London *Fork `json:"london,omitempty"` - EIP150 *Fork `json:"EIP150,omitempty"` - EIP158 *Fork `json:"EIP158,omitempty"` - EIP155 *Fork `json:"EIP155,omitempty"` -} - -func (f *Forks) active(ff *Fork, block uint64) bool { - if ff == nil { - return false +// predefined forks +const ( + Homestead = "homestead" + Byzantium = "byzantium" + Constantinople = "constantinople" + Petersburg = "petersburg" + Istanbul = "istanbul" + London = "london" + EIP150 = "EIP150" + EIP158 = "EIP158" + EIP155 = "EIP155" +) + +type AvailableForks struct { + Homestead *Fork + Byzantium *Fork + Constantinople *Fork + Petersburg *Fork + Istanbul *Fork + London *Fork + EIP150 *Fork + EIP158 *Fork + EIP155 *Fork +} + +func (f *AvailableForks) At(block uint64) ForksInTime { + return ForksInTime{ + Homestead: active(f.Homestead, block), + Byzantium: active(f.Byzantium, block), + Constantinople: active(f.Constantinople, block), + Petersburg: active(f.Petersburg, block), + Istanbul: active(f.Istanbul, block), + London: active(f.London, block), + EIP150: active(f.EIP150, block), + EIP158: active(f.EIP158, block), + EIP155: active(f.EIP155, block), } +} - return ff.Active(block) +func (f *AvailableForks) ToForks() *Forks { + forks := &Forks{} + + add := func(name string, fork *Fork) { + if fork != nil { + (*forks)[name] = fork + } + } + + add(Homestead, f.Homestead) + add(Byzantium, f.Byzantium) + add(Constantinople, f.Constantinople) + add(Petersburg, f.Petersburg) + add(Istanbul, f.Istanbul) + add(London, f.London) + add(EIP150, f.EIP150) + add(EIP158, f.EIP158) + add(EIP155, f.EIP155) + + return forks } +// Forks specifies when each fork is activated +type Forks map[string]*Fork + func (f *Forks) IsHomestead(block uint64) bool { - return f.active(f.Homestead, block) + return active((*f)[Homestead], block) } func (f *Forks) IsByzantium(block uint64) bool { - return f.active(f.Byzantium, block) + return active((*f)[Byzantium], block) } func (f *Forks) IsConstantinople(block uint64) bool { - return f.active(f.Constantinople, block) + return active((*f)[Constantinople], block) } func (f *Forks) IsPetersburg(block uint64) bool { - return f.active(f.Petersburg, block) + return active((*f)[Petersburg], block) } func (f *Forks) IsLondon(block uint64) bool { - return f.active(f.London, block) + return active((*f)[London], block) } func (f *Forks) IsEIP150(block uint64) bool { - return f.active(f.EIP150, block) + return active((*f)[EIP150], block) } func (f *Forks) IsEIP158(block uint64) bool { - return f.active(f.EIP158, block) + return active((*f)[EIP158], block) } func (f *Forks) IsEIP155(block uint64) bool { - return f.active(f.EIP155, block) + return active((*f)[EIP155], block) +} + +func (f *Forks) Is(name string, block uint64) bool { + return active((*f)[name], block) +} + +func (f *Forks) IsSupported(name string) bool { + _, exists := (*f)[name] + + return exists } func (f *Forks) At(block uint64) ForksInTime { return ForksInTime{ - Homestead: f.active(f.Homestead, block), - Byzantium: f.active(f.Byzantium, block), - Constantinople: f.active(f.Constantinople, block), - Petersburg: f.active(f.Petersburg, block), - Istanbul: f.active(f.Istanbul, block), - London: f.active(f.London, block), - EIP150: f.active(f.EIP150, block), - EIP158: f.active(f.EIP158, block), - EIP155: f.active(f.EIP155, block), + Homestead: active((*f)[Homestead], block), + Byzantium: active((*f)[Byzantium], block), + Constantinople: active((*f)[Constantinople], block), + Petersburg: active((*f)[Petersburg], block), + Istanbul: active((*f)[Istanbul], block), + London: active((*f)[London], block), + EIP150: active((*f)[EIP150], block), + EIP158: active((*f)[EIP158], block), + EIP155: active((*f)[EIP155], block), } } @@ -169,7 +224,7 @@ type ForksInTime struct { EIP155 bool } -var AllForksEnabled = &Forks{ +var AllForksEnabled = &AvailableForks{ Homestead: NewFork(0), EIP150: NewFork(0), EIP155: NewFork(0), @@ -180,3 +235,18 @@ var AllForksEnabled = &Forks{ Istanbul: NewFork(0), London: NewFork(0), } + +func active(ff *Fork, block uint64) bool { + if ff == nil { + return false + } + + return ff.Active(block) +} + +func IsForkAvailable(name string) bool { + structureType := reflect.TypeOf(AvailableForks{}) + _, found := structureType.FieldByName(strings.Title(name)) + + return found +} diff --git a/command/genesis/params.go b/command/genesis/params.go index 95edcb5aa3..07ccdaaaec 100644 --- a/command/genesis/params.go +++ b/command/genesis/params.go @@ -384,7 +384,7 @@ func (p *genesisParams) initGenesisConfig() error { }, Params: &chain.Params{ ChainID: int64(p.chainID), - Forks: enabledForks, + Forks: enabledForks.ToForks(), Engine: p.consensusEngineConfig, }, Bootnodes: p.bootnodes, diff --git a/command/genesis/polybft_params.go b/command/genesis/polybft_params.go index b80135ae60..832366312e 100644 --- a/command/genesis/polybft_params.go +++ b/command/genesis/polybft_params.go @@ -156,7 +156,7 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er Name: p.name, Params: &chain.Params{ ChainID: int64(p.chainID), - Forks: enabledForks, + Forks: enabledForks.ToForks(), Engine: map[string]interface{}{ string(server.PolyBFTConsensus): polyBftConfig, }, diff --git a/command/server/init.go b/command/server/init.go index 353fbf9bde..174a4c17da 100644 --- a/command/server/init.go +++ b/command/server/init.go @@ -125,7 +125,7 @@ func (p *serverParams) initDevMode() { // - disables peer discovery // - enables all forks p.rawConfig.Network.NoDiscover = true - p.genesisConfig.Params.Forks = chain.AllForksEnabled + p.genesisConfig.Params.Forks = chain.AllForksEnabled.ToForks() p.initDevConsensusConfig() } diff --git a/consensus/ibft/fork/hooks_test.go b/consensus/ibft/fork/hooks_test.go index 3cf696e00f..51e1009b7c 100644 --- a/consensus/ibft/fork/hooks_test.go +++ b/consensus/ibft/fork/hooks_test.go @@ -278,7 +278,7 @@ func newTestTransition( st := itrie.NewState(itrie.NewMemoryStorage()) ex := state.NewExecutor(&chain.Params{ - Forks: chain.AllForksEnabled, + Forks: chain.AllForksEnabled.ToForks(), BurnContract: map[uint64]string{ 0: types.ZeroAddress.String(), }, diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go index 93435293f5..abd1d483ef 100644 --- a/consensus/polybft/polybft.go +++ b/consensus/polybft/polybft.go @@ -16,6 +16,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/forkmanager" "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/progress" "github.com/0xPolygon/polygon-edge/network" @@ -357,7 +358,7 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st } } - return nil + return registerForksAndHandlers(config.Params.Forks) } } @@ -678,3 +679,38 @@ func (p *Polybft) GetBridgeProvider() consensus.BridgeDataProvider { func (p *Polybft) FilterExtra(extra []byte) ([]byte, error) { return GetIbftExtraClean(extra) } + +func registerForksAndHandlers(forks *chain.Forks) error { + //nolint:godox + // TODO: update to real values and read from smart contract + availableForks := []forkmanager.ForkName{} + activeForks := []*forkmanager.ForkInfo{} + handlers := []forkmanager.ForkHandler{} + + for name, block := range *forks { + if !chain.IsForkAvailable(name) { + panic(fmt.Errorf("fork is not available: %s", name)) //nolint:gocritic + } + + availableForks = append(availableForks, forkmanager.ForkName(name)) + + if block != nil { + info := forkmanager.NewForkInfo(forkmanager.ForkName(name), (uint64)(*block)) + activeForks = append(activeForks, info) + } + } + + return forkmanager.GetInstance().RegisterAll(availableForks, handlers, activeForks) +} + +func init() { + // init default fork + availableForks := []forkmanager.ForkName{""} + activeForks := []*forkmanager.ForkInfo{ + forkmanager.NewForkInfo("", 0), + } + + if err := forkmanager.GetInstance().RegisterAll(availableForks, nil, activeForks); err != nil { + panic(err) //nolint:gocritic + } +} diff --git a/consensus/polybft/system_state_test.go b/consensus/polybft/system_state_test.go index e9f2894f7a..822699d222 100644 --- a/consensus/polybft/system_state_test.go +++ b/consensus/polybft/system_state_test.go @@ -132,7 +132,7 @@ func newTestTransition(t *testing.T, alloc map[types.Address]*chain.GenesisAccou st := itrie.NewState(itrie.NewMemoryStorage()) ex := state.NewExecutor(&chain.Params{ - Forks: chain.AllForksEnabled, + Forks: chain.AllForksEnabled.ToForks(), BurnContract: map[uint64]string{ 0: types.ZeroAddress.String(), }, diff --git a/forkmanager/fork.go b/forkmanager/fork.go new file mode 100644 index 0000000000..06d5947ba2 --- /dev/null +++ b/forkmanager/fork.go @@ -0,0 +1,43 @@ +package forkmanager + +type ForkHandlerName string + +type ForkName string + +type ForkInfo struct { + Name ForkName + FromBlockNumber uint64 +} + +type Fork struct { + Name ForkName + FromBlockNumber uint64 + IsActive bool + Handlers map[ForkHandlerName]interface{} +} + +type ForkActiveHandler struct { + FromBlockNumber uint64 + Handler interface{} +} + +type ForkHandler struct { + ForkName ForkName + HandlerName ForkHandlerName + Handler interface{} +} + +func NewForkInfo(name ForkName, blockNumber uint64) *ForkInfo { + return &ForkInfo{ + Name: name, + FromBlockNumber: blockNumber, + } +} + +func NewForkHandler(name ForkName, handlerName ForkHandlerName, handler interface{}) ForkHandler { + return ForkHandler{ + ForkName: name, + HandlerName: handlerName, + Handler: handler, + } +} diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go new file mode 100644 index 0000000000..e0c15f6f8f --- /dev/null +++ b/forkmanager/fork_manager.go @@ -0,0 +1,233 @@ +package forkmanager + +import ( + "fmt" + "sort" + "sync" +) + +/* +Regarding whether it is okay to use the Singleton pattern in Go, it's a topic of some debate. +The Singleton pattern can introduce global state and make testing and concurrent programming more challenging. +It can also make code tightly coupled and harder to maintain. +In general, it's recommended to favor dependency injection and explicit collaboration over singletons. + +However, there might be scenarios where the Singleton pattern is still useful, +such as managing shared resources or maintaining a global configuration. +Just be mindful of the potential drawbacks and consider alternative patterns when appropriate. +*/ + +var ( + forkManagerInstance *forkManager + forkManagerInstanceLock sync.Mutex +) + +type forkManager struct { + lock sync.Mutex + + forkMap map[ForkName]*Fork + handlersMap map[ForkHandlerName][]ForkActiveHandler +} + +func GetInstance() *forkManager { + forkManagerInstanceLock.Lock() + defer forkManagerInstanceLock.Unlock() + + if forkManagerInstance == nil { + forkManagerInstance = &forkManager{ + forkMap: map[ForkName]*Fork{}, + handlersMap: map[ForkHandlerName][]ForkActiveHandler{}, + } + } + + return forkManagerInstance +} + +func (fm *forkManager) RegisterFork(name ForkName) { + fm.lock.Lock() + defer fm.lock.Unlock() + + fm.forkMap[name] = &Fork{ + Name: name, + FromBlockNumber: 0, + IsActive: false, + Handlers: map[ForkHandlerName]interface{}{}, + } +} + +func (fm *forkManager) RegisterHandler(forkName ForkName, handlerName ForkHandlerName, handler interface{}) error { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[forkName] + if !exists { + return fmt.Errorf("fork does not exist: %s", forkName) + } + + fork.Handlers[handlerName] = handler + + return nil +} + +func (fm *forkManager) ActivateFork(forkName ForkName, blockNumber uint64) error { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[forkName] + if !exists { + return fmt.Errorf("fork does not exist: %s", forkName) + } + + if fork.IsActive { + return nil // already activated + } + + fork.IsActive = true + fork.FromBlockNumber = blockNumber + + for forkHandlerName, forkHandler := range fork.Handlers { + fm.addHandler(forkHandlerName, blockNumber, forkHandler) + } + + return nil +} + +func (fm *forkManager) DeactivateFork(forkName ForkName) error { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[forkName] + if !exists { + return fmt.Errorf("fork does not exist: %s", forkName) + } + + if !fork.IsActive { + return nil // already deactivated + } + + fork.IsActive = false + + for forkHandlerName := range fork.Handlers { + fm.removeHandler(forkHandlerName, fork.FromBlockNumber) + } + + return nil +} + +func (fm *forkManager) GetHandler(name ForkHandlerName, blockNumber uint64) interface{} { + fm.lock.Lock() + defer fm.lock.Unlock() + + handlers, exists := fm.handlersMap[name] + if !exists { + panic(fmt.Errorf("handlers not registered for %s", name)) //nolint:gocritic + } + + // binary search to find first position inside []*ForkHandler where FromBlockNumber >= blockNumber + pos := sort.Search(len(handlers), func(i int) bool { + return blockNumber < handlers[i].FromBlockNumber + }) - 1 + + return handlers[pos].Handler +} + +func (fm *forkManager) IsForkSupported(name ForkName) bool { + fm.lock.Lock() + defer fm.lock.Unlock() + + _, exists := fm.forkMap[name] + + return exists +} + +func (fm *forkManager) IsForkEnabled(name ForkName, blockNumber uint64) bool { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[name] + if !exists { + return false + } + + return fork.IsActive && fork.FromBlockNumber <= blockNumber +} + +func (fm *forkManager) GetForkBlock(name ForkName) (uint64, error) { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[name] + if !exists { + return 0, fmt.Errorf("fork does not exists: %s", name) + } + + if !fork.IsActive { + return 0, fmt.Errorf("fork is not active: %s", name) + } + + return fork.FromBlockNumber, nil +} + +func (fm *forkManager) addHandler(handlerName ForkHandlerName, blockNumber uint64, handler interface{}) { + if handlers, exists := fm.handlersMap[handlerName]; !exists { + fm.handlersMap[handlerName] = []ForkActiveHandler{ + { + FromBlockNumber: blockNumber, + Handler: handler, + }, + } + } else { + // keep everything in sorted order + index := sort.Search(len(handlers), func(i int) bool { + return handlers[i].FromBlockNumber >= blockNumber + }) + handlers = append(handlers, ForkActiveHandler{}) + copy(handlers[index+1:], handlers[index:]) + handlers[index] = ForkActiveHandler{ + FromBlockNumber: blockNumber, + Handler: handler, + } + fm.handlersMap[handlerName] = handlers + } +} + +func (fm *forkManager) removeHandler(handlerName ForkHandlerName, blockNumber uint64) { + handlers, exists := fm.handlersMap[handlerName] + if !exists { + return + } + + index := sort.Search(len(handlers), func(i int) bool { + return handlers[i].FromBlockNumber == blockNumber + }) + + if index != -1 { + copy(handlers[index:], handlers[index+1:]) + handlers[len(handlers)-1] = ForkActiveHandler{} + handlers = handlers[:len(handlers)-1] + } +} + +func (fm *forkManager) RegisterAll( + availableForks []ForkName, + handlers []ForkHandler, + activeForks []*ForkInfo, +) error { + for _, x := range availableForks { + fm.RegisterFork(x) + } + + for _, x := range handlers { + if err := fm.RegisterHandler(x.ForkName, x.HandlerName, x.Handler); err != nil { + return err + } + } + + for _, it := range activeForks { + if err := fm.ActivateFork(it.Name, it.FromBlockNumber); err != nil { + return err + } + } + + return nil +} diff --git a/tests/state_test.go b/tests/state_test.go index 981a9b9f86..02c7d6b4c4 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -42,7 +42,7 @@ func RunSpecificTest(t *testing.T, file string, c testCase, name, fork string, i var baseFee *big.Int - if config.IsLondon(0) { + if config.ToForks().IsLondon(0) { if c.Env.BaseFee != "" { baseFee = stringToBigIntT(t, c.Env.BaseFee) } else { @@ -61,7 +61,7 @@ func RunSpecificTest(t *testing.T, file string, c testCase, name, fork string, i forks := config.At(uint64(env.Number)) xxx := state.NewExecutor(&chain.Params{ - Forks: config, + Forks: config.ToForks(), ChainID: 1, BurnContract: map[uint64]string{ 0: types.ZeroAddress.String(), diff --git a/tests/testing.go b/tests/testing.go index 6595a1f640..eaf94c1ef1 100644 --- a/tests/testing.go +++ b/tests/testing.go @@ -402,7 +402,7 @@ func (t *stTransaction) UnmarshalJSON(input []byte) error { // forks -var Forks = map[string]*chain.Forks{ +var Forks = map[string]*chain.AvailableForks{ "Frontier": {}, "Homestead": { Homestead: chain.NewFork(0), diff --git a/txpool/txpool_test.go b/txpool/txpool_test.go index 00f9c41fee..1f1aef7eb3 100644 --- a/txpool/txpool_test.go +++ b/txpool/txpool_test.go @@ -31,11 +31,11 @@ const ( ) var ( - forks = &chain.Forks{ + forks = (&chain.AvailableForks{ Homestead: chain.NewFork(0), Istanbul: chain.NewFork(0), London: chain.NewFork(0), - } + }).ToForks() ) // addresses used in tests diff --git a/validators/store/contract/contract_test.go b/validators/store/contract/contract_test.go index b91a89633e..2ca434a94a 100644 --- a/validators/store/contract/contract_test.go +++ b/validators/store/contract/contract_test.go @@ -82,7 +82,7 @@ func newTestTransition( st := itrie.NewState(itrie.NewMemoryStorage()) ex := state.NewExecutor(&chain.Params{ - Forks: chain.AllForksEnabled, + Forks: chain.AllForksEnabled.ToForks(), BurnContract: map[uint64]string{ 0: types.ZeroAddress.String(), }, From ee9e9041f24772b863041b1acf43a5015b914265 Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Fri, 26 May 2023 13:37:22 +0200 Subject: [PATCH 02/16] params refactor --- blockchain/blockchain.go | 2 +- blockchain/blockchain_test.go | 6 +- blockchain/testing.go | 10 +- chain/params.go | 93 ++--------------- command/genesis/params.go | 4 +- command/genesis/polybft_params.go | 4 +- command/server/init.go | 2 +- consensus/ibft/fork/hooks_test.go | 2 +- consensus/polybft/system_state_test.go | 2 +- tests/state_test.go | 4 +- tests/testing.go | 110 ++++++++++----------- txpool/txpool_test.go | 10 +- validators/store/contract/contract_test.go | 2 +- 13 files changed, 86 insertions(+), 165 deletions(-) diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index fd99fbf58e..d4e60f6ee2 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -1413,7 +1413,7 @@ func (b *Blockchain) Close() error { // CalculateBaseFee calculates the basefee of the header. func (b *Blockchain) CalculateBaseFee(parent *types.Header) uint64 { - if !b.config.Params.Forks.IsLondon(parent.Number) { + if !b.config.Params.Forks.IsEnabled(chain.London, parent.Number) { return chain.GenesisBaseFee } diff --git a/blockchain/blockchain_test.go b/blockchain/blockchain_test.go index 6d20dab9f9..ddc8a41c97 100644 --- a/blockchain/blockchain_test.go +++ b/blockchain/blockchain_test.go @@ -1366,14 +1366,14 @@ func TestBlockchain_CalculateBaseFee(t *testing.T) { t.Parallel() fork := chain.Fork(5) - forksAvailable := &chain.AvailableForks{ - London: &fork, + forksAvailable := &chain.Forks{ + chain.London: &fork, } blockchain := Blockchain{ config: &chain.Chain{ Params: &chain.Params{ - Forks: forksAvailable.ToForks(), + Forks: forksAvailable, }, Genesis: &chain.Genesis{ BaseFeeEM: test.elasticityMultiplier, diff --git a/blockchain/testing.go b/blockchain/testing.go index cafa8561c0..fe11c027c2 100644 --- a/blockchain/testing.go +++ b/blockchain/testing.go @@ -97,14 +97,14 @@ func NewTestBlockchain(t *testing.T, headers []*types.Header) *Blockchain { Number: 0, GasLimit: 0, } - forksAvail := &chain.AvailableForks{ - EIP155: chain.NewFork(0), - Homestead: chain.NewFork(0), + forksAvail := &chain.Forks{ + chain.EIP155: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), } config := &chain.Chain{ Genesis: genesis, Params: &chain.Params{ - Forks: forksAvail.ToForks(), + Forks: forksAvail, BlockGasTarget: defaultBlockGasTarget, }, } @@ -151,7 +151,7 @@ func NewMockBlockchain( GasLimit: 0, }, Params: &chain.Params{ - Forks: chain.AllForksEnabled.ToForks(), + Forks: chain.AllForksEnabled, }, } mockStorage = storage.NewMockStorage() diff --git a/chain/params.go b/chain/params.go index ebff9f20d3..7e6e741e8f 100644 --- a/chain/params.go +++ b/chain/params.go @@ -3,9 +3,7 @@ package chain import ( "errors" "math/big" - "reflect" "sort" - "strings" "github.com/0xPolygon/polygon-edge/types" ) @@ -89,90 +87,10 @@ const ( EIP155 = "EIP155" ) -type AvailableForks struct { - Homestead *Fork - Byzantium *Fork - Constantinople *Fork - Petersburg *Fork - Istanbul *Fork - London *Fork - EIP150 *Fork - EIP158 *Fork - EIP155 *Fork -} - -func (f *AvailableForks) At(block uint64) ForksInTime { - return ForksInTime{ - Homestead: active(f.Homestead, block), - Byzantium: active(f.Byzantium, block), - Constantinople: active(f.Constantinople, block), - Petersburg: active(f.Petersburg, block), - Istanbul: active(f.Istanbul, block), - London: active(f.London, block), - EIP150: active(f.EIP150, block), - EIP158: active(f.EIP158, block), - EIP155: active(f.EIP155, block), - } -} - -func (f *AvailableForks) ToForks() *Forks { - forks := &Forks{} - - add := func(name string, fork *Fork) { - if fork != nil { - (*forks)[name] = fork - } - } - - add(Homestead, f.Homestead) - add(Byzantium, f.Byzantium) - add(Constantinople, f.Constantinople) - add(Petersburg, f.Petersburg) - add(Istanbul, f.Istanbul) - add(London, f.London) - add(EIP150, f.EIP150) - add(EIP158, f.EIP158) - add(EIP155, f.EIP155) - - return forks -} - // Forks specifies when each fork is activated type Forks map[string]*Fork -func (f *Forks) IsHomestead(block uint64) bool { - return active((*f)[Homestead], block) -} - -func (f *Forks) IsByzantium(block uint64) bool { - return active((*f)[Byzantium], block) -} - -func (f *Forks) IsConstantinople(block uint64) bool { - return active((*f)[Constantinople], block) -} - -func (f *Forks) IsPetersburg(block uint64) bool { - return active((*f)[Petersburg], block) -} - -func (f *Forks) IsLondon(block uint64) bool { - return active((*f)[London], block) -} - -func (f *Forks) IsEIP150(block uint64) bool { - return active((*f)[EIP150], block) -} - -func (f *Forks) IsEIP158(block uint64) bool { - return active((*f)[EIP158], block) -} - -func (f *Forks) IsEIP155(block uint64) bool { - return active((*f)[EIP155], block) -} - -func (f *Forks) Is(name string, block uint64) bool { +func (f *Forks) IsEnabled(name string, block uint64) bool { return active((*f)[name], block) } @@ -182,6 +100,10 @@ func (f *Forks) IsSupported(name string) bool { return exists } +func (f *Forks) SetFork(name string, value *Fork) { + (*f)[name] = value +} + func (f *Forks) At(block uint64) ForksInTime { return ForksInTime{ Homestead: active((*f)[Homestead], block), @@ -224,7 +146,7 @@ type ForksInTime struct { EIP155 bool } -var AllForksEnabled = &AvailableForks{ +var AllForksEnabled = &Forks{ Homestead: NewFork(0), EIP150: NewFork(0), EIP155: NewFork(0), @@ -245,8 +167,7 @@ func active(ff *Fork, block uint64) bool { } func IsForkAvailable(name string) bool { - structureType := reflect.TypeOf(AvailableForks{}) - _, found := structureType.FieldByName(strings.Title(name)) + _, found := (*AllForksEnabled)[name] return found } diff --git a/command/genesis/params.go b/command/genesis/params.go index 07ccdaaaec..0e4e917f48 100644 --- a/command/genesis/params.go +++ b/command/genesis/params.go @@ -370,7 +370,7 @@ func (p *genesisParams) initGenesisConfig() error { // Disable london hardfork if burn contract address is not provided enabledForks := chain.AllForksEnabled if len(p.burnContracts) == 0 { - enabledForks.London = nil + enabledForks.SetFork(chain.London, nil) } chainConfig := &chain.Chain{ @@ -384,7 +384,7 @@ func (p *genesisParams) initGenesisConfig() error { }, Params: &chain.Params{ ChainID: int64(p.chainID), - Forks: enabledForks.ToForks(), + Forks: enabledForks, Engine: p.consensusEngineConfig, }, Bootnodes: p.bootnodes, diff --git a/command/genesis/polybft_params.go b/command/genesis/polybft_params.go index 832366312e..1abb645bee 100644 --- a/command/genesis/polybft_params.go +++ b/command/genesis/polybft_params.go @@ -149,14 +149,14 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er // Disable london hardfork if burn contract address is not provided enabledForks := chain.AllForksEnabled if len(p.burnContracts) == 0 { - enabledForks.London = nil + enabledForks.SetFork(chain.London, nil) } chainConfig := &chain.Chain{ Name: p.name, Params: &chain.Params{ ChainID: int64(p.chainID), - Forks: enabledForks.ToForks(), + Forks: enabledForks, Engine: map[string]interface{}{ string(server.PolyBFTConsensus): polyBftConfig, }, diff --git a/command/server/init.go b/command/server/init.go index 174a4c17da..353fbf9bde 100644 --- a/command/server/init.go +++ b/command/server/init.go @@ -125,7 +125,7 @@ func (p *serverParams) initDevMode() { // - disables peer discovery // - enables all forks p.rawConfig.Network.NoDiscover = true - p.genesisConfig.Params.Forks = chain.AllForksEnabled.ToForks() + p.genesisConfig.Params.Forks = chain.AllForksEnabled p.initDevConsensusConfig() } diff --git a/consensus/ibft/fork/hooks_test.go b/consensus/ibft/fork/hooks_test.go index 51e1009b7c..3cf696e00f 100644 --- a/consensus/ibft/fork/hooks_test.go +++ b/consensus/ibft/fork/hooks_test.go @@ -278,7 +278,7 @@ func newTestTransition( st := itrie.NewState(itrie.NewMemoryStorage()) ex := state.NewExecutor(&chain.Params{ - Forks: chain.AllForksEnabled.ToForks(), + Forks: chain.AllForksEnabled, BurnContract: map[uint64]string{ 0: types.ZeroAddress.String(), }, diff --git a/consensus/polybft/system_state_test.go b/consensus/polybft/system_state_test.go index 822699d222..e9f2894f7a 100644 --- a/consensus/polybft/system_state_test.go +++ b/consensus/polybft/system_state_test.go @@ -132,7 +132,7 @@ func newTestTransition(t *testing.T, alloc map[types.Address]*chain.GenesisAccou st := itrie.NewState(itrie.NewMemoryStorage()) ex := state.NewExecutor(&chain.Params{ - Forks: chain.AllForksEnabled.ToForks(), + Forks: chain.AllForksEnabled, BurnContract: map[uint64]string{ 0: types.ZeroAddress.String(), }, diff --git a/tests/state_test.go b/tests/state_test.go index 02c7d6b4c4..24650dd273 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -42,7 +42,7 @@ func RunSpecificTest(t *testing.T, file string, c testCase, name, fork string, i var baseFee *big.Int - if config.ToForks().IsLondon(0) { + if config.IsEnabled(chain.London, 0) { if c.Env.BaseFee != "" { baseFee = stringToBigIntT(t, c.Env.BaseFee) } else { @@ -61,7 +61,7 @@ func RunSpecificTest(t *testing.T, file string, c testCase, name, fork string, i forks := config.At(uint64(env.Number)) xxx := state.NewExecutor(&chain.Params{ - Forks: config.ToForks(), + Forks: config, ChainID: 1, BurnContract: map[uint64]string{ 0: types.ZeroAddress.String(), diff --git a/tests/testing.go b/tests/testing.go index eaf94c1ef1..c256d8d9dd 100644 --- a/tests/testing.go +++ b/tests/testing.go @@ -402,86 +402,86 @@ func (t *stTransaction) UnmarshalJSON(input []byte) error { // forks -var Forks = map[string]*chain.AvailableForks{ +var Forks = map[string]*chain.Forks{ "Frontier": {}, "Homestead": { - Homestead: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), }, "EIP150": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), }, "EIP158": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), }, "Byzantium": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), }, "Constantinople": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(0), }, - "Istanbul": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(0), - Petersburg: chain.NewFork(0), - Istanbul: chain.NewFork(0), + "Istchain.anbul": { + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(0), + chain.Petersburg: chain.NewFork(0), + chain.Istanbul: chain.NewFork(0), }, /*"London": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(0), - Petersburg: chain.NewFork(0), - Istanbul: chain.NewFork(0), - London: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(0), + chain.Petersburg: chain.NewFork(0), + chain.Istanbul: chain.NewFork(0), + chain.London: chain.NewFork(0), },*/ "FrontierToHomesteadAt5": { - Homestead: chain.NewFork(5), + chain.Homestead: chain.NewFork(5), }, "HomesteadToEIP150At5": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(5), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(5), }, "HomesteadToDaoAt5": { - Homestead: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), }, "EIP158ToByzantiumAt5": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(5), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(5), }, "ByzantiumToConstantinopleAt5": { - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(5), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(5), }, "ConstantinopleFix": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(0), - Petersburg: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(0), + chain.Petersburg: chain.NewFork(0), }, } diff --git a/txpool/txpool_test.go b/txpool/txpool_test.go index 1f1aef7eb3..c19647bc23 100644 --- a/txpool/txpool_test.go +++ b/txpool/txpool_test.go @@ -31,11 +31,11 @@ const ( ) var ( - forks = (&chain.AvailableForks{ - Homestead: chain.NewFork(0), - Istanbul: chain.NewFork(0), - London: chain.NewFork(0), - }).ToForks() + forks = (&chain.Forks{ + chain.Homestead: chain.NewFork(0), + chain.Istanbul: chain.NewFork(0), + chain.London: chain.NewFork(0), + }) ) // addresses used in tests diff --git a/validators/store/contract/contract_test.go b/validators/store/contract/contract_test.go index 2ca434a94a..b91a89633e 100644 --- a/validators/store/contract/contract_test.go +++ b/validators/store/contract/contract_test.go @@ -82,7 +82,7 @@ func newTestTransition( st := itrie.NewState(itrie.NewMemoryStorage()) ex := state.NewExecutor(&chain.Params{ - Forks: chain.AllForksEnabled.ToForks(), + Forks: chain.AllForksEnabled, BurnContract: map[uint64]string{ 0: types.ZeroAddress.String(), }, From 52c3780abfb8ead2f319e9cc551dddcabb54d09c Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Sat, 27 May 2023 20:21:51 +0200 Subject: [PATCH 03/16] cr fix --- chain/params.go | 6 +----- consensus/polybft/polybft.go | 18 ++---------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/chain/params.go b/chain/params.go index 7e6e741e8f..993cfe78f1 100644 --- a/chain/params.go +++ b/chain/params.go @@ -159,11 +159,7 @@ var AllForksEnabled = &Forks{ } func active(ff *Fork, block uint64) bool { - if ff == nil { - return false - } - - return ff.Active(block) + return ff != nil && ff.Active(block) } func IsForkAvailable(name string) bool { diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go index abd1d483ef..46a9229c88 100644 --- a/consensus/polybft/polybft.go +++ b/consensus/polybft/polybft.go @@ -681,8 +681,6 @@ func (p *Polybft) FilterExtra(extra []byte) ([]byte, error) { } func registerForksAndHandlers(forks *chain.Forks) error { - //nolint:godox - // TODO: update to real values and read from smart contract availableForks := []forkmanager.ForkName{} activeForks := []*forkmanager.ForkInfo{} handlers := []forkmanager.ForkHandler{} @@ -695,22 +693,10 @@ func registerForksAndHandlers(forks *chain.Forks) error { availableForks = append(availableForks, forkmanager.ForkName(name)) if block != nil { - info := forkmanager.NewForkInfo(forkmanager.ForkName(name), (uint64)(*block)) - activeForks = append(activeForks, info) + activeForks = append(activeForks, + forkmanager.NewForkInfo(forkmanager.ForkName(name), (uint64)(*block))) } } return forkmanager.GetInstance().RegisterAll(availableForks, handlers, activeForks) } - -func init() { - // init default fork - availableForks := []forkmanager.ForkName{""} - activeForks := []*forkmanager.ForkInfo{ - forkmanager.NewForkInfo("", 0), - } - - if err := forkmanager.GetInstance().RegisterAll(availableForks, nil, activeForks); err != nil { - panic(err) //nolint:gocritic - } -} From ca1e96cf20bed6ec1ad22666cc4be687140252bf Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Mon, 29 May 2023 09:23:05 +0200 Subject: [PATCH 04/16] cr fix 2 --- consensus/polybft/polybft.go | 43 ++++++++++++++++++------------------ forkmanager/fork.go | 26 ---------------------- forkmanager/fork_manager.go | 24 -------------------- server/builtin.go | 6 +++++ server/server.go | 6 +++++ tests/testing.go | 11 --------- 6 files changed, 33 insertions(+), 83 deletions(-) diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go index 46a9229c88..75de5ce59b 100644 --- a/consensus/polybft/polybft.go +++ b/consensus/polybft/polybft.go @@ -358,8 +358,28 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st } } - return registerForksAndHandlers(config.Params.Forks) + return nil + } +} + +func ForkManagerFactory(forks *chain.Forks) error { + fm := forkmanager.GetInstance() + + for name, block := range *forks { + if !chain.IsForkAvailable(name) { + return fmt.Errorf("fork is not available: %s", name) + } + + fm.RegisterFork(forkmanager.ForkName(name)) + + if block != nil { + if err := fm.ActivateFork(forkmanager.ForkName(name), (uint64)(*block)); err != nil { + return err + } + } } + + return nil } // Initialize initializes the consensus (e.g. setup data) @@ -679,24 +699,3 @@ func (p *Polybft) GetBridgeProvider() consensus.BridgeDataProvider { func (p *Polybft) FilterExtra(extra []byte) ([]byte, error) { return GetIbftExtraClean(extra) } - -func registerForksAndHandlers(forks *chain.Forks) error { - availableForks := []forkmanager.ForkName{} - activeForks := []*forkmanager.ForkInfo{} - handlers := []forkmanager.ForkHandler{} - - for name, block := range *forks { - if !chain.IsForkAvailable(name) { - panic(fmt.Errorf("fork is not available: %s", name)) //nolint:gocritic - } - - availableForks = append(availableForks, forkmanager.ForkName(name)) - - if block != nil { - activeForks = append(activeForks, - forkmanager.NewForkInfo(forkmanager.ForkName(name), (uint64)(*block))) - } - } - - return forkmanager.GetInstance().RegisterAll(availableForks, handlers, activeForks) -} diff --git a/forkmanager/fork.go b/forkmanager/fork.go index 06d5947ba2..2d41d2699d 100644 --- a/forkmanager/fork.go +++ b/forkmanager/fork.go @@ -4,11 +4,6 @@ type ForkHandlerName string type ForkName string -type ForkInfo struct { - Name ForkName - FromBlockNumber uint64 -} - type Fork struct { Name ForkName FromBlockNumber uint64 @@ -20,24 +15,3 @@ type ForkActiveHandler struct { FromBlockNumber uint64 Handler interface{} } - -type ForkHandler struct { - ForkName ForkName - HandlerName ForkHandlerName - Handler interface{} -} - -func NewForkInfo(name ForkName, blockNumber uint64) *ForkInfo { - return &ForkInfo{ - Name: name, - FromBlockNumber: blockNumber, - } -} - -func NewForkHandler(name ForkName, handlerName ForkHandlerName, handler interface{}) ForkHandler { - return ForkHandler{ - ForkName: name, - HandlerName: handlerName, - Handler: handler, - } -} diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go index e0c15f6f8f..c2a4c08d31 100644 --- a/forkmanager/fork_manager.go +++ b/forkmanager/fork_manager.go @@ -207,27 +207,3 @@ func (fm *forkManager) removeHandler(handlerName ForkHandlerName, blockNumber ui handlers = handlers[:len(handlers)-1] } } - -func (fm *forkManager) RegisterAll( - availableForks []ForkName, - handlers []ForkHandler, - activeForks []*ForkInfo, -) error { - for _, x := range availableForks { - fm.RegisterFork(x) - } - - for _, x := range handlers { - if err := fm.RegisterHandler(x.ForkName, x.HandlerName, x.Handler); err != nil { - return err - } - } - - for _, it := range activeForks { - if err := fm.ActivateFork(it.Name, it.FromBlockNumber); err != nil { - return err - } - } - - return nil -} diff --git a/server/builtin.go b/server/builtin.go index 435bb1a282..c84e03e97c 100644 --- a/server/builtin.go +++ b/server/builtin.go @@ -19,6 +19,8 @@ type GenesisFactoryHook func(config *chain.Chain, engineName string) func(*state type ConsensusType string +type ForkManagerFactory func(forks *chain.Forks) error + const ( DevConsensus ConsensusType = "dev" IBFTConsensus ConsensusType = "ibft" @@ -46,6 +48,10 @@ var genesisCreationFactory = map[ConsensusType]GenesisFactoryHook{ PolyBFTConsensus: consensusPolyBFT.GenesisPostHookFactory, } +var forkManagerFactory = map[ConsensusType]ForkManagerFactory{ + PolyBFTConsensus: consensusPolyBFT.ForkManagerFactory, +} + func ConsensusSupported(value string) bool { _, ok := consensusBackends[ConsensusType(value)] diff --git a/server/server.go b/server/server.go index 5aca527c21..b0aef318cd 100644 --- a/server/server.go +++ b/server/server.go @@ -276,6 +276,12 @@ func NewServer(config *Config) (*Server, error) { return nil, err } + if factory, exists := forkManagerFactory[ConsensusType(engineName)]; exists { + if err := factory(config.Chain.Params.Forks); err != nil { + return nil, err + } + } + // compute the genesis root state config.Chain.Genesis.StateRoot = genesisRoot diff --git a/tests/testing.go b/tests/testing.go index c256d8d9dd..fca394139e 100644 --- a/tests/testing.go +++ b/tests/testing.go @@ -442,17 +442,6 @@ var Forks = map[string]*chain.Forks{ chain.Petersburg: chain.NewFork(0), chain.Istanbul: chain.NewFork(0), }, - /*"London": { - chain.Homestead: chain.NewFork(0), - chain.EIP150: chain.NewFork(0), - chain.EIP155: chain.NewFork(0), - chain.EIP158: chain.NewFork(0), - chain.Byzantium: chain.NewFork(0), - chain.Constantinople: chain.NewFork(0), - chain.Petersburg: chain.NewFork(0), - chain.Istanbul: chain.NewFork(0), - chain.London: chain.NewFork(0), - },*/ "FrontierToHomesteadAt5": { chain.Homestead: chain.NewFork(5), }, From 169fa94093738f0af1c968a8380c0e622d8bc0de Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Mon, 29 May 2023 12:24:10 +0200 Subject: [PATCH 05/16] current block state and tests --- consensus/polybft/consensus_runtime.go | 3 + forkmanager/fork_manager.go | 30 +++-- forkmanager/fork_manager_test.go | 177 +++++++++++++++++++++++++ server/server.go | 4 + 4 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 forkmanager/fork_manager_test.go diff --git a/consensus/polybft/consensus_runtime.go b/consensus/polybft/consensus_runtime.go index 66017cd5b0..dfbbe0b6f4 100644 --- a/consensus/polybft/consensus_runtime.go +++ b/consensus/polybft/consensus_runtime.go @@ -14,6 +14,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/forkmanager" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" @@ -270,6 +271,8 @@ func (c *consensusRuntime) OnBlockInserted(fullBlock *types.FullBlock) { c.lock.Lock() defer c.lock.Unlock() + forkmanager.GetInstance().SetCurrentBlock(fullBlock.Block.Number() + 1) + if c.lastBuiltBlock != nil && c.lastBuiltBlock.Number >= fullBlock.Block.Number() { c.logger.Debug("on block inserted already handled", "current", c.lastBuiltBlock.Number, "block", fullBlock.Block.Number()) diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go index c2a4c08d31..fbbd888a84 100644 --- a/forkmanager/fork_manager.go +++ b/forkmanager/fork_manager.go @@ -27,6 +27,8 @@ type forkManager struct { forkMap map[ForkName]*Fork handlersMap map[ForkHandlerName][]ForkActiveHandler + + currentHandlers map[ForkHandlerName]interface{} } func GetInstance() *forkManager { @@ -114,21 +116,29 @@ func (fm *forkManager) DeactivateFork(forkName ForkName) error { return nil } -func (fm *forkManager) GetHandler(name ForkHandlerName, blockNumber uint64) interface{} { +func (fm *forkManager) SetCurrentBlock(currentBlock uint64) { fm.lock.Lock() defer fm.lock.Unlock() - handlers, exists := fm.handlersMap[name] - if !exists { - panic(fmt.Errorf("handlers not registered for %s", name)) //nolint:gocritic + fm.currentHandlers = map[ForkHandlerName]interface{}{} + + for handlerName, handlers := range fm.handlersMap { + // binary search to find first position inside []*ForkHandler where FromBlockNumber >= blockNumber + pos := sort.Search(len(handlers), func(i int) bool { + return currentBlock < handlers[i].FromBlockNumber + }) - 1 + + if pos >= 0 { + fm.currentHandlers[handlerName] = handlers[pos].Handler + } } +} - // binary search to find first position inside []*ForkHandler where FromBlockNumber >= blockNumber - pos := sort.Search(len(handlers), func(i int) bool { - return blockNumber < handlers[i].FromBlockNumber - }) - 1 +func (fm *forkManager) GetHandler(name ForkHandlerName) interface{} { + fm.lock.Lock() + defer fm.lock.Unlock() - return handlers[pos].Handler + return fm.currentHandlers[name] } func (fm *forkManager) IsForkSupported(name ForkName) bool { @@ -204,6 +214,6 @@ func (fm *forkManager) removeHandler(handlerName ForkHandlerName, blockNumber ui if index != -1 { copy(handlers[index:], handlers[index+1:]) handlers[len(handlers)-1] = ForkActiveHandler{} - handlers = handlers[:len(handlers)-1] + fm.handlersMap[handlerName] = handlers[:len(handlers)-1] } } diff --git a/forkmanager/fork_manager_test.go b/forkmanager/fork_manager_test.go new file mode 100644 index 0000000000..a37661191d --- /dev/null +++ b/forkmanager/fork_manager_test.go @@ -0,0 +1,177 @@ +package forkmanager + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestForkManager(t *testing.T) { + t.Parallel() + + forkManager := GetInstance() + + forkManager.RegisterFork(ForkName("A")) + forkManager.RegisterFork(ForkName("B")) + forkManager.RegisterFork(ForkName("C")) + forkManager.RegisterFork(ForkName("D")) + + assert.NoError(t, forkManager.RegisterHandler(ForkName("A"), "A", func() string { return "AAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkName("C"), "A", func() string { return "ACH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkName("A"), "B", func() string { return "BAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkName("B"), "B", func() string { return "BBH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkName("D"), "B", func() string { return "BDH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkName("B"), "C", func() string { return "CBH" })) + + assert.NoError(t, forkManager.ActivateFork(ForkName("A"), 0)) + assert.NoError(t, forkManager.ActivateFork(ForkName("B"), 100)) + assert.NoError(t, forkManager.ActivateFork(ForkName("C"), 200)) + assert.NoError(t, forkManager.ActivateFork(ForkName("D"), 300)) + + handlersACnt := len(forkManager.handlersMap[ForkHandlerName("A")]) + handlersBCnt := len(forkManager.handlersMap[ForkHandlerName("B")]) + + assert.Equal(t, 2, handlersACnt) + assert.Equal(t, 3, handlersBCnt) + + t.Run("activate not registered fork", func(t *testing.T) { + t.Parallel() + + assert.Error(t, forkManager.ActivateFork(ForkName("EE"), 100)) + }) + + t.Run("activate already activated fork", func(t *testing.T) { + t.Parallel() + + assert.NoError(t, forkManager.ActivateFork(ForkName("A"), 100)) + + // count not changed + assert.Equal(t, handlersACnt, len(forkManager.handlersMap[ForkHandlerName("A")])) + assert.Equal(t, handlersBCnt, len(forkManager.handlersMap[ForkHandlerName("B")])) + }) + + t.Run("is fork enabled", func(t *testing.T) { + t.Parallel() + + assert.True(t, forkManager.IsForkEnabled(ForkName("A"), 0)) + assert.True(t, forkManager.IsForkEnabled(ForkName("A"), 100)) + assert.True(t, forkManager.IsForkEnabled(ForkName("A"), 200)) + + assert.False(t, forkManager.IsForkEnabled(ForkName("B"), 0)) + assert.True(t, forkManager.IsForkEnabled(ForkName("B"), 100)) + assert.True(t, forkManager.IsForkEnabled(ForkName("B"), 200)) + + assert.False(t, forkManager.IsForkEnabled(ForkName("C"), 0)) + assert.False(t, forkManager.IsForkEnabled(ForkName("C"), 100)) + assert.True(t, forkManager.IsForkEnabled(ForkName("C"), 200)) + assert.True(t, forkManager.IsForkEnabled(ForkName("C"), 300)) + + assert.False(t, forkManager.IsForkEnabled(ForkName("D"), 0)) + assert.False(t, forkManager.IsForkEnabled(ForkName("D"), 100)) + assert.False(t, forkManager.IsForkEnabled(ForkName("D"), 200)) + assert.True(t, forkManager.IsForkEnabled(ForkName("D"), 300)) + assert.True(t, forkManager.IsForkEnabled(ForkName("D"), 400)) + + assert.False(t, forkManager.IsForkEnabled(ForkName("FF"), 0)) + }) + + t.Run("is fork supported", func(t *testing.T) { + t.Parallel() + + assert.True(t, forkManager.IsForkSupported(ForkName("A"))) + assert.True(t, forkManager.IsForkSupported(ForkName("B"))) + assert.True(t, forkManager.IsForkSupported(ForkName("C"))) + assert.True(t, forkManager.IsForkSupported(ForkName("D"))) + + assert.False(t, forkManager.IsForkSupported(ForkName("CC"))) + }) + + t.Run("get fork block", func(t *testing.T) { + t.Parallel() + + b, err := forkManager.GetForkBlock(ForkName("A")) + assert.NoError(t, err) + assert.Equal(t, uint64(0), b) + + b, err = forkManager.GetForkBlock(ForkName("B")) + assert.NoError(t, err) + assert.Equal(t, uint64(100), b) + + b, err = forkManager.GetForkBlock(ForkName("C")) + assert.NoError(t, err) + assert.Equal(t, uint64(200), b) + + b, err = forkManager.GetForkBlock(ForkName("D")) + assert.NoError(t, err) + assert.Equal(t, uint64(300), b) + + _, err = forkManager.GetForkBlock(ForkName("DD")) + assert.Error(t, err) + }) + + t.Run("register handler not existing fork", func(t *testing.T) { + t.Parallel() + + assert.Error(t, forkManager.RegisterHandler(ForkName("EEE"), ForkHandlerName("E"), func() {})) + }) + + t.Run("get handler", func(t *testing.T) { + t.Parallel() + + for i := 0; i < 4; i++ { + forkManager.SetCurrentBlock(uint64(i)) + + assert.Equal(t, "AAH", forkManager.GetHandler("A").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "BAH", forkManager.GetHandler("B").(func() string)()) //nolint:forcetypeassert + assert.Nil(t, forkManager.GetHandler("C")) + + forkManager.SetCurrentBlock(uint64(100 + i)) + + assert.Equal(t, "AAH", forkManager.GetHandler("A").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "BBH", forkManager.GetHandler("B").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "CBH", forkManager.GetHandler("C").(func() string)()) //nolint:forcetypeassert + + forkManager.SetCurrentBlock(uint64(200 + i)) + + assert.Equal(t, "ACH", forkManager.GetHandler("A").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "BBH", forkManager.GetHandler("B").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "CBH", forkManager.GetHandler("C").(func() string)()) //nolint:forcetypeassert + + forkManager.SetCurrentBlock(uint64(300 + i)) + + assert.Equal(t, "ACH", forkManager.GetHandler("A").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "BDH", forkManager.GetHandler("B").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "CBH", forkManager.GetHandler("C").(func() string)()) //nolint:forcetypeassert + } + + assert.Nil(t, forkManager.GetHandler("D")) + }) +} + +func TestForkManager_Deactivate(t *testing.T) { + t.Parallel() + + forkManager := &forkManager{ + forkMap: map[ForkName]*Fork{}, + handlersMap: map[ForkHandlerName][]ForkActiveHandler{}, + } + + forkManager.RegisterFork(ForkName("A")) + forkManager.RegisterFork(ForkName("B")) + + assert.NoError(t, forkManager.RegisterHandler(ForkName("A"), "A", func() string { return "AAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkName("B"), "A", func() string { return "ABH" })) + + assert.NoError(t, forkManager.ActivateFork(ForkName("A"), 0)) + assert.NoError(t, forkManager.ActivateFork(ForkName("B"), 0)) + + assert.Equal(t, 2, len(forkManager.handlersMap[ForkHandlerName("A")])) + + assert.NoError(t, forkManager.DeactivateFork(ForkName("A"))) + + assert.Equal(t, 1, len(forkManager.handlersMap[ForkHandlerName("A")])) + + assert.NoError(t, forkManager.DeactivateFork(ForkName("B"))) + + assert.Equal(t, 0, len(forkManager.handlersMap[ForkHandlerName("A")])) +} diff --git a/server/server.go b/server/server.go index b0aef318cd..d60b905d04 100644 --- a/server/server.go +++ b/server/server.go @@ -16,6 +16,7 @@ import ( "github.com/0xPolygon/polygon-edge/blockchain/storage/leveldb" "github.com/0xPolygon/polygon-edge/blockchain/storage/memory" consensusPolyBFT "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/forkmanager" "github.com/0xPolygon/polygon-edge/archive" "github.com/0xPolygon/polygon-edge/blockchain" @@ -370,6 +371,9 @@ func NewServer(config *Config) (*Server, error) { return nil, err } + // update fork manager state + forkmanager.GetInstance().SetCurrentBlock(m.blockchain.Header().Number + 1) + // initialize data in consensus layer if err := m.consensus.Initialize(); err != nil { return nil, err From 89ba7f6f437b598dda47c9175ccc828bf8bae658 Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Mon, 29 May 2023 12:51:18 +0200 Subject: [PATCH 06/16] comments --- blockchain/blockchain.go | 2 +- blockchain/blockchain_test.go | 9 +++----- chain/params.go | 38 ++++++++++++++------------------ forkmanager/fork_manager.go | 14 +++++++++++- forkmanager/fork_manager_test.go | 10 ++++----- tests/state_test.go | 2 +- 6 files changed, 40 insertions(+), 35 deletions(-) diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index d4e60f6ee2..d720b0ce3a 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -1413,7 +1413,7 @@ func (b *Blockchain) Close() error { // CalculateBaseFee calculates the basefee of the header. func (b *Blockchain) CalculateBaseFee(parent *types.Header) uint64 { - if !b.config.Params.Forks.IsEnabled(chain.London, parent.Number) { + if !b.config.Params.Forks.IsActive(chain.London, parent.Number) { return chain.GenesisBaseFee } diff --git a/blockchain/blockchain_test.go b/blockchain/blockchain_test.go index ddc8a41c97..d1f882d533 100644 --- a/blockchain/blockchain_test.go +++ b/blockchain/blockchain_test.go @@ -1365,15 +1365,12 @@ func TestBlockchain_CalculateBaseFee(t *testing.T) { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { t.Parallel() - fork := chain.Fork(5) - forksAvailable := &chain.Forks{ - chain.London: &fork, - } - blockchain := Blockchain{ config: &chain.Chain{ Params: &chain.Params{ - Forks: forksAvailable, + Forks: &chain.Forks{ + chain.London: chain.NewFork(5), + }, }, Genesis: &chain.Genesis{ BaseFeeEM: test.elasticityMultiplier, diff --git a/chain/params.go b/chain/params.go index 993cfe78f1..ebf275f661 100644 --- a/chain/params.go +++ b/chain/params.go @@ -87,17 +87,13 @@ const ( EIP155 = "EIP155" ) -// Forks specifies when each fork is activated +// Forks is map which contains all forks and their starting blocks from genesis type Forks map[string]*Fork -func (f *Forks) IsEnabled(name string, block uint64) bool { - return active((*f)[name], block) -} - -func (f *Forks) IsSupported(name string) bool { - _, exists := (*f)[name] +func (f *Forks) IsActive(name string, block uint64) bool { + ff := (*f)[name] - return exists + return ff != nil && ff.Active(block) } func (f *Forks) SetFork(name string, value *Fork) { @@ -106,15 +102,15 @@ func (f *Forks) SetFork(name string, value *Fork) { func (f *Forks) At(block uint64) ForksInTime { return ForksInTime{ - Homestead: active((*f)[Homestead], block), - Byzantium: active((*f)[Byzantium], block), - Constantinople: active((*f)[Constantinople], block), - Petersburg: active((*f)[Petersburg], block), - Istanbul: active((*f)[Istanbul], block), - London: active((*f)[London], block), - EIP150: active((*f)[EIP150], block), - EIP158: active((*f)[EIP158], block), - EIP155: active((*f)[EIP155], block), + Homestead: f.IsActive(Homestead, block), + Byzantium: f.IsActive(Byzantium, block), + Constantinople: f.IsActive(Constantinople, block), + Petersburg: f.IsActive(Petersburg, block), + Istanbul: f.IsActive(Istanbul, block), + London: f.IsActive(London, block), + EIP150: f.IsActive(EIP150, block), + EIP158: f.IsActive(EIP158, block), + EIP155: f.IsActive(EIP155, block), } } @@ -134,6 +130,7 @@ func (f Fork) Int() *big.Int { return big.NewInt(int64(f)) } +// ForksInTime should contain all supported forks by current edge version type ForksInTime struct { Homestead, Byzantium, @@ -146,6 +143,8 @@ type ForksInTime struct { EIP155 bool } +// AllForksEnabled should contain all supported forks by current edge version +// All forks should be available from block 0 var AllForksEnabled = &Forks{ Homestead: NewFork(0), EIP150: NewFork(0), @@ -158,10 +157,7 @@ var AllForksEnabled = &Forks{ London: NewFork(0), } -func active(ff *Fork, block uint64) bool { - return ff != nil && ff.Active(block) -} - +// IsForkAvailable returns true if some fork defined by its name is supported by current edge version func IsForkAvailable(name string) bool { _, found := (*AllForksEnabled)[name] diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go index fbbd888a84..a24cea5ee0 100644 --- a/forkmanager/fork_manager.go +++ b/forkmanager/fork_manager.go @@ -31,6 +31,7 @@ type forkManager struct { currentHandlers map[ForkHandlerName]interface{} } +// GeInstance returns fork manager singleton instance. Thread safe func GetInstance() *forkManager { forkManagerInstanceLock.Lock() defer forkManagerInstanceLock.Unlock() @@ -45,6 +46,7 @@ func GetInstance() *forkManager { return forkManagerInstance } +// RegisterFork registers fork by its name func (fm *forkManager) RegisterFork(name ForkName) { fm.lock.Lock() defer fm.lock.Unlock() @@ -57,6 +59,7 @@ func (fm *forkManager) RegisterFork(name ForkName) { } } +// RegisterHandler registers handler by its name for specific fork func (fm *forkManager) RegisterHandler(forkName ForkName, handlerName ForkHandlerName, handler interface{}) error { fm.lock.Lock() defer fm.lock.Unlock() @@ -71,6 +74,8 @@ func (fm *forkManager) RegisterHandler(forkName ForkName, handlerName ForkHandle return nil } +// ActivateFork activates fork from some block number +// All handlers belong to this fork are also activated func (fm *forkManager) ActivateFork(forkName ForkName, blockNumber uint64) error { fm.lock.Lock() defer fm.lock.Unlock() @@ -94,6 +99,8 @@ func (fm *forkManager) ActivateFork(forkName ForkName, blockNumber uint64) error return nil } +// DeactivateFork de-activates fork +// All handlers belong to this fork are also de-activated func (fm *forkManager) DeactivateFork(forkName ForkName) error { fm.lock.Lock() defer fm.lock.Unlock() @@ -116,6 +123,7 @@ func (fm *forkManager) DeactivateFork(forkName ForkName) error { return nil } +// SetCurrentBlock updates internal structures which allowes using GetHandler without specifying block func (fm *forkManager) SetCurrentBlock(currentBlock uint64) { fm.lock.Lock() defer fm.lock.Unlock() @@ -134,6 +142,7 @@ func (fm *forkManager) SetCurrentBlock(currentBlock uint64) { } } +// GetHandler retrives handler defined by its name for current block (@see SetCurrentBlock) func (fm *forkManager) GetHandler(name ForkHandlerName) interface{} { fm.lock.Lock() defer fm.lock.Unlock() @@ -141,7 +150,8 @@ func (fm *forkManager) GetHandler(name ForkHandlerName) interface{} { return fm.currentHandlers[name] } -func (fm *forkManager) IsForkSupported(name ForkName) bool { +// IsForkRegistered checks if fork is registered +func (fm *forkManager) IsForkRegistered(name ForkName) bool { fm.lock.Lock() defer fm.lock.Unlock() @@ -150,6 +160,7 @@ func (fm *forkManager) IsForkSupported(name ForkName) bool { return exists } +// IsForkEnabled checks if fork is registered and enabled for specific block func (fm *forkManager) IsForkEnabled(name ForkName, blockNumber uint64) bool { fm.lock.Lock() defer fm.lock.Unlock() @@ -162,6 +173,7 @@ func (fm *forkManager) IsForkEnabled(name ForkName, blockNumber uint64) bool { return fork.IsActive && fork.FromBlockNumber <= blockNumber } +// GetForkBlock returns fork block if fork is registered and activated func (fm *forkManager) GetForkBlock(name ForkName) (uint64, error) { fm.lock.Lock() defer fm.lock.Unlock() diff --git a/forkmanager/fork_manager_test.go b/forkmanager/fork_manager_test.go index a37661191d..d6c51b5670 100644 --- a/forkmanager/fork_manager_test.go +++ b/forkmanager/fork_manager_test.go @@ -78,12 +78,12 @@ func TestForkManager(t *testing.T) { t.Run("is fork supported", func(t *testing.T) { t.Parallel() - assert.True(t, forkManager.IsForkSupported(ForkName("A"))) - assert.True(t, forkManager.IsForkSupported(ForkName("B"))) - assert.True(t, forkManager.IsForkSupported(ForkName("C"))) - assert.True(t, forkManager.IsForkSupported(ForkName("D"))) + assert.True(t, forkManager.IsForkRegistered(ForkName("A"))) + assert.True(t, forkManager.IsForkRegistered(ForkName("B"))) + assert.True(t, forkManager.IsForkRegistered(ForkName("C"))) + assert.True(t, forkManager.IsForkRegistered(ForkName("D"))) - assert.False(t, forkManager.IsForkSupported(ForkName("CC"))) + assert.False(t, forkManager.IsForkRegistered(ForkName("CC"))) }) t.Run("get fork block", func(t *testing.T) { diff --git a/tests/state_test.go b/tests/state_test.go index 24650dd273..198f39b5c1 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -42,7 +42,7 @@ func RunSpecificTest(t *testing.T, file string, c testCase, name, fork string, i var baseFee *big.Int - if config.IsEnabled(chain.London, 0) { + if config.IsActive(chain.London, 0) { if c.Env.BaseFee != "" { baseFee = stringToBigIntT(t, c.Env.BaseFee) } else { From ed6297e9f8afc3fc163d517a79c124be3f64c8e8 Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Tue, 30 May 2023 12:07:55 +0200 Subject: [PATCH 07/16] state is not good. at the same time we probably need to access few different blocks --- consensus/polybft/consensus_runtime.go | 3 -- forkmanager/fork_manager.go | 33 ++++++++------------- forkmanager/fork_manager_test.go | 41 ++++++++++++-------------- server/server.go | 4 --- 4 files changed, 31 insertions(+), 50 deletions(-) diff --git a/consensus/polybft/consensus_runtime.go b/consensus/polybft/consensus_runtime.go index dfbbe0b6f4..66017cd5b0 100644 --- a/consensus/polybft/consensus_runtime.go +++ b/consensus/polybft/consensus_runtime.go @@ -14,7 +14,6 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" - "github.com/0xPolygon/polygon-edge/forkmanager" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" @@ -271,8 +270,6 @@ func (c *consensusRuntime) OnBlockInserted(fullBlock *types.FullBlock) { c.lock.Lock() defer c.lock.Unlock() - forkmanager.GetInstance().SetCurrentBlock(fullBlock.Block.Number() + 1) - if c.lastBuiltBlock != nil && c.lastBuiltBlock.Number >= fullBlock.Block.Number() { c.logger.Debug("on block inserted already handled", "current", c.lastBuiltBlock.Number, "block", fullBlock.Block.Number()) diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go index a24cea5ee0..60e3bd0998 100644 --- a/forkmanager/fork_manager.go +++ b/forkmanager/fork_manager.go @@ -27,8 +27,6 @@ type forkManager struct { forkMap map[ForkName]*Fork handlersMap map[ForkHandlerName][]ForkActiveHandler - - currentHandlers map[ForkHandlerName]interface{} } // GeInstance returns fork manager singleton instance. Thread safe @@ -123,31 +121,24 @@ func (fm *forkManager) DeactivateFork(forkName ForkName) error { return nil } -// SetCurrentBlock updates internal structures which allowes using GetHandler without specifying block -func (fm *forkManager) SetCurrentBlock(currentBlock uint64) { +func (fm *forkManager) GetHandler(name ForkHandlerName, blockNumber uint64) interface{} { fm.lock.Lock() defer fm.lock.Unlock() - fm.currentHandlers = map[ForkHandlerName]interface{}{} - - for handlerName, handlers := range fm.handlersMap { - // binary search to find first position inside []*ForkHandler where FromBlockNumber >= blockNumber - pos := sort.Search(len(handlers), func(i int) bool { - return currentBlock < handlers[i].FromBlockNumber - }) - 1 - - if pos >= 0 { - fm.currentHandlers[handlerName] = handlers[pos].Handler - } + handlers, exists := fm.handlersMap[name] + if !exists { + return nil } -} -// GetHandler retrives handler defined by its name for current block (@see SetCurrentBlock) -func (fm *forkManager) GetHandler(name ForkHandlerName) interface{} { - fm.lock.Lock() - defer fm.lock.Unlock() + // binary search to find first position where handler.FromBlockNumber < blockNumber + pos := sort.Search(len(handlers), func(i int) bool { + return blockNumber < handlers[i].FromBlockNumber + }) - 1 + if pos < 0 { + return nil + } - return fm.currentHandlers[name] + return handlers[pos].Handler } // IsForkRegistered checks if fork is registered diff --git a/forkmanager/fork_manager_test.go b/forkmanager/fork_manager_test.go index d6c51b5670..6d8f447c66 100644 --- a/forkmanager/fork_manager_test.go +++ b/forkmanager/fork_manager_test.go @@ -21,7 +21,7 @@ func TestForkManager(t *testing.T) { assert.NoError(t, forkManager.RegisterHandler(ForkName("A"), "B", func() string { return "BAH" })) assert.NoError(t, forkManager.RegisterHandler(ForkName("B"), "B", func() string { return "BBH" })) assert.NoError(t, forkManager.RegisterHandler(ForkName("D"), "B", func() string { return "BDH" })) - assert.NoError(t, forkManager.RegisterHandler(ForkName("B"), "C", func() string { return "CBH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkName("C"), "C", func() string { return "CCH" })) assert.NoError(t, forkManager.ActivateFork(ForkName("A"), 0)) assert.NoError(t, forkManager.ActivateFork(ForkName("B"), 100)) @@ -118,33 +118,30 @@ func TestForkManager(t *testing.T) { t.Run("get handler", func(t *testing.T) { t.Parallel() - for i := 0; i < 4; i++ { - forkManager.SetCurrentBlock(uint64(i)) - - assert.Equal(t, "AAH", forkManager.GetHandler("A").(func() string)()) //nolint:forcetypeassert - assert.Equal(t, "BAH", forkManager.GetHandler("B").(func() string)()) //nolint:forcetypeassert - assert.Nil(t, forkManager.GetHandler("C")) - - forkManager.SetCurrentBlock(uint64(100 + i)) - - assert.Equal(t, "AAH", forkManager.GetHandler("A").(func() string)()) //nolint:forcetypeassert - assert.Equal(t, "BBH", forkManager.GetHandler("B").(func() string)()) //nolint:forcetypeassert - assert.Equal(t, "CBH", forkManager.GetHandler("C").(func() string)()) //nolint:forcetypeassert + execute := func(name ForkHandlerName, block uint64) string { + //nolint:forcetypeassert + return forkManager.GetHandler(name, block).(func() string)() + } - forkManager.SetCurrentBlock(uint64(200 + i)) + for i := uint64(0); i < uint64(4); i++ { + assert.Equal(t, "AAH", execute("A", i)) + assert.Equal(t, "BAH", execute("B", i)) + assert.Nil(t, forkManager.GetHandler("C", i)) - assert.Equal(t, "ACH", forkManager.GetHandler("A").(func() string)()) //nolint:forcetypeassert - assert.Equal(t, "BBH", forkManager.GetHandler("B").(func() string)()) //nolint:forcetypeassert - assert.Equal(t, "CBH", forkManager.GetHandler("C").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "AAH", execute("A", 100+i)) + assert.Equal(t, "BBH", execute("B", 100+i)) + assert.Nil(t, forkManager.GetHandler("C", 100+i)) - forkManager.SetCurrentBlock(uint64(300 + i)) + assert.Equal(t, "ACH", execute("A", 200+i)) + assert.Equal(t, "BBH", execute("B", 200+i)) + assert.Equal(t, "CCH", execute("C", 200+i)) - assert.Equal(t, "ACH", forkManager.GetHandler("A").(func() string)()) //nolint:forcetypeassert - assert.Equal(t, "BDH", forkManager.GetHandler("B").(func() string)()) //nolint:forcetypeassert - assert.Equal(t, "CBH", forkManager.GetHandler("C").(func() string)()) //nolint:forcetypeassert + assert.Equal(t, "ACH", execute("A", 300+i)) + assert.Equal(t, "BDH", execute("B", 300+i)) + assert.Equal(t, "CCH", execute("C", 300+i)) } - assert.Nil(t, forkManager.GetHandler("D")) + assert.Nil(t, forkManager.GetHandler("D", 0)) }) } diff --git a/server/server.go b/server/server.go index d60b905d04..b0aef318cd 100644 --- a/server/server.go +++ b/server/server.go @@ -16,7 +16,6 @@ import ( "github.com/0xPolygon/polygon-edge/blockchain/storage/leveldb" "github.com/0xPolygon/polygon-edge/blockchain/storage/memory" consensusPolyBFT "github.com/0xPolygon/polygon-edge/consensus/polybft" - "github.com/0xPolygon/polygon-edge/forkmanager" "github.com/0xPolygon/polygon-edge/archive" "github.com/0xPolygon/polygon-edge/blockchain" @@ -371,9 +370,6 @@ func NewServer(config *Config) (*Server, error) { return nil, err } - // update fork manager state - forkmanager.GetInstance().SetCurrentBlock(m.blockchain.Header().Number + 1) - // initialize data in consensus layer if err := m.consensus.Initialize(); err != nil { return nil, err From 00764af1a8f08063b15f349b74c8a0309ec6fd7f Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Tue, 30 May 2023 13:34:30 +0200 Subject: [PATCH 08/16] small change --- chain/params.go | 14 ++++++++++---- consensus/polybft/polybft.go | 24 ++++++++++++++++-------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/chain/params.go b/chain/params.go index ebf275f661..4364b973fa 100644 --- a/chain/params.go +++ b/chain/params.go @@ -2,6 +2,7 @@ package chain import ( "errors" + "fmt" "math/big" "sort" @@ -157,9 +158,14 @@ var AllForksEnabled = &Forks{ London: NewFork(0), } -// IsForkAvailable returns true if some fork defined by its name is supported by current edge version -func IsForkAvailable(name string) bool { - _, found := (*AllForksEnabled)[name] +// CheckMissingFork checks if there is a fork received as a genesis parameter that is not supported +// by the current edge version. +func CheckMissingFork(forks *Forks) error { + for name := range *forks { + if _, found := (*AllForksEnabled)[name]; !found { + return fmt.Errorf("fork is not available: %s", name) + } + } - return found + return nil } diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go index 75de5ce59b..86ba32a443 100644 --- a/consensus/polybft/polybft.go +++ b/consensus/polybft/polybft.go @@ -363,19 +363,27 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st } func ForkManagerFactory(forks *chain.Forks) error { + if err := chain.CheckMissingFork(forks); err != nil { + return err + } + fm := forkmanager.GetInstance() + // Register forks + for name := range *forks { + fm.RegisterFork(forkmanager.ForkName(name)) + } + + // Register handlers here + + // Activate forks for name, block := range *forks { - if !chain.IsForkAvailable(name) { - return fmt.Errorf("fork is not available: %s", name) + if block == nil { + continue } - fm.RegisterFork(forkmanager.ForkName(name)) - - if block != nil { - if err := fm.ActivateFork(forkmanager.ForkName(name), (uint64)(*block)); err != nil { - return err - } + if err := fm.ActivateFork(forkmanager.ForkName(name), (uint64)(*block)); err != nil { + return err } } From 7ecf16cddf4205543949e8822ff77940df5dd8af Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Tue, 30 May 2023 14:07:01 +0200 Subject: [PATCH 09/16] cr fix --- consensus/polybft/polybft.go | 6 +++--- forkmanager/fork_manager.go | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go index 86ba32a443..876edf0bd5 100644 --- a/consensus/polybft/polybft.go +++ b/consensus/polybft/polybft.go @@ -377,12 +377,12 @@ func ForkManagerFactory(forks *chain.Forks) error { // Register handlers here // Activate forks - for name, block := range *forks { - if block == nil { + for name, blockNumber := range *forks { + if blockNumber == nil { continue } - if err := fm.ActivateFork(forkmanager.ForkName(name), (uint64)(*block)); err != nil { + if err := fm.ActivateFork(forkmanager.ForkName(name), (uint64)(*blockNumber)); err != nil { return err } } diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go index 60e3bd0998..79a7dedc41 100644 --- a/forkmanager/fork_manager.go +++ b/forkmanager/fork_manager.go @@ -121,6 +121,7 @@ func (fm *forkManager) DeactivateFork(forkName ForkName) error { return nil } +// GetHandler retrieves handler for handler name and for a block number func (fm *forkManager) GetHandler(name ForkHandlerName, blockNumber uint64) interface{} { fm.lock.Lock() defer fm.lock.Unlock() @@ -130,7 +131,7 @@ func (fm *forkManager) GetHandler(name ForkHandlerName, blockNumber uint64) inte return nil } - // binary search to find first position where handler.FromBlockNumber < blockNumber + // binary search to find the latest handler defined for a specific block pos := sort.Search(len(handlers), func(i int) bool { return blockNumber < handlers[i].FromBlockNumber }) - 1 @@ -171,7 +172,7 @@ func (fm *forkManager) GetForkBlock(name ForkName) (uint64, error) { fork, exists := fm.forkMap[name] if !exists { - return 0, fmt.Errorf("fork does not exists: %s", name) + return 0, fmt.Errorf("fork does not exist: %s", name) } if !fork.IsActive { From debb89eb4e150fb86007192b8e92852328dc3c8f Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Tue, 30 May 2023 14:47:47 +0200 Subject: [PATCH 10/16] const in test --- forkmanager/fork_manager_test.go | 155 +++++++++++++++++-------------- 1 file changed, 84 insertions(+), 71 deletions(-) diff --git a/forkmanager/fork_manager_test.go b/forkmanager/fork_manager_test.go index 6d8f447c66..9e7f1237df 100644 --- a/forkmanager/fork_manager_test.go +++ b/forkmanager/fork_manager_test.go @@ -6,30 +6,43 @@ import ( "github.com/stretchr/testify/assert" ) +const ( + HandlerA = ForkHandlerName("HA") + HandlerB = ForkHandlerName("HB") + HandlerC = ForkHandlerName("HC") + HandlerD = ForkHandlerName("HD") + + ForkA = ForkName("A") + ForkB = ForkName("B") + ForkC = ForkName("C") + ForkD = ForkName("D") + ForkE = ForkName("E") +) + func TestForkManager(t *testing.T) { t.Parallel() forkManager := GetInstance() - forkManager.RegisterFork(ForkName("A")) - forkManager.RegisterFork(ForkName("B")) - forkManager.RegisterFork(ForkName("C")) - forkManager.RegisterFork(ForkName("D")) + forkManager.RegisterFork(ForkA) + forkManager.RegisterFork(ForkB) + forkManager.RegisterFork(ForkC) + forkManager.RegisterFork(ForkD) - assert.NoError(t, forkManager.RegisterHandler(ForkName("A"), "A", func() string { return "AAH" })) - assert.NoError(t, forkManager.RegisterHandler(ForkName("C"), "A", func() string { return "ACH" })) - assert.NoError(t, forkManager.RegisterHandler(ForkName("A"), "B", func() string { return "BAH" })) - assert.NoError(t, forkManager.RegisterHandler(ForkName("B"), "B", func() string { return "BBH" })) - assert.NoError(t, forkManager.RegisterHandler(ForkName("D"), "B", func() string { return "BDH" })) - assert.NoError(t, forkManager.RegisterHandler(ForkName("C"), "C", func() string { return "CCH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkA, HandlerA, func() string { return "AAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkC, HandlerA, func() string { return "ACH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkA, HandlerB, func() string { return "BAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkB, HandlerB, func() string { return "BBH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkD, HandlerB, func() string { return "BDH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkC, HandlerC, func() string { return "CCH" })) - assert.NoError(t, forkManager.ActivateFork(ForkName("A"), 0)) - assert.NoError(t, forkManager.ActivateFork(ForkName("B"), 100)) - assert.NoError(t, forkManager.ActivateFork(ForkName("C"), 200)) - assert.NoError(t, forkManager.ActivateFork(ForkName("D"), 300)) + assert.NoError(t, forkManager.ActivateFork(ForkA, 0)) + assert.NoError(t, forkManager.ActivateFork(ForkB, 100)) + assert.NoError(t, forkManager.ActivateFork(ForkC, 200)) + assert.NoError(t, forkManager.ActivateFork(ForkD, 300)) - handlersACnt := len(forkManager.handlersMap[ForkHandlerName("A")]) - handlersBCnt := len(forkManager.handlersMap[ForkHandlerName("B")]) + handlersACnt := len(forkManager.handlersMap[HandlerA]) + handlersBCnt := len(forkManager.handlersMap[HandlerB]) assert.Equal(t, 2, handlersACnt) assert.Equal(t, 3, handlersBCnt) @@ -37,82 +50,82 @@ func TestForkManager(t *testing.T) { t.Run("activate not registered fork", func(t *testing.T) { t.Parallel() - assert.Error(t, forkManager.ActivateFork(ForkName("EE"), 100)) + assert.Error(t, forkManager.ActivateFork(ForkE, 100)) }) t.Run("activate already activated fork", func(t *testing.T) { t.Parallel() - assert.NoError(t, forkManager.ActivateFork(ForkName("A"), 100)) + assert.NoError(t, forkManager.ActivateFork(ForkA, 100)) // count not changed - assert.Equal(t, handlersACnt, len(forkManager.handlersMap[ForkHandlerName("A")])) - assert.Equal(t, handlersBCnt, len(forkManager.handlersMap[ForkHandlerName("B")])) + assert.Equal(t, handlersACnt, len(forkManager.handlersMap[HandlerA])) + assert.Equal(t, handlersBCnt, len(forkManager.handlersMap[HandlerB])) }) t.Run("is fork enabled", func(t *testing.T) { t.Parallel() - assert.True(t, forkManager.IsForkEnabled(ForkName("A"), 0)) - assert.True(t, forkManager.IsForkEnabled(ForkName("A"), 100)) - assert.True(t, forkManager.IsForkEnabled(ForkName("A"), 200)) + assert.True(t, forkManager.IsForkEnabled(ForkA, 0)) + assert.True(t, forkManager.IsForkEnabled(ForkA, 100)) + assert.True(t, forkManager.IsForkEnabled(ForkA, 200)) - assert.False(t, forkManager.IsForkEnabled(ForkName("B"), 0)) - assert.True(t, forkManager.IsForkEnabled(ForkName("B"), 100)) - assert.True(t, forkManager.IsForkEnabled(ForkName("B"), 200)) + assert.False(t, forkManager.IsForkEnabled(ForkB, 0)) + assert.True(t, forkManager.IsForkEnabled(ForkB, 100)) + assert.True(t, forkManager.IsForkEnabled(ForkB, 200)) - assert.False(t, forkManager.IsForkEnabled(ForkName("C"), 0)) - assert.False(t, forkManager.IsForkEnabled(ForkName("C"), 100)) - assert.True(t, forkManager.IsForkEnabled(ForkName("C"), 200)) - assert.True(t, forkManager.IsForkEnabled(ForkName("C"), 300)) + assert.False(t, forkManager.IsForkEnabled(ForkC, 0)) + assert.False(t, forkManager.IsForkEnabled(ForkC, 100)) + assert.True(t, forkManager.IsForkEnabled(ForkC, 200)) + assert.True(t, forkManager.IsForkEnabled(ForkC, 300)) - assert.False(t, forkManager.IsForkEnabled(ForkName("D"), 0)) - assert.False(t, forkManager.IsForkEnabled(ForkName("D"), 100)) - assert.False(t, forkManager.IsForkEnabled(ForkName("D"), 200)) - assert.True(t, forkManager.IsForkEnabled(ForkName("D"), 300)) - assert.True(t, forkManager.IsForkEnabled(ForkName("D"), 400)) + assert.False(t, forkManager.IsForkEnabled(ForkD, 0)) + assert.False(t, forkManager.IsForkEnabled(ForkD, 100)) + assert.False(t, forkManager.IsForkEnabled(ForkD, 200)) + assert.True(t, forkManager.IsForkEnabled(ForkD, 300)) + assert.True(t, forkManager.IsForkEnabled(ForkD, 400)) - assert.False(t, forkManager.IsForkEnabled(ForkName("FF"), 0)) + assert.False(t, forkManager.IsForkEnabled(ForkE, 0)) }) t.Run("is fork supported", func(t *testing.T) { t.Parallel() - assert.True(t, forkManager.IsForkRegistered(ForkName("A"))) - assert.True(t, forkManager.IsForkRegistered(ForkName("B"))) - assert.True(t, forkManager.IsForkRegistered(ForkName("C"))) - assert.True(t, forkManager.IsForkRegistered(ForkName("D"))) + assert.True(t, forkManager.IsForkRegistered(ForkA)) + assert.True(t, forkManager.IsForkRegistered(ForkB)) + assert.True(t, forkManager.IsForkRegistered(ForkC)) + assert.True(t, forkManager.IsForkRegistered(ForkD)) - assert.False(t, forkManager.IsForkRegistered(ForkName("CC"))) + assert.False(t, forkManager.IsForkRegistered(ForkE)) }) t.Run("get fork block", func(t *testing.T) { t.Parallel() - b, err := forkManager.GetForkBlock(ForkName("A")) + b, err := forkManager.GetForkBlock(ForkA) assert.NoError(t, err) assert.Equal(t, uint64(0), b) - b, err = forkManager.GetForkBlock(ForkName("B")) + b, err = forkManager.GetForkBlock(ForkB) assert.NoError(t, err) assert.Equal(t, uint64(100), b) - b, err = forkManager.GetForkBlock(ForkName("C")) + b, err = forkManager.GetForkBlock(ForkC) assert.NoError(t, err) assert.Equal(t, uint64(200), b) - b, err = forkManager.GetForkBlock(ForkName("D")) + b, err = forkManager.GetForkBlock(ForkD) assert.NoError(t, err) assert.Equal(t, uint64(300), b) - _, err = forkManager.GetForkBlock(ForkName("DD")) + _, err = forkManager.GetForkBlock(ForkE) assert.Error(t, err) }) t.Run("register handler not existing fork", func(t *testing.T) { t.Parallel() - assert.Error(t, forkManager.RegisterHandler(ForkName("EEE"), ForkHandlerName("E"), func() {})) + assert.Error(t, forkManager.RegisterHandler(ForkE, HandlerD, func() {})) }) t.Run("get handler", func(t *testing.T) { @@ -124,24 +137,24 @@ func TestForkManager(t *testing.T) { } for i := uint64(0); i < uint64(4); i++ { - assert.Equal(t, "AAH", execute("A", i)) - assert.Equal(t, "BAH", execute("B", i)) - assert.Nil(t, forkManager.GetHandler("C", i)) + assert.Equal(t, "AAH", execute(HandlerA, i)) + assert.Equal(t, "BAH", execute(HandlerB, i)) + assert.Nil(t, forkManager.GetHandler(HandlerC, i)) - assert.Equal(t, "AAH", execute("A", 100+i)) - assert.Equal(t, "BBH", execute("B", 100+i)) - assert.Nil(t, forkManager.GetHandler("C", 100+i)) + assert.Equal(t, "AAH", execute(HandlerA, 100+i)) + assert.Equal(t, "BBH", execute(HandlerB, 100+i)) + assert.Nil(t, forkManager.GetHandler(HandlerC, 100+i)) - assert.Equal(t, "ACH", execute("A", 200+i)) - assert.Equal(t, "BBH", execute("B", 200+i)) - assert.Equal(t, "CCH", execute("C", 200+i)) + assert.Equal(t, "ACH", execute(HandlerA, 200+i)) + assert.Equal(t, "BBH", execute(HandlerB, 200+i)) + assert.Equal(t, "CCH", execute(HandlerC, 200+i)) - assert.Equal(t, "ACH", execute("A", 300+i)) - assert.Equal(t, "BDH", execute("B", 300+i)) - assert.Equal(t, "CCH", execute("C", 300+i)) + assert.Equal(t, "ACH", execute(HandlerA, 300+i)) + assert.Equal(t, "BDH", execute(HandlerB, 300+i)) + assert.Equal(t, "CCH", execute(HandlerC, 300+i)) } - assert.Nil(t, forkManager.GetHandler("D", 0)) + assert.Nil(t, forkManager.GetHandler(HandlerD, 0)) }) } @@ -153,22 +166,22 @@ func TestForkManager_Deactivate(t *testing.T) { handlersMap: map[ForkHandlerName][]ForkActiveHandler{}, } - forkManager.RegisterFork(ForkName("A")) - forkManager.RegisterFork(ForkName("B")) + forkManager.RegisterFork(ForkA) + forkManager.RegisterFork(ForkB) - assert.NoError(t, forkManager.RegisterHandler(ForkName("A"), "A", func() string { return "AAH" })) - assert.NoError(t, forkManager.RegisterHandler(ForkName("B"), "A", func() string { return "ABH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkA, HandlerA, func() string { return "AAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkB, HandlerA, func() string { return "ABH" })) - assert.NoError(t, forkManager.ActivateFork(ForkName("A"), 0)) - assert.NoError(t, forkManager.ActivateFork(ForkName("B"), 0)) + assert.NoError(t, forkManager.ActivateFork(ForkA, 0)) + assert.NoError(t, forkManager.ActivateFork(ForkB, 0)) - assert.Equal(t, 2, len(forkManager.handlersMap[ForkHandlerName("A")])) + assert.Equal(t, 2, len(forkManager.handlersMap[HandlerA])) - assert.NoError(t, forkManager.DeactivateFork(ForkName("A"))) + assert.NoError(t, forkManager.DeactivateFork(ForkA)) - assert.Equal(t, 1, len(forkManager.handlersMap[ForkHandlerName("A")])) + assert.Equal(t, 1, len(forkManager.handlersMap[HandlerA])) - assert.NoError(t, forkManager.DeactivateFork(ForkName("B"))) + assert.NoError(t, forkManager.DeactivateFork(ForkB)) - assert.Equal(t, 0, len(forkManager.handlersMap[ForkHandlerName("A")])) + assert.Equal(t, 0, len(forkManager.handlersMap[HandlerA])) } From 37e021cfa5311fa38e4a120d16ad8fe9793e75be Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Wed, 31 May 2023 10:06:42 +0200 Subject: [PATCH 11/16] cr fixes --- chain/params.go | 4 ++- consensus/polybft/polybft.go | 26 +------------------ forkmanager/fork.go | 24 ++++++++++++------ forkmanager/fork_manager.go | 38 ++++++++++++++-------------- forkmanager/fork_manager_test.go | 26 +++++++++---------- server/server.go | 43 +++++++++++++++++++++++++++++--- 6 files changed, 91 insertions(+), 70 deletions(-) diff --git a/chain/params.go b/chain/params.go index 4364b973fa..4ed158f3b2 100644 --- a/chain/params.go +++ b/chain/params.go @@ -91,16 +91,19 @@ const ( // Forks is map which contains all forks and their starting blocks from genesis type Forks map[string]*Fork +// IsActive returns true if fork defined by name exists and defined for the block func (f *Forks) IsActive(name string, block uint64) bool { ff := (*f)[name] return ff != nil && ff.Active(block) } +// SetFork adds/updates fork defined by name func (f *Forks) SetFork(name string, value *Fork) { (*f)[name] = value } +// At returns ForksInTime instance that shows which supported forks are enabled for the block func (f *Forks) At(block uint64) ForksInTime { return ForksInTime{ Homestead: f.IsActive(Homestead, block), @@ -145,7 +148,6 @@ type ForksInTime struct { } // AllForksEnabled should contain all supported forks by current edge version -// All forks should be available from block 0 var AllForksEnabled = &Forks{ Homestead: NewFork(0), EIP150: NewFork(0), diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go index 876edf0bd5..399375db9b 100644 --- a/consensus/polybft/polybft.go +++ b/consensus/polybft/polybft.go @@ -16,7 +16,6 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" - "github.com/0xPolygon/polygon-edge/forkmanager" "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/progress" "github.com/0xPolygon/polygon-edge/network" @@ -363,30 +362,7 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st } func ForkManagerFactory(forks *chain.Forks) error { - if err := chain.CheckMissingFork(forks); err != nil { - return err - } - - fm := forkmanager.GetInstance() - - // Register forks - for name := range *forks { - fm.RegisterFork(forkmanager.ForkName(name)) - } - - // Register handlers here - - // Activate forks - for name, blockNumber := range *forks { - if blockNumber == nil { - continue - } - - if err := fm.ActivateFork(forkmanager.ForkName(name), (uint64)(*blockNumber)); err != nil { - return err - } - } - + // place fork manager handler registration here return nil } diff --git a/forkmanager/fork.go b/forkmanager/fork.go index 2d41d2699d..9b6b717c4b 100644 --- a/forkmanager/fork.go +++ b/forkmanager/fork.go @@ -1,17 +1,25 @@ package forkmanager -type ForkHandlerName string - -type ForkName string +// HandlerDesc gives description for the handler +// eq: "extra", "proposer_calculator", etc +type HandlerDesc string +// Fork structure defines one fork type Fork struct { - Name ForkName + // name of the fork + Name string + // after the fork is activated, `FromBlockNumber` shows from which block is enabled FromBlockNumber uint64 - IsActive bool - Handlers map[ForkHandlerName]interface{} + // this value is false if fork is registered but not activated + IsActive bool + // map of all handlers registered for this fork + Handlers map[HandlerDesc]interface{} } -type ForkActiveHandler struct { +// Handler defines one custom handler +type Handler struct { + // Handler should be active from block `FromBlockNumber`` FromBlockNumber uint64 - Handler interface{} + // instance of some structure, function etc + Handler interface{} } diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go index 79a7dedc41..9c6122a8bf 100644 --- a/forkmanager/fork_manager.go +++ b/forkmanager/fork_manager.go @@ -25,8 +25,8 @@ var ( type forkManager struct { lock sync.Mutex - forkMap map[ForkName]*Fork - handlersMap map[ForkHandlerName][]ForkActiveHandler + forkMap map[string]*Fork + handlersMap map[HandlerDesc][]Handler } // GeInstance returns fork manager singleton instance. Thread safe @@ -36,8 +36,8 @@ func GetInstance() *forkManager { if forkManagerInstance == nil { forkManagerInstance = &forkManager{ - forkMap: map[ForkName]*Fork{}, - handlersMap: map[ForkHandlerName][]ForkActiveHandler{}, + forkMap: map[string]*Fork{}, + handlersMap: map[HandlerDesc][]Handler{}, } } @@ -45,7 +45,7 @@ func GetInstance() *forkManager { } // RegisterFork registers fork by its name -func (fm *forkManager) RegisterFork(name ForkName) { +func (fm *forkManager) RegisterFork(name string) { fm.lock.Lock() defer fm.lock.Unlock() @@ -53,12 +53,12 @@ func (fm *forkManager) RegisterFork(name ForkName) { Name: name, FromBlockNumber: 0, IsActive: false, - Handlers: map[ForkHandlerName]interface{}{}, + Handlers: map[HandlerDesc]interface{}{}, } } // RegisterHandler registers handler by its name for specific fork -func (fm *forkManager) RegisterHandler(forkName ForkName, handlerName ForkHandlerName, handler interface{}) error { +func (fm *forkManager) RegisterHandler(forkName string, handlerName HandlerDesc, handler interface{}) error { fm.lock.Lock() defer fm.lock.Unlock() @@ -74,7 +74,7 @@ func (fm *forkManager) RegisterHandler(forkName ForkName, handlerName ForkHandle // ActivateFork activates fork from some block number // All handlers belong to this fork are also activated -func (fm *forkManager) ActivateFork(forkName ForkName, blockNumber uint64) error { +func (fm *forkManager) ActivateFork(forkName string, blockNumber uint64) error { fm.lock.Lock() defer fm.lock.Unlock() @@ -99,7 +99,7 @@ func (fm *forkManager) ActivateFork(forkName ForkName, blockNumber uint64) error // DeactivateFork de-activates fork // All handlers belong to this fork are also de-activated -func (fm *forkManager) DeactivateFork(forkName ForkName) error { +func (fm *forkManager) DeactivateFork(forkName string) error { fm.lock.Lock() defer fm.lock.Unlock() @@ -122,7 +122,7 @@ func (fm *forkManager) DeactivateFork(forkName ForkName) error { } // GetHandler retrieves handler for handler name and for a block number -func (fm *forkManager) GetHandler(name ForkHandlerName, blockNumber uint64) interface{} { +func (fm *forkManager) GetHandler(name HandlerDesc, blockNumber uint64) interface{} { fm.lock.Lock() defer fm.lock.Unlock() @@ -143,7 +143,7 @@ func (fm *forkManager) GetHandler(name ForkHandlerName, blockNumber uint64) inte } // IsForkRegistered checks if fork is registered -func (fm *forkManager) IsForkRegistered(name ForkName) bool { +func (fm *forkManager) IsForkRegistered(name string) bool { fm.lock.Lock() defer fm.lock.Unlock() @@ -153,7 +153,7 @@ func (fm *forkManager) IsForkRegistered(name ForkName) bool { } // IsForkEnabled checks if fork is registered and enabled for specific block -func (fm *forkManager) IsForkEnabled(name ForkName, blockNumber uint64) bool { +func (fm *forkManager) IsForkEnabled(name string, blockNumber uint64) bool { fm.lock.Lock() defer fm.lock.Unlock() @@ -166,7 +166,7 @@ func (fm *forkManager) IsForkEnabled(name ForkName, blockNumber uint64) bool { } // GetForkBlock returns fork block if fork is registered and activated -func (fm *forkManager) GetForkBlock(name ForkName) (uint64, error) { +func (fm *forkManager) GetForkBlock(name string) (uint64, error) { fm.lock.Lock() defer fm.lock.Unlock() @@ -182,9 +182,9 @@ func (fm *forkManager) GetForkBlock(name ForkName) (uint64, error) { return fork.FromBlockNumber, nil } -func (fm *forkManager) addHandler(handlerName ForkHandlerName, blockNumber uint64, handler interface{}) { +func (fm *forkManager) addHandler(handlerName HandlerDesc, blockNumber uint64, handler interface{}) { if handlers, exists := fm.handlersMap[handlerName]; !exists { - fm.handlersMap[handlerName] = []ForkActiveHandler{ + fm.handlersMap[handlerName] = []Handler{ { FromBlockNumber: blockNumber, Handler: handler, @@ -195,9 +195,9 @@ func (fm *forkManager) addHandler(handlerName ForkHandlerName, blockNumber uint6 index := sort.Search(len(handlers), func(i int) bool { return handlers[i].FromBlockNumber >= blockNumber }) - handlers = append(handlers, ForkActiveHandler{}) + handlers = append(handlers, Handler{}) copy(handlers[index+1:], handlers[index:]) - handlers[index] = ForkActiveHandler{ + handlers[index] = Handler{ FromBlockNumber: blockNumber, Handler: handler, } @@ -205,7 +205,7 @@ func (fm *forkManager) addHandler(handlerName ForkHandlerName, blockNumber uint6 } } -func (fm *forkManager) removeHandler(handlerName ForkHandlerName, blockNumber uint64) { +func (fm *forkManager) removeHandler(handlerName HandlerDesc, blockNumber uint64) { handlers, exists := fm.handlersMap[handlerName] if !exists { return @@ -217,7 +217,7 @@ func (fm *forkManager) removeHandler(handlerName ForkHandlerName, blockNumber ui if index != -1 { copy(handlers[index:], handlers[index+1:]) - handlers[len(handlers)-1] = ForkActiveHandler{} + handlers[len(handlers)-1] = Handler{} fm.handlersMap[handlerName] = handlers[:len(handlers)-1] } } diff --git a/forkmanager/fork_manager_test.go b/forkmanager/fork_manager_test.go index 9e7f1237df..d3b91b1877 100644 --- a/forkmanager/fork_manager_test.go +++ b/forkmanager/fork_manager_test.go @@ -7,16 +7,16 @@ import ( ) const ( - HandlerA = ForkHandlerName("HA") - HandlerB = ForkHandlerName("HB") - HandlerC = ForkHandlerName("HC") - HandlerD = ForkHandlerName("HD") - - ForkA = ForkName("A") - ForkB = ForkName("B") - ForkC = ForkName("C") - ForkD = ForkName("D") - ForkE = ForkName("E") + HandlerA = HandlerDesc("HA") + HandlerB = HandlerDesc("HB") + HandlerC = HandlerDesc("HC") + HandlerD = HandlerDesc("HD") + + ForkA = "A" + ForkB = "B" + ForkC = "C" + ForkD = "D" + ForkE = "E" ) func TestForkManager(t *testing.T) { @@ -131,7 +131,7 @@ func TestForkManager(t *testing.T) { t.Run("get handler", func(t *testing.T) { t.Parallel() - execute := func(name ForkHandlerName, block uint64) string { + execute := func(name HandlerDesc, block uint64) string { //nolint:forcetypeassert return forkManager.GetHandler(name, block).(func() string)() } @@ -162,8 +162,8 @@ func TestForkManager_Deactivate(t *testing.T) { t.Parallel() forkManager := &forkManager{ - forkMap: map[ForkName]*Fork{}, - handlersMap: map[ForkHandlerName][]ForkActiveHandler{}, + forkMap: map[string]*Fork{}, + handlersMap: map[HandlerDesc][]Handler{}, } forkManager.RegisterFork(ForkA) diff --git a/server/server.go b/server/server.go index b0aef318cd..62bdbe5407 100644 --- a/server/server.go +++ b/server/server.go @@ -16,6 +16,7 @@ import ( "github.com/0xPolygon/polygon-edge/blockchain/storage/leveldb" "github.com/0xPolygon/polygon-edge/blockchain/storage/memory" consensusPolyBFT "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/forkmanager" "github.com/0xPolygon/polygon-edge/archive" "github.com/0xPolygon/polygon-edge/blockchain" @@ -276,10 +277,8 @@ func NewServer(config *Config) (*Server, error) { return nil, err } - if factory, exists := forkManagerFactory[ConsensusType(engineName)]; exists { - if err := factory(config.Chain.Params.Forks); err != nil { - return nil, err - } + if err := forkManagerInit(engineName, config.Chain.Params.Forks); err != nil { + return nil, err } // compute the genesis root state @@ -411,6 +410,42 @@ func NewServer(config *Config) (*Server, error) { return m, nil } +func forkManagerInit(engineName string, forks *chain.Forks) error { + if err := chain.CheckMissingFork(forks); err != nil { + return err + } + + factory, exists := forkManagerFactory[ConsensusType(engineName)] + if !exists { + return nil + } + + fm := forkmanager.GetInstance() + + // Register forks + for name := range *forks { + fm.RegisterFork(name) + } + + // Register handlers here + if err := factory(forks); err != nil { + return err + } + + // Activate forks + for name, blockNumber := range *forks { + if blockNumber == nil { + continue + } + + if err := fm.ActivateFork(name, (uint64)(*blockNumber)); err != nil { + return err + } + } + + return nil +} + func unaryInterceptor( ctx context.Context, req interface{}, From ef1feb3b164a30dbd0e4d9759af7bdf5bcb765e2 Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Wed, 31 May 2023 11:23:35 +0200 Subject: [PATCH 12/16] fix small issue already existed in code --- server/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/server.go b/server/server.go index 62bdbe5407..cb09e9a71c 100644 --- a/server/server.go +++ b/server/server.go @@ -287,10 +287,10 @@ func NewServer(config *Config) (*Server, error) { // Use the london signer with eip-155 as a fallback one var signer crypto.TxSigner = crypto.NewLondonSigner( uint64(m.config.Chain.Params.ChainID), - chain.AllForksEnabled.At(0).Homestead, + config.Chain.Params.Forks.IsActive(chain.Homestead, 0), crypto.NewEIP155Signer( uint64(m.config.Chain.Params.ChainID), - chain.AllForksEnabled.At(0).Homestead, + config.Chain.Params.Forks.IsActive(chain.Homestead, 0), ), ) From e92c8e10185e7131cf16395c7a21854dbb74f81e Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Wed, 31 May 2023 13:05:25 +0200 Subject: [PATCH 13/16] move ForkManagerInit to forkmanager. it will be needed from other parts of the code - e2e tests --- chain/params.go | 13 ------------- forkmanager/fork.go | 42 ++++++++++++++++++++++++++++++++++++++++++ server/server.go | 40 +++------------------------------------- 3 files changed, 45 insertions(+), 50 deletions(-) diff --git a/chain/params.go b/chain/params.go index 4ed158f3b2..fc16f5842a 100644 --- a/chain/params.go +++ b/chain/params.go @@ -2,7 +2,6 @@ package chain import ( "errors" - "fmt" "math/big" "sort" @@ -159,15 +158,3 @@ var AllForksEnabled = &Forks{ Istanbul: NewFork(0), London: NewFork(0), } - -// CheckMissingFork checks if there is a fork received as a genesis parameter that is not supported -// by the current edge version. -func CheckMissingFork(forks *Forks) error { - for name := range *forks { - if _, found := (*AllForksEnabled)[name]; !found { - return fmt.Errorf("fork is not available: %s", name) - } - } - - return nil -} diff --git a/forkmanager/fork.go b/forkmanager/fork.go index 9b6b717c4b..6f2e4bb572 100644 --- a/forkmanager/fork.go +++ b/forkmanager/fork.go @@ -1,5 +1,11 @@ package forkmanager +import ( + "fmt" + + "github.com/0xPolygon/polygon-edge/chain" +) + // HandlerDesc gives description for the handler // eq: "extra", "proposer_calculator", etc type HandlerDesc string @@ -23,3 +29,39 @@ type Handler struct { // instance of some structure, function etc Handler interface{} } + +func ForkManagerInit(factory func(*chain.Forks) error, forks *chain.Forks) error { + if factory == nil { + return nil + } + + fm := GetInstance() + + // Register forks + for name := range *forks { + // check if fork is not supported by current edge version + if _, found := (*chain.AllForksEnabled)[name]; !found { + return fmt.Errorf("fork is not available: %s", name) + } + + fm.RegisterFork(name) + } + + // Register handlers and additional forks here + if err := factory(forks); err != nil { + return err + } + + // Activate forks + for name, blockNumber := range *forks { + if blockNumber == nil { + continue + } + + if err := fm.ActivateFork(name, (uint64)(*blockNumber)); err != nil { + return err + } + } + + return nil +} diff --git a/server/server.go b/server/server.go index cb09e9a71c..f511e500e7 100644 --- a/server/server.go +++ b/server/server.go @@ -277,7 +277,9 @@ func NewServer(config *Config) (*Server, error) { return nil, err } - if err := forkManagerInit(engineName, config.Chain.Params.Forks); err != nil { + if err := forkmanager.ForkManagerInit( + forkManagerFactory[ConsensusType(engineName)], + config.Chain.Params.Forks); err != nil { return nil, err } @@ -410,42 +412,6 @@ func NewServer(config *Config) (*Server, error) { return m, nil } -func forkManagerInit(engineName string, forks *chain.Forks) error { - if err := chain.CheckMissingFork(forks); err != nil { - return err - } - - factory, exists := forkManagerFactory[ConsensusType(engineName)] - if !exists { - return nil - } - - fm := forkmanager.GetInstance() - - // Register forks - for name := range *forks { - fm.RegisterFork(name) - } - - // Register handlers here - if err := factory(forks); err != nil { - return err - } - - // Activate forks - for name, blockNumber := range *forks { - if blockNumber == nil { - continue - } - - if err := fm.ActivateFork(name, (uint64)(*blockNumber)); err != nil { - return err - } - } - - return nil -} - func unaryInterceptor( ctx context.Context, req interface{}, From ca8e9d8fc1349b183010a50e26484fb2ccc3e326 Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Wed, 31 May 2023 16:06:41 +0200 Subject: [PATCH 14/16] initial fork --- forkmanager/fork.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/forkmanager/fork.go b/forkmanager/fork.go index 6f2e4bb572..c77a540f26 100644 --- a/forkmanager/fork.go +++ b/forkmanager/fork.go @@ -6,6 +6,8 @@ import ( "github.com/0xPolygon/polygon-edge/chain" ) +const InitialFork = "initialfork" + // HandlerDesc gives description for the handler // eq: "extra", "proposer_calculator", etc type HandlerDesc string @@ -37,6 +39,9 @@ func ForkManagerInit(factory func(*chain.Forks) error, forks *chain.Forks) error fm := GetInstance() + // register initial fork + fm.RegisterFork(InitialFork) + // Register forks for name := range *forks { // check if fork is not supported by current edge version @@ -52,6 +57,11 @@ func ForkManagerInit(factory func(*chain.Forks) error, forks *chain.Forks) error return err } + // Activate initial fork + if err := fm.ActivateFork(InitialFork, uint64(0)); err != nil { + return err + } + // Activate forks for name, blockNumber := range *forks { if blockNumber == nil { From 9a0563916c59d66316c17843b581680424f9dc76 Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Thu, 1 Jun 2023 10:50:25 +0200 Subject: [PATCH 15/16] init fix --- command/genesis/polybft_params.go | 5 +++++ forkmanager/fork.go | 1 + forkmanager/fork_manager.go | 14 ++++++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/command/genesis/polybft_params.go b/command/genesis/polybft_params.go index 1abb645bee..261b5dd7c5 100644 --- a/command/genesis/polybft_params.go +++ b/command/genesis/polybft_params.go @@ -20,6 +20,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/forkmanager" "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/server" "github.com/0xPolygon/polygon-edge/types" @@ -71,6 +72,10 @@ var ( // generatePolyBftChainConfig creates and persists polybft chain configuration to the provided file path func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) error { + if err := forkmanager.ForkManagerInit(polybft.ForkManagerFactory, chain.AllForksEnabled); err != nil { + return err + } + // populate premine balance map premineBalances := make(map[types.Address]*premineInfo, len(p.premine)) diff --git a/forkmanager/fork.go b/forkmanager/fork.go index c77a540f26..0556ca6c7e 100644 --- a/forkmanager/fork.go +++ b/forkmanager/fork.go @@ -38,6 +38,7 @@ func ForkManagerInit(factory func(*chain.Forks) error, forks *chain.Forks) error } fm := GetInstance() + fm.Clear() // register initial fork fm.RegisterFork(InitialFork) diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go index 9c6122a8bf..653bd860d1 100644 --- a/forkmanager/fork_manager.go +++ b/forkmanager/fork_manager.go @@ -35,15 +35,21 @@ func GetInstance() *forkManager { defer forkManagerInstanceLock.Unlock() if forkManagerInstance == nil { - forkManagerInstance = &forkManager{ - forkMap: map[string]*Fork{}, - handlersMap: map[HandlerDesc][]Handler{}, - } + forkManagerInstance = &forkManager{} + forkManagerInstance.Clear() } return forkManagerInstance } +func (fm *forkManager) Clear() { + fm.lock.Lock() + defer fm.lock.Unlock() + + fm.forkMap = map[string]*Fork{} + fm.handlersMap = map[HandlerDesc][]Handler{} +} + // RegisterFork registers fork by its name func (fm *forkManager) RegisterFork(name string) { fm.lock.Lock() From de7988234c91e1dcfbc9f9431645b58b179294da Mon Sep 17 00:00:00 2001 From: Igor Crevar Date: Thu, 1 Jun 2023 12:11:31 +0200 Subject: [PATCH 16/16] remove *chain.Params from genesis struct --- chain/chain.go | 2 -- consensus/polybft/extra_test.go | 11 ----------- 2 files changed, 13 deletions(-) diff --git a/chain/chain.go b/chain/chain.go index 46044d9a10..64bed7f1f5 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -41,8 +41,6 @@ type Chain struct { // Genesis specifies the header fields, state of a genesis block type Genesis struct { - Config *Params `json:"config"` - Nonce [8]byte `json:"nonce"` Timestamp uint64 `json:"timestamp"` ExtraData []byte `json:"extraData,omitempty"` diff --git a/consensus/polybft/extra_test.go b/consensus/polybft/extra_test.go index cd31c22cd4..4f33798291 100644 --- a/consensus/polybft/extra_test.go +++ b/consensus/polybft/extra_test.go @@ -496,8 +496,6 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { const validatorsCount = 7 vals := validator.NewTestValidators(t, validatorsCount) - polyBftConfig := PolyBFTConfig{InitialValidatorSet: vals.GetParamValidators()} - delta := &validator.ValidatorSetDelta{ Added: make(validator.AccountSet, validatorsCount), Removed: bitmap.Bitmap{}, @@ -516,9 +514,6 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { extra := Extra{Validators: delta} genesis := &chain.Genesis{ - Config: &chain.Params{Engine: map[string]interface{}{ - ConsensusName: polyBftConfig, - }}, ExtraData: extra.MarshalRLPTo(nil), } @@ -531,13 +526,7 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { t.Run("Invalid Extra data", func(t *testing.T) { t.Parallel() - validators := validator.NewTestValidators(t, 5) - polyBftConfig := PolyBFTConfig{InitialValidatorSet: validators.GetParamValidators()} - genesis := &chain.Genesis{ - Config: &chain.Params{Engine: map[string]interface{}{ - ConsensusName: polyBftConfig, - }}, ExtraData: append(make([]byte, ExtraVanity), []byte{0x2, 0x3}...), }