core: allow to create hard-fork

This commit is contained in:
Anna Shaleva 2022-05-06 15:19:17 +03:00
parent d1588115a2
commit e70bf7d12e
6 changed files with 86 additions and 1 deletions

31
pkg/config/hardfork.go Normal file
View file

@ -0,0 +1,31 @@
package config
//go:generate stringer -type=Hardfork -linecomment
// Hardfork represents the application hard-fork identifier.
type Hardfork byte
const (
// HF2712FixSyscallFees represents hard-fork introduced in #2469 (ported from
// https://github.com/neo-project/neo/pull/2712) changing the prices of
// System.Contract.CreateStandardAccount and
// System.Contract.CreateMultisigAccount interops.
HF2712FixSyscallFees Hardfork = 1 << iota // HF_2712_FixSyscallFees
)
// hardforks holds a map of Hardfork string representation to its type.
var hardforks map[string]Hardfork
func init() {
hardforks = make(map[string]Hardfork)
for _, hf := range []Hardfork{HF2712FixSyscallFees} {
hardforks[hf.String()] = hf
}
}
// IsHardforkValid denotes whether the provided string represents a valid
// Hardfork name.
func IsHardforkValid(s string) bool {
_, ok := hardforks[s]
return ok
}

View file

@ -0,0 +1,24 @@
// Code generated by "stringer -type Hardfork -linecomment ./pkg/config/hardfork.go"; DO NOT EDIT.
package config
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[HF2712FixSyscallFees-1]
}
const _Hardfork_name = "HF_2712_FixSyscallFees"
var _Hardfork_index = [...]uint8{0, 22}
func (i Hardfork) String() string {
i -= 1
if i >= Hardfork(len(_Hardfork_index)-1) {
return "Hardfork(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _Hardfork_name[_Hardfork_index[i]:_Hardfork_index[i+1]]
}

View file

@ -23,6 +23,9 @@ type (
Magic netmode.Magic `yaml:"Magic"`
MemPoolSize int `yaml:"MemPoolSize"`
// Hardforks is a map of hardfork names that enables version-specific application
// logic dependent on the specified height.
Hardforks map[string]uint32 `yaml:"Hardforks"`
// InitialGASSupply is the amount of GAS generated in the genesis block.
InitialGASSupply fixedn.Fixed8 `yaml:"InitialGASSupply"`
// P2PNotaryRequestPayloadPoolSize specifies the memory pool size for P2PNotaryRequestPayloads.
@ -94,6 +97,11 @@ func (p *ProtocolConfiguration) Validate() error {
return fmt.Errorf("NativeActivations configuration section contains unexpected native contract name: %s", name)
}
}
for name := range p.Hardforks {
if !IsHardforkValid(name) {
return fmt.Errorf("Hardforks configuration section contains unexpected hardfork: %s", name)
}
}
if p.ValidatorsCount != 0 && len(p.ValidatorsHistory) != 0 {
return errors.New("configuration should either have ValidatorsCount or ValidatorsHistory, not both")
}

View file

@ -100,6 +100,12 @@ func TestProtocolConfigurationValidation(t *testing.T) {
ValidatorsHistory: map[uint32]int{0: 4, 100: 4},
}
require.Error(t, p.Validate())
p = &ProtocolConfiguration{
Hardforks: map[string]uint32{
"HF_Unknown": 123, // Unknown hard-fork.
},
}
require.Error(t, p.Validate())
p = &ProtocolConfiguration{
StandbyCommittee: []string{
"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2",

View file

@ -259,6 +259,10 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
cfg.NativeUpdateHistories = map[string][]uint32{}
log.Info("NativeActivations are not set, using default values")
}
if cfg.Hardforks == nil {
cfg.Hardforks = map[string]uint32{}
log.Info("Hardforks are not set, using default value")
}
bc := &Blockchain{
config: cfg,
dao: dao.NewSimple(s, cfg.StateRootInHeader, cfg.P2PSigExtensions),

View file

@ -48,6 +48,7 @@ type Context struct {
Chain Ledger
Container hash.Hashable
Network uint32
Hardforks map[string]uint32
Natives []Contract
Trigger trigger.Type
Block *block.Block
@ -71,9 +72,11 @@ func NewContext(trigger trigger.Type, bc Ledger, d *dao.Simple, baseExecFee, bas
getContract func(*dao.Simple, util.Uint160) (*state.Contract, error), natives []Contract,
block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context {
dao := d.GetPrivate()
cfg := bc.GetConfig()
return &Context{
Chain: bc,
Network: uint32(bc.GetConfig().Magic),
Network: uint32(cfg.Magic),
Hardforks: cfg.Hardforks,
Natives: natives,
Trigger: trigger,
Block: block,
@ -368,3 +371,12 @@ func (ic *Context) GetBlock(hash util.Uint256) (*block.Block, error) {
}
return block, nil
}
// IsHardforkEnabled tells whether specified hard-fork enabled at the current context height.
func (ic *Context) IsHardforkEnabled(hf config.Hardfork) bool {
height, ok := ic.Hardforks[hf.String()]
if ok {
return ic.BlockHeight() >= height
}
return len(ic.Hardforks) == 0 // Enable each hard-fork by default.
}