github.com/iotexproject/iotex-core@v1.14.1-rc1/blockchain/genesis/genesis.go (about)

     1  // Copyright (c) 2024 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package genesis
     7  
     8  import (
     9  	"math"
    10  	"math/big"
    11  	"sort"
    12  	"sync"
    13  	"sync/atomic"
    14  	"time"
    15  
    16  	"github.com/ethereum/go-ethereum/common"
    17  	"github.com/pkg/errors"
    18  	"go.uber.org/config"
    19  	"go.uber.org/zap"
    20  	"google.golang.org/protobuf/proto"
    21  
    22  	"github.com/iotexproject/go-pkgs/hash"
    23  	"github.com/iotexproject/iotex-address/address"
    24  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    25  
    26  	"github.com/iotexproject/iotex-core/pkg/log"
    27  	"github.com/iotexproject/iotex-core/pkg/unit"
    28  	"github.com/iotexproject/iotex-core/test/identityset"
    29  )
    30  
    31  var (
    32  	// Default contains the default genesis config
    33  	Default = defaultConfig()
    34  
    35  	_genesisTs     int64
    36  	_loadGenesisTs sync.Once
    37  )
    38  
    39  func init() {
    40  	initTestDefaultConfig(&Default)
    41  }
    42  
    43  func defaultConfig() Genesis {
    44  	return Genesis{
    45  		Blockchain: Blockchain{
    46  			Timestamp:               1546329600,
    47  			BlockGasLimit:           20000000,
    48  			TsunamiBlockGasLimit:    50000000,
    49  			ActionGasLimit:          5000000,
    50  			BlockInterval:           10 * time.Second,
    51  			NumSubEpochs:            2,
    52  			DardanellesNumSubEpochs: 30,
    53  			NumDelegates:            24,
    54  			NumCandidateDelegates:   36,
    55  			TimeBasedRotation:       false,
    56  			PacificBlockHeight:      432001,
    57  			AleutianBlockHeight:     864001,
    58  			BeringBlockHeight:       1512001,
    59  			CookBlockHeight:         1641601,
    60  			DardanellesBlockHeight:  1816201,
    61  			DaytonaBlockHeight:      3238921,
    62  			EasterBlockHeight:       4478761,
    63  			FbkMigrationBlockHeight: 5157001,
    64  			FairbankBlockHeight:     5165641,
    65  			GreenlandBlockHeight:    6544441,
    66  			HawaiiBlockHeight:       11267641,
    67  			IcelandBlockHeight:      12289321,
    68  			JutlandBlockHeight:      13685401,
    69  			KamchatkaBlockHeight:    13816441,
    70  			LordHoweBlockHeight:     13979161,
    71  			MidwayBlockHeight:       16509241,
    72  			NewfoundlandBlockHeight: 17662681,
    73  			OkhotskBlockHeight:      21542761,
    74  			PalauBlockHeight:        22991401,
    75  			QuebecBlockHeight:       24838201,
    76  			RedseaBlockHeight:       26704441,
    77  			SumatraBlockHeight:      28516681,
    78  			TsunamiBlockHeight:      29275561,
    79  			ToBeEnabledBlockHeight:  math.MaxUint64,
    80  		},
    81  		Account: Account{
    82  			InitBalanceMap:          make(map[string]string),
    83  			ReplayDeployerWhitelist: []string{"0x3fab184622dc19b6109349b94811493bf2a45362"},
    84  		},
    85  		Poll: Poll{
    86  			PollMode:                         "nativeMix",
    87  			EnableGravityChainVoting:         true,
    88  			GravityChainCeilingHeight:        10199000,
    89  			ProbationEpochPeriod:             6,
    90  			ProbationIntensityRate:           90,
    91  			UnproductiveDelegateMaxCacheSize: 20,
    92  			SystemStakingContractAddress:     "io1drde9f483guaetl3w3w6n6y7yv80f8fael7qme", // https://iotexscout.io/tx/8b899515d180d631abe8596b091380b0f42117122415393fa459c74c2bc5b6af
    93  			SystemStakingContractHeight:      24486464,
    94  		},
    95  		Rewarding: Rewarding{
    96  			InitBalanceStr:                 unit.ConvertIotxToRau(200000000).String(),
    97  			BlockRewardStr:                 unit.ConvertIotxToRau(16).String(),
    98  			DardanellesBlockRewardStr:      unit.ConvertIotxToRau(8).String(),
    99  			EpochRewardStr:                 unit.ConvertIotxToRau(12500).String(),
   100  			AleutianEpochRewardStr:         unit.ConvertIotxToRau(18750).String(),
   101  			NumDelegatesForEpochReward:     100,
   102  			ExemptAddrStrsFromEpochReward:  []string{},
   103  			FoundationBonusStr:             unit.ConvertIotxToRau(80).String(),
   104  			NumDelegatesForFoundationBonus: 36,
   105  			FoundationBonusLastEpoch:       8760,
   106  			FoundationBonusP2StartEpoch:    9698,
   107  			FoundationBonusP2EndEpoch:      18458,
   108  		},
   109  		Staking: Staking{
   110  			VoteWeightCalConsts: VoteWeightCalConsts{
   111  				DurationLg: 1.2,
   112  				AutoStake:  1,
   113  				SelfStake:  1.06,
   114  			},
   115  			RegistrationConsts: RegistrationConsts{
   116  				Fee:          unit.ConvertIotxToRau(100).String(),
   117  				MinSelfStake: unit.ConvertIotxToRau(1200000).String(),
   118  			},
   119  			WithdrawWaitingPeriod:            3 * 24 * time.Hour,
   120  			MinStakeAmount:                   unit.ConvertIotxToRau(100).String(),
   121  			BootstrapCandidates:              []BootstrapCandidate{},
   122  			EndorsementWithdrawWaitingBlocks: 24 * 60 * 60 / 5,
   123  		},
   124  	}
   125  }
   126  
   127  // TestDefault is the default genesis config for testing
   128  func TestDefault() Genesis {
   129  	ge := defaultConfig()
   130  	initTestDefaultConfig(&ge)
   131  	return ge
   132  }
   133  
   134  func initTestDefaultConfig(cfg *Genesis) {
   135  	cfg.PacificBlockHeight = 0
   136  	for i := 0; i < identityset.Size(); i++ {
   137  		addr := identityset.Address(i).String()
   138  		value := unit.ConvertIotxToRau(100000000).String()
   139  		cfg.InitBalanceMap[addr] = value
   140  		if uint64(i) < cfg.NumDelegates {
   141  			cfg.Delegates = append(cfg.Delegates, Delegate{
   142  				OperatorAddrStr: addr,
   143  				RewardAddrStr:   addr,
   144  				VotesStr:        value,
   145  			})
   146  		}
   147  	}
   148  }
   149  
   150  type (
   151  	// Genesis is the root level of genesis config. Genesis config is the network-wide blockchain config. All the nodes
   152  	// participating into the same network should use EXACTLY SAME genesis config.
   153  	Genesis struct {
   154  		Blockchain `yaml:"blockchain"`
   155  		Account    `yaml:"account"`
   156  		Poll       `yaml:"poll"`
   157  		Rewarding  `yaml:"rewarding"`
   158  		Staking    `yaml:"staking"`
   159  	}
   160  	// Blockchain contains blockchain level configs
   161  	Blockchain struct {
   162  		// Timestamp is the timestamp of the genesis block
   163  		Timestamp int64
   164  		// BlockGasLimit is the total gas limit could be consumed in a block
   165  		BlockGasLimit uint64 `yaml:"blockGasLimit"`
   166  		// TsunamiBlockGasLimit is the block gas limit starting Tsunami height (raised to 50M by default)
   167  		TsunamiBlockGasLimit uint64 `yaml:"tsunamiBlockGasLimit"`
   168  		// ActionGasLimit is the per action gas limit cap
   169  		ActionGasLimit uint64 `yaml:"actionGasLimit"`
   170  		// BlockInterval is the interval between two blocks
   171  		BlockInterval time.Duration `yaml:"blockInterval"`
   172  		// NumSubEpochs is the number of sub epochs in one epoch of block production
   173  		NumSubEpochs uint64 `yaml:"numSubEpochs"`
   174  		// DardanellesNumSubEpochs is the number of sub epochs starts from dardanelles height in one epoch of block production
   175  		DardanellesNumSubEpochs uint64 `yaml:"dardanellesNumSubEpochs"`
   176  		// NumDelegates is the number of delegates that participate into one epoch of block production
   177  		NumDelegates uint64 `yaml:"numDelegates"`
   178  		// NumCandidateDelegates is the number of candidate delegates, who may be selected as a delegate via roll dpos
   179  		NumCandidateDelegates uint64 `yaml:"numCandidateDelegates"`
   180  		// TimeBasedRotation is the flag to enable rotating delegates' time slots on a block height
   181  		TimeBasedRotation bool `yaml:"timeBasedRotation"`
   182  		// PacificBlockHeight is the start height of using the logic of Pacific version
   183  		// TODO: PacificBlockHeight is not added into protobuf definition for backward compatibility
   184  		PacificBlockHeight uint64 `yaml:"pacificHeight"`
   185  		// AleutianBlockHeight is the start height of adding bloom filter of all events into block header
   186  		AleutianBlockHeight uint64 `yaml:"aleutianHeight"`
   187  		// BeringBlockHeight is the start height of evm upgrade
   188  		BeringBlockHeight uint64 `yaml:"beringHeight"`
   189  		// CookBlockHeight is the start height of native staking
   190  		CookBlockHeight uint64 `yaml:"cookHeight"`
   191  		// DardanellesBlockHeight is the start height of 5s block internal
   192  		DardanellesBlockHeight uint64 `yaml:"dardanellesHeight"`
   193  		// DaytonaBlockHeight is the height to fix low gas for read native staking contract
   194  		DaytonaBlockHeight uint64 `yaml:"daytonaBlockHeight"`
   195  		// EasterBlockHeight is the start height of probation for slashing
   196  		EasterBlockHeight uint64 `yaml:"easterHeight"`
   197  		// FbkMigrationBlockHeight is the start height for fairbank migration
   198  		FbkMigrationBlockHeight uint64 `yaml:"fbkMigrationHeight"`
   199  		// FairbankBlockHeight is the start height to switch to native staking V2
   200  		FairbankBlockHeight uint64 `yaml:"fairbankHeight"`
   201  		// GreenlandBlockHeight is the start height of storing latest 720 block meta and rewarding/staking bucket pool
   202  		GreenlandBlockHeight uint64 `yaml:"greenlandHeight"`
   203  		// HawaiiBlockHeight is the start height to
   204  		// 1. fix GetBlockHash in EVM
   205  		// 2. add revert message to log
   206  		// 3. fix change to same candidate in staking protocol
   207  		// 4. fix sorted map in StateDBAdapter
   208  		// 5. use pending nonce in EVM
   209  		HawaiiBlockHeight uint64 `yaml:"hawaiiHeight"`
   210  		// IcelandBlockHeight is the start height to support chainID opcode and EVM Istanbul
   211  		IcelandBlockHeight uint64 `yaml:"icelandHeight"`
   212  		// JutlandBlockHeight is the start height to
   213  		// 1. report more EVM error codes
   214  		// 2. enable the opCall fix
   215  		JutlandBlockHeight uint64 `yaml:"jutlandHeight"`
   216  		// KamchatkaBlockHeight is the start height to
   217  		// 1. fix EVM snapshot order
   218  		// 2. extend foundation bonus
   219  		KamchatkaBlockHeight uint64 `yaml:"kamchatkaHeight"`
   220  		// LordHoweBlockHeight is the start height to
   221  		// 1. recover the smart contracts affected by snapshot order
   222  		// 2. clear snapshots in Revert()
   223  		LordHoweBlockHeight uint64 `yaml:"lordHoweHeight"`
   224  		// MidwayBlockHeight is the start height to
   225  		// 1. allow correct and default ChainID
   226  		// 2. fix GetHashFunc in EVM
   227  		// 3. correct tx/log index for transaction receipt and EVM log
   228  		// 4. revert logs upon tx reversion in EVM
   229  		MidwayBlockHeight uint64 `yaml:"midwayHeight"`
   230  		// NewfoundlandBlockHeight is the start height to
   231  		// 1. use correct chainID
   232  		// 2. check legacy address
   233  		// 3. enable web3 staking transaction
   234  		NewfoundlandBlockHeight uint64 `yaml:"newfoundlandHeight"`
   235  		// OkhotskBlockHeight is the start height to
   236  		// 1. enable London EVM
   237  		// 2. create zero-nonce account
   238  		// 3. fix gas and nonce update
   239  		// 4. fix unproductive delegates in staking protocol
   240  		OkhotskBlockHeight uint64 `yaml:"okhotskHeight"`
   241  		// PalauBlockHeight is the the start height to
   242  		// 1. enable rewarding action via web3
   243  		// 2. broadcast node info into the p2p network
   244  		PalauBlockHeight uint64 `yaml:"palauHeight"`
   245  		// QuebecBlockHeight is the start height to
   246  		// 1. enforce using correct chainID only
   247  		// 2. enable IIP-13 liquidity staking
   248  		// 3. valiate system action layout
   249  		QuebecBlockHeight uint64 `yaml:"quebecHeight"`
   250  		// RedseaBlockHeight is the start height to
   251  		// 1. upgrade go-ethereum to Bellatrix release
   252  		// 2. correct weighted votes for contract staking bucket
   253  		RedseaBlockHeight uint64 `yaml:"redseaHeight"`
   254  		// SumatraBlockHeight is the start height to enable Shanghai EVM
   255  		SumatraBlockHeight uint64 `yaml:"sumatraHeight"`
   256  		// TsunamiBlockHeight is the start height to
   257  		// 1. enable delegate endorsement
   258  		// 2. generate transaction log for Suicide() call in EVM
   259  		// 3. raise block gas limit to 50M
   260  		TsunamiBlockHeight uint64 `yaml:"tsunamiHeight"`
   261  		// ToBeEnabledBlockHeight is a fake height that acts as a gating factor for WIP features
   262  		// upon next release, change IsToBeEnabled() to IsNextHeight() for features to be released
   263  		ToBeEnabledBlockHeight uint64 `yaml:"toBeEnabledHeight"`
   264  	}
   265  	// Account contains the configs for account protocol
   266  	Account struct {
   267  		// InitBalanceMap is the address and initial balance mapping before the first block.
   268  		InitBalanceMap map[string]string `yaml:"initBalances"`
   269  		// ReplayDeployerWhitelist is the whitelist address for unprotected (pre-EIP155) transaction
   270  		ReplayDeployerWhitelist []string `yaml:"replayDeployerWhitelist"`
   271  	}
   272  	// Poll contains the configs for poll protocol
   273  	Poll struct {
   274  		// PollMode is different based on chain type or poll input data source
   275  		PollMode string `yaml:"pollMode"`
   276  		// EnableGravityChainVoting is a flag whether read voting from gravity chain
   277  		EnableGravityChainVoting bool `yaml:"enableGravityChainVoting"`
   278  		// GravityChainStartHeight is the height in gravity chain where the init poll result stored
   279  		GravityChainStartHeight uint64 `yaml:"gravityChainStartHeight"`
   280  		// GravityChainCeilingHeight is the height in gravity chain where the poll is no longer needed
   281  		GravityChainCeilingHeight uint64 `yaml:"gravityChainCeilingHeight"`
   282  		// GravityChainHeightInterval the height interval on gravity chain to pull delegate information
   283  		GravityChainHeightInterval uint64 `yaml:"gravityChainHeightInterval"`
   284  		// RegisterContractAddress is the address of register contract
   285  		RegisterContractAddress string `yaml:"registerContractAddress"`
   286  		// StakingContractAddress is the address of staking contract
   287  		StakingContractAddress string `yaml:"stakingContractAddress"`
   288  		// NativeStakingContractAddress is the address of native staking contract
   289  		NativeStakingContractAddress string `yaml:"nativeStakingContractAddress"`
   290  		// NativeStakingContractCode is the code of native staking contract
   291  		NativeStakingContractCode string `yaml:"nativeStakingContractCode"`
   292  		// ConsortiumCommitteeCode is the code of consortiumCommittee contract
   293  		ConsortiumCommitteeContractCode string `yaml:"consortiumCommitteeContractCode"`
   294  		// VoteThreshold is the vote threshold amount in decimal string format
   295  		VoteThreshold string `yaml:"voteThreshold"`
   296  		// ScoreThreshold is the score threshold amount in decimal string format
   297  		ScoreThreshold string `yaml:"scoreThreshold"`
   298  		// SelfStakingThreshold is self-staking vote threshold amount in decimal string format
   299  		SelfStakingThreshold string `yaml:"selfStakingThreshold"`
   300  		// Delegates is a list of delegates with votes
   301  		Delegates []Delegate `yaml:"delegates"`
   302  		// ProbationEpochPeriod is a duration of probation after delegate's productivity is lower than threshold
   303  		ProbationEpochPeriod uint64 `yaml:"probationEpochPeriod"`
   304  		// ProbationIntensityRate is a intensity rate of probation range from [0, 100], where 100 is hard-probation
   305  		ProbationIntensityRate uint32 `yaml:"probationIntensityRate"`
   306  		// UnproductiveDelegateMaxCacheSize is a max cache size of upd which is stored into state DB (probationEpochPeriod <= UnproductiveDelegateMaxCacheSize)
   307  		UnproductiveDelegateMaxCacheSize uint64 `yaml:"unproductiveDelegateMaxCacheSize"`
   308  		// SystemStakingContractAddress is the address of system staking contract
   309  		SystemStakingContractAddress string `yaml:"systemStakingContractAddress"`
   310  		// SystemStakingContractHeight is the height of system staking contract
   311  		SystemStakingContractHeight uint64 `yaml:"systemStakingContractHeight"`
   312  		// SystemSGDContractAddress is the address of system sgd contract
   313  		SystemSGDContractAddress string `yaml:"systemSGDContractAddress"`
   314  		// SystemSGDContractHeight is the height of system sgd contract
   315  		SystemSGDContractHeight uint64 `yaml:"systemSGDContractHeight"`
   316  	}
   317  	// Delegate defines a delegate with address and votes
   318  	Delegate struct {
   319  		// OperatorAddrStr is the address who will operate the node
   320  		OperatorAddrStr string `yaml:"operatorAddr"`
   321  		// RewardAddrStr is the address who will get the reward when operator produces blocks
   322  		RewardAddrStr string `yaml:"rewardAddr"`
   323  		// VotesStr is the score for the operator to rank and weight for rewardee to split epoch reward
   324  		VotesStr string `yaml:"votes"`
   325  	}
   326  	// Rewarding contains the configs for rewarding protocol
   327  	Rewarding struct {
   328  		// InitBalanceStr is the initial balance of the rewarding protocol in decimal string format
   329  		InitBalanceStr string `yaml:"initBalance"`
   330  		// BlockReward is the block reward amount in decimal string format
   331  		BlockRewardStr string `yaml:"blockReward"`
   332  		// DardanellesBlockReward is the block reward amount starts from dardanelles height in decimal string format
   333  		DardanellesBlockRewardStr string `yaml:"dardanellesBlockReward"`
   334  		// EpochReward is the epoch reward amount in decimal string format
   335  		EpochRewardStr string `yaml:"epochReward"`
   336  		// AleutianEpochRewardStr is the epoch reward amount in decimal string format after aleutian fork
   337  		AleutianEpochRewardStr string `yaml:"aleutianEpochReward"`
   338  		// NumDelegatesForEpochReward is the number of top candidates that will share a epoch reward
   339  		NumDelegatesForEpochReward uint64 `yaml:"numDelegatesForEpochReward"`
   340  		// ExemptAddrStrsFromEpochReward is the list of addresses in encoded string format that exempt from epoch reward
   341  		ExemptAddrStrsFromEpochReward []string `yaml:"exemptAddrsFromEpochReward"`
   342  		// FoundationBonusStr is the bootstrap bonus in decimal string format
   343  		FoundationBonusStr string `yaml:"foundationBonus"`
   344  		// NumDelegatesForFoundationBonus is the number of top candidate that will get the bootstrap bonus
   345  		NumDelegatesForFoundationBonus uint64 `yaml:"numDelegatesForFoundationBonus"`
   346  		// FoundationBonusLastEpoch is the last epoch number that bootstrap bonus will be granted
   347  		FoundationBonusLastEpoch uint64 `yaml:"foundationBonusLastEpoch"`
   348  		// FoundationBonusP2StartEpoch is the start epoch number for part 2 foundation bonus
   349  		FoundationBonusP2StartEpoch uint64 `yaml:"foundationBonusP2StartEpoch"`
   350  		// FoundationBonusP2EndEpoch is the end epoch number for part 2 foundation bonus
   351  		FoundationBonusP2EndEpoch uint64 `yaml:"foundationBonusP2EndEpoch"`
   352  		// ProductivityThreshold is the percentage number that a delegate's productivity needs to reach not to get probation
   353  		ProductivityThreshold uint64 `yaml:"productivityThreshold"`
   354  	}
   355  	// Staking contains the configs for staking protocol
   356  	Staking struct {
   357  		VoteWeightCalConsts              VoteWeightCalConsts  `yaml:"voteWeightCalConsts"`
   358  		RegistrationConsts               RegistrationConsts   `yaml:"registrationConsts"`
   359  		WithdrawWaitingPeriod            time.Duration        `yaml:"withdrawWaitingPeriod"`
   360  		MinStakeAmount                   string               `yaml:"minStakeAmount"`
   361  		BootstrapCandidates              []BootstrapCandidate `yaml:"bootstrapCandidates"`
   362  		EndorsementWithdrawWaitingBlocks uint64               `yaml:"endorsementWithdrawWaitingBlocks"`
   363  	}
   364  
   365  	// VoteWeightCalConsts contains the configs for calculating vote weight
   366  	VoteWeightCalConsts struct {
   367  		DurationLg float64 `yaml:"durationLg"`
   368  		AutoStake  float64 `yaml:"autoStake"`
   369  		SelfStake  float64 `yaml:"selfStake"`
   370  	}
   371  
   372  	// RegistrationConsts contains the configs for candidate registration
   373  	RegistrationConsts struct {
   374  		Fee          string `yaml:"fee"`
   375  		MinSelfStake string `yaml:"minSelfStake"`
   376  	}
   377  
   378  	// BootstrapCandidate is the candidate data need to be provided to bootstrap candidate.
   379  	BootstrapCandidate struct {
   380  		OwnerAddress      string `yaml:"ownerAddress"`
   381  		OperatorAddress   string `yaml:"operatorAddress"`
   382  		RewardAddress     string `yaml:"rewardAddress"`
   383  		Name              string `yaml:"name"`
   384  		SelfStakingTokens string `yaml:"selfStakingTokens"`
   385  	}
   386  )
   387  
   388  // New constructs a genesis config. It loads the default values, and could be overwritten by values defined in the yaml
   389  // config files
   390  func New(genesisPath string) (Genesis, error) {
   391  	def := defaultConfig()
   392  
   393  	opts := make([]config.YAMLOption, 0)
   394  	opts = append(opts, config.Static(def))
   395  	if genesisPath != "" {
   396  		opts = append(opts, config.File(genesisPath))
   397  	}
   398  	yaml, err := config.NewYAML(opts...)
   399  	if err != nil {
   400  		return Genesis{}, errors.Wrap(err, "error when constructing a genesis in yaml")
   401  	}
   402  
   403  	var genesis Genesis
   404  	if err := yaml.Get(config.Root).Populate(&genesis); err != nil {
   405  		return Genesis{}, errors.Wrap(err, "failed to unmarshal yaml genesis to struct")
   406  	}
   407  	return genesis, nil
   408  }
   409  
   410  // SetGenesisTimestamp sets the genesis timestamp
   411  func SetGenesisTimestamp(ts int64) {
   412  	_loadGenesisTs.Do(func() {
   413  		_genesisTs = ts
   414  	})
   415  }
   416  
   417  // Timestamp returns the genesis timestamp
   418  func Timestamp() int64 {
   419  	return atomic.LoadInt64(&_genesisTs)
   420  }
   421  
   422  // Hash is the hash of genesis config
   423  func (g *Genesis) Hash() hash.Hash256 {
   424  	gbProto := iotextypes.GenesisBlockchain{
   425  		Timestamp:             g.Timestamp,
   426  		BlockGasLimit:         g.BlockGasLimit,
   427  		ActionGasLimit:        g.ActionGasLimit,
   428  		BlockInterval:         g.BlockInterval.Nanoseconds(),
   429  		NumSubEpochs:          g.NumSubEpochs,
   430  		NumDelegates:          g.NumDelegates,
   431  		NumCandidateDelegates: g.NumCandidateDelegates,
   432  		TimeBasedRotation:     g.TimeBasedRotation,
   433  	}
   434  
   435  	initBalanceAddrs := make([]string, 0)
   436  	for initBalanceAddr := range g.InitBalanceMap {
   437  		initBalanceAddrs = append(initBalanceAddrs, initBalanceAddr)
   438  	}
   439  	sort.Strings(initBalanceAddrs)
   440  	initBalances := make([]string, 0)
   441  	for _, initBalanceAddr := range initBalanceAddrs {
   442  		initBalances = append(initBalances, g.InitBalanceMap[initBalanceAddr])
   443  	}
   444  	aProto := iotextypes.GenesisAccount{
   445  		InitBalanceAddrs: initBalanceAddrs,
   446  		InitBalances:     initBalances,
   447  	}
   448  
   449  	dProtos := make([]*iotextypes.GenesisDelegate, 0)
   450  	for _, d := range g.Delegates {
   451  		dProto := iotextypes.GenesisDelegate{
   452  			OperatorAddr: d.OperatorAddrStr,
   453  			RewardAddr:   d.RewardAddrStr,
   454  			Votes:        d.VotesStr,
   455  		}
   456  		dProtos = append(dProtos, &dProto)
   457  	}
   458  	pProto := iotextypes.GenesisPoll{
   459  		EnableGravityChainVoting: g.EnableGravityChainVoting,
   460  		GravityChainStartHeight:  g.GravityChainStartHeight,
   461  		RegisterContractAddress:  g.RegisterContractAddress,
   462  		StakingContractAddress:   g.StakingContractAddress,
   463  		VoteThreshold:            g.VoteThreshold,
   464  		ScoreThreshold:           g.ScoreThreshold,
   465  		SelfStakingThreshold:     g.SelfStakingThreshold,
   466  		Delegates:                dProtos,
   467  	}
   468  
   469  	rProto := iotextypes.GenesisRewarding{
   470  		InitBalance:                    g.InitBalanceStr,
   471  		BlockReward:                    g.BlockRewardStr,
   472  		EpochReward:                    g.EpochRewardStr,
   473  		NumDelegatesForEpochReward:     g.NumDelegatesForEpochReward,
   474  		FoundationBonus:                g.FoundationBonusStr,
   475  		NumDelegatesForFoundationBonus: g.NumDelegatesForFoundationBonus,
   476  		FoundationBonusLastEpoch:       g.FoundationBonusLastEpoch,
   477  		ProductivityThreshold:          g.ProductivityThreshold,
   478  	}
   479  
   480  	gProto := iotextypes.Genesis{
   481  		Blockchain: &gbProto,
   482  		Account:    &aProto,
   483  		Poll:       &pProto,
   484  		Rewarding:  &rProto,
   485  	}
   486  	b, err := proto.Marshal(&gProto)
   487  	if err != nil {
   488  		log.L().Panic("Error when marshaling genesis proto", zap.Error(err))
   489  	}
   490  	return hash.Hash256b(b)
   491  }
   492  
   493  func (g *Blockchain) isPost(targetHeight, height uint64) bool {
   494  	return height >= targetHeight
   495  }
   496  
   497  // IsPacific checks whether height is equal to or larger than pacific height
   498  func (g *Blockchain) IsPacific(height uint64) bool {
   499  	return g.isPost(g.PacificBlockHeight, height)
   500  }
   501  
   502  // IsAleutian checks whether height is equal to or larger than aleutian height
   503  func (g *Blockchain) IsAleutian(height uint64) bool {
   504  	return g.isPost(g.AleutianBlockHeight, height)
   505  }
   506  
   507  // IsBering checks whether height is equal to or larger than bering height
   508  func (g *Blockchain) IsBering(height uint64) bool {
   509  	return g.isPost(g.BeringBlockHeight, height)
   510  }
   511  
   512  // IsCook checks whether height is equal to or larger than cook height
   513  func (g *Blockchain) IsCook(height uint64) bool {
   514  	return g.isPost(g.CookBlockHeight, height)
   515  }
   516  
   517  // IsDardanelles checks whether height is equal to or larger than dardanelles height
   518  func (g *Blockchain) IsDardanelles(height uint64) bool {
   519  	return g.isPost(g.DardanellesBlockHeight, height)
   520  }
   521  
   522  // IsDaytona checks whether height is equal to or larger than daytona height
   523  func (g *Blockchain) IsDaytona(height uint64) bool {
   524  	return g.isPost(g.DaytonaBlockHeight, height)
   525  }
   526  
   527  // IsEaster checks whether height is equal to or larger than easter height
   528  func (g *Blockchain) IsEaster(height uint64) bool {
   529  	return g.isPost(g.EasterBlockHeight, height)
   530  }
   531  
   532  // IsFairbank checks whether height is equal to or larger than fairbank height
   533  func (g *Blockchain) IsFairbank(height uint64) bool {
   534  	return g.isPost(g.FairbankBlockHeight, height)
   535  }
   536  
   537  // IsFbkMigration checks whether height is equal to or larger than fbk migration height
   538  func (g *Blockchain) IsFbkMigration(height uint64) bool {
   539  	return g.isPost(g.FbkMigrationBlockHeight, height)
   540  }
   541  
   542  // IsGreenland checks whether height is equal to or larger than greenland height
   543  func (g *Blockchain) IsGreenland(height uint64) bool {
   544  	return g.isPost(g.GreenlandBlockHeight, height)
   545  }
   546  
   547  // IsHawaii checks whether height is equal to or larger than hawaii height
   548  func (g *Blockchain) IsHawaii(height uint64) bool {
   549  	return g.isPost(g.HawaiiBlockHeight, height)
   550  }
   551  
   552  // IsIceland checks whether height is equal to or larger than iceland height
   553  func (g *Blockchain) IsIceland(height uint64) bool {
   554  	return g.isPost(g.IcelandBlockHeight, height)
   555  }
   556  
   557  // IsJutland checks whether height is equal to or larger than jutland height
   558  func (g *Blockchain) IsJutland(height uint64) bool {
   559  	return g.isPost(g.JutlandBlockHeight, height)
   560  }
   561  
   562  // IsKamchatka checks whether height is equal to or larger than kamchatka height
   563  func (g *Blockchain) IsKamchatka(height uint64) bool {
   564  	return g.isPost(g.KamchatkaBlockHeight, height)
   565  }
   566  
   567  // IsLordHowe checks whether height is equal to or larger than lordHowe height
   568  func (g *Blockchain) IsLordHowe(height uint64) bool {
   569  	return g.isPost(g.LordHoweBlockHeight, height)
   570  }
   571  
   572  // IsMidway checks whether height is equal to or larger than midway height
   573  func (g *Blockchain) IsMidway(height uint64) bool {
   574  	return g.isPost(g.MidwayBlockHeight, height)
   575  }
   576  
   577  // IsNewfoundland checks whether height is equal to or larger than newfoundland height
   578  func (g *Blockchain) IsNewfoundland(height uint64) bool {
   579  	return g.isPost(g.NewfoundlandBlockHeight, height)
   580  }
   581  
   582  // IsOkhotsk checks whether height is equal to or larger than okhotsk height
   583  func (g *Blockchain) IsOkhotsk(height uint64) bool {
   584  	return g.isPost(g.OkhotskBlockHeight, height)
   585  }
   586  
   587  // IsPalau checks whether height is equal to or larger than palau height
   588  func (g *Blockchain) IsPalau(height uint64) bool {
   589  	return g.isPost(g.PalauBlockHeight, height)
   590  }
   591  
   592  // IsQuebec checks whether height is equal to or larger than quebec height
   593  func (g *Blockchain) IsQuebec(height uint64) bool {
   594  	return g.isPost(g.QuebecBlockHeight, height)
   595  }
   596  
   597  // IsRedsea checks whether height is equal to or larger than redsea height
   598  func (g *Blockchain) IsRedsea(height uint64) bool {
   599  	return g.isPost(g.RedseaBlockHeight, height)
   600  }
   601  
   602  // IsSumatra checks whether height is equal to or larger than sumatra height
   603  func (g *Blockchain) IsSumatra(height uint64) bool {
   604  	return g.isPost(g.SumatraBlockHeight, height)
   605  }
   606  
   607  // IsTsunami checks whether height is equal to or larger than tsunami height
   608  func (g *Blockchain) IsTsunami(height uint64) bool {
   609  	return g.isPost(g.TsunamiBlockHeight, height)
   610  }
   611  
   612  // IsToBeEnabled checks whether height is equal to or larger than toBeEnabled height
   613  func (g *Blockchain) IsToBeEnabled(height uint64) bool {
   614  	return g.isPost(g.ToBeEnabledBlockHeight, height)
   615  }
   616  
   617  func (g *Blockchain) BlockGasLimitByHeight(height uint64) uint64 {
   618  	if g.isPost(g.TsunamiBlockHeight, height) {
   619  		// block gas limit raised to 50M after Tsunami block height
   620  		return g.TsunamiBlockGasLimit
   621  	}
   622  	return g.BlockGasLimit
   623  }
   624  
   625  // IsDeployerWhitelisted returns if the replay deployer is whitelisted
   626  func (a *Account) IsDeployerWhitelisted(deployer address.Address) bool {
   627  	for _, v := range a.ReplayDeployerWhitelist {
   628  		if v[:3] == "io1" {
   629  			if addr, err := address.FromString(v); err == nil {
   630  				if address.Equal(deployer, addr) {
   631  					return true
   632  				}
   633  			}
   634  		} else if common.IsHexAddress(v) {
   635  			if addr, err := address.FromHex(v); err == nil {
   636  				if address.Equal(deployer, addr) {
   637  					return true
   638  				}
   639  			}
   640  		}
   641  	}
   642  	return false
   643  }
   644  
   645  // InitBalances returns the address that have initial balances and the corresponding amounts. The i-th amount is the
   646  // i-th address' balance.
   647  func (a *Account) InitBalances() ([]address.Address, []*big.Int) {
   648  	// Make the list always be ordered
   649  	addrStrs := make([]string, 0)
   650  	for addrStr := range a.InitBalanceMap {
   651  		addrStrs = append(addrStrs, addrStr)
   652  	}
   653  	sort.Strings(addrStrs)
   654  	addrs := make([]address.Address, 0)
   655  	amounts := make([]*big.Int, 0)
   656  	for _, addrStr := range addrStrs {
   657  		addr, err := address.FromString(addrStr)
   658  		if err != nil {
   659  			log.L().Panic("Error when decoding the account protocol init balance address from string.", zap.Error(err))
   660  		}
   661  		addrs = append(addrs, addr)
   662  		amount, ok := new(big.Int).SetString(a.InitBalanceMap[addrStr], 10)
   663  		if !ok {
   664  			log.S().Panicf("Error when casting init balance string %s into big int", a.InitBalanceMap[addrStr])
   665  		}
   666  		amounts = append(amounts, amount)
   667  	}
   668  	return addrs, amounts
   669  }
   670  
   671  // OperatorAddr is the address of operator
   672  func (d *Delegate) OperatorAddr() address.Address {
   673  	addr, err := address.FromString(d.OperatorAddrStr)
   674  	if err != nil {
   675  		log.L().Panic("Error when decoding the poll protocol operator address from string.", zap.Error(err))
   676  	}
   677  	return addr
   678  }
   679  
   680  // RewardAddr is the address of rewardee, which is allowed to be nil
   681  func (d *Delegate) RewardAddr() address.Address {
   682  	if d.RewardAddrStr == "" {
   683  		return nil
   684  	}
   685  	addr, err := address.FromString(d.RewardAddrStr)
   686  	if err != nil {
   687  		log.L().Panic("Error when decoding the poll protocol rewardee address from string.", zap.Error(err))
   688  	}
   689  	return addr
   690  }
   691  
   692  // Votes returns the votes
   693  func (d *Delegate) Votes() *big.Int {
   694  	val, ok := new(big.Int).SetString(d.VotesStr, 10)
   695  	if !ok {
   696  		log.S().Panicf("Error when casting votes string %s into big int", d.VotesStr)
   697  	}
   698  	return val
   699  }
   700  
   701  // InitBalance returns the init balance of the rewarding fund
   702  func (r *Rewarding) InitBalance() *big.Int {
   703  	val, ok := new(big.Int).SetString(r.InitBalanceStr, 10)
   704  	if !ok {
   705  		log.S().Panicf("Error when casting init balance string %s into big int", r.InitBalanceStr)
   706  	}
   707  	return val
   708  }
   709  
   710  // BlockReward returns the block reward amount
   711  func (r *Rewarding) BlockReward() *big.Int {
   712  	val, ok := new(big.Int).SetString(r.BlockRewardStr, 10)
   713  	if !ok {
   714  		log.S().Panicf("Error when casting block reward string %s into big int", r.BlockRewardStr)
   715  	}
   716  	return val
   717  }
   718  
   719  // EpochReward returns the epoch reward amount
   720  func (r *Rewarding) EpochReward() *big.Int {
   721  	val, ok := new(big.Int).SetString(r.EpochRewardStr, 10)
   722  	if !ok {
   723  		log.S().Panicf("Error when casting epoch reward string %s into big int", r.EpochRewardStr)
   724  	}
   725  	return val
   726  }
   727  
   728  // AleutianEpochReward returns the epoch reward amount after Aleutian fork
   729  func (r *Rewarding) AleutianEpochReward() *big.Int {
   730  	val, ok := new(big.Int).SetString(r.AleutianEpochRewardStr, 10)
   731  	if !ok {
   732  		log.S().Panicf("Error when casting epoch reward string %s into big int", r.EpochRewardStr)
   733  	}
   734  	return val
   735  }
   736  
   737  // DardanellesBlockReward returns the block reward amount after dardanelles fork
   738  func (r *Rewarding) DardanellesBlockReward() *big.Int {
   739  	val, ok := new(big.Int).SetString(r.DardanellesBlockRewardStr, 10)
   740  	if !ok {
   741  		log.S().Panicf("Error when casting block reward string %s into big int", r.EpochRewardStr)
   742  	}
   743  	return val
   744  }
   745  
   746  // ExemptAddrsFromEpochReward returns the list of addresses that exempt from epoch reward
   747  func (r *Rewarding) ExemptAddrsFromEpochReward() []address.Address {
   748  	addrs := make([]address.Address, 0)
   749  	for _, addrStr := range r.ExemptAddrStrsFromEpochReward {
   750  		addr, err := address.FromString(addrStr)
   751  		if err != nil {
   752  			log.L().Panic("Error when decoding the rewarding protocol exempt address from string.", zap.Error(err))
   753  		}
   754  		addrs = append(addrs, addr)
   755  	}
   756  	return addrs
   757  }
   758  
   759  // FoundationBonus returns the bootstrap bonus amount rewarded per epoch
   760  func (r *Rewarding) FoundationBonus() *big.Int {
   761  	val, ok := new(big.Int).SetString(r.FoundationBonusStr, 10)
   762  	if !ok {
   763  		log.S().Panicf("Error when casting bootstrap bonus string %s into big int", r.EpochRewardStr)
   764  	}
   765  	return val
   766  }