gitlab.com/flarenetwork/coreth@v0.1.1/params/config.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2016 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package params
    28  
    29  import (
    30  	"errors"
    31  	"fmt"
    32  	"math/big"
    33  
    34  	"github.com/ethereum/go-ethereum/common"
    35  )
    36  
    37  // Avalanche ChainIDs
    38  var (
    39  	// AvalancheMainnetChainID ...
    40  	AvalancheMainnetChainID = big.NewInt(43114)
    41  	// AvalancheFujiChainID ...
    42  	AvalancheFujiChainID = big.NewInt(43113)
    43  	// AvalancheLocalChainID ...
    44  	AvalancheLocalChainID = big.NewInt(43112)
    45  
    46  	errNonGenesisForkByHeight = errors.New("coreth only supports forking by height at the genesis block")
    47  )
    48  
    49  var (
    50  	// AvalancheMainnetChainConfig is the configuration for Avalanche Main Network
    51  	AvalancheMainnetChainConfig = &ChainConfig{
    52  		ChainID:                     AvalancheMainnetChainID,
    53  		HomesteadBlock:              big.NewInt(0),
    54  		DAOForkBlock:                big.NewInt(0),
    55  		DAOForkSupport:              true,
    56  		EIP150Block:                 big.NewInt(0),
    57  		EIP150Hash:                  common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
    58  		EIP155Block:                 big.NewInt(0),
    59  		EIP158Block:                 big.NewInt(0),
    60  		ByzantiumBlock:              big.NewInt(0),
    61  		ConstantinopleBlock:         big.NewInt(0),
    62  		PetersburgBlock:             big.NewInt(0),
    63  		IstanbulBlock:               big.NewInt(0),
    64  		MuirGlacierBlock:            big.NewInt(0),
    65  		ApricotPhase1BlockTimestamp: big.NewInt(1617199200), // 10am EST 3/31/2021
    66  		ApricotPhase2BlockTimestamp: big.NewInt(1620644400), // 10am EST 5/10/2021
    67  		ApricotPhase3BlockTimestamp: big.NewInt(1629813600), // 10am EST 8/24/2021
    68  	}
    69  
    70  	// AvalancheFujiChainConfig is the configuration for the Fuji Test Network
    71  	AvalancheFujiChainConfig = &ChainConfig{
    72  		ChainID:                     AvalancheFujiChainID,
    73  		HomesteadBlock:              big.NewInt(0),
    74  		DAOForkBlock:                big.NewInt(0),
    75  		DAOForkSupport:              true,
    76  		EIP150Block:                 big.NewInt(0),
    77  		EIP150Hash:                  common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
    78  		EIP155Block:                 big.NewInt(0),
    79  		EIP158Block:                 big.NewInt(0),
    80  		ByzantiumBlock:              big.NewInt(0),
    81  		ConstantinopleBlock:         big.NewInt(0),
    82  		PetersburgBlock:             big.NewInt(0),
    83  		IstanbulBlock:               big.NewInt(0),
    84  		MuirGlacierBlock:            big.NewInt(0),
    85  		ApricotPhase1BlockTimestamp: big.NewInt(1616767200), // 10am EST 3/26/2021
    86  		ApricotPhase2BlockTimestamp: big.NewInt(1620223200), // 10am EST 5/5/2021
    87  		ApricotPhase3BlockTimestamp: big.NewInt(1629140400), // 3pm EST 8/16/2021
    88  	}
    89  
    90  	// AvalancheLocalChainConfig is the configuration for the Avalanche Local Network
    91  	AvalancheLocalChainConfig = &ChainConfig{
    92  		ChainID:                     AvalancheLocalChainID,
    93  		HomesteadBlock:              big.NewInt(0),
    94  		DAOForkBlock:                big.NewInt(0),
    95  		DAOForkSupport:              true,
    96  		EIP150Block:                 big.NewInt(0),
    97  		EIP150Hash:                  common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
    98  		EIP155Block:                 big.NewInt(0),
    99  		EIP158Block:                 big.NewInt(0),
   100  		ByzantiumBlock:              big.NewInt(0),
   101  		ConstantinopleBlock:         big.NewInt(0),
   102  		PetersburgBlock:             big.NewInt(0),
   103  		IstanbulBlock:               big.NewInt(0),
   104  		MuirGlacierBlock:            big.NewInt(0),
   105  		ApricotPhase1BlockTimestamp: big.NewInt(0),
   106  		ApricotPhase2BlockTimestamp: big.NewInt(0),
   107  		ApricotPhase3BlockTimestamp: big.NewInt(0),
   108  	}
   109  
   110  	TestChainConfig            = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0)}
   111  	AllAvalancheUpgradesConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0)}
   112  	TestRules                  = TestChainConfig.AvalancheRules(new(big.Int), new(big.Int))
   113  )
   114  
   115  // ChainConfig is the core config which determines the blockchain settings.
   116  //
   117  // ChainConfig is stored in the database on a per block basis. This means
   118  // that any network, identified by its genesis block, can have its own
   119  // set of configuration options.
   120  type ChainConfig struct {
   121  	ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
   122  
   123  	HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead)
   124  
   125  	DAOForkBlock   *big.Int `json:"daoForkBlock,omitempty"`   // TheDAO hard-fork switch block (nil = no fork)
   126  	DAOForkSupport bool     `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
   127  
   128  	// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
   129  	EIP150Block *big.Int    `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork)
   130  	EIP150Hash  common.Hash `json:"eip150Hash,omitempty"`  // EIP150 HF hash (needed for header only clients as only gas pricing changed)
   131  
   132  	EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
   133  	EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block
   134  
   135  	ByzantiumBlock      *big.Int `json:"byzantiumBlock,omitempty"`      // Byzantium switch block (nil = no fork, 0 = already on byzantium)
   136  	ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
   137  	PetersburgBlock     *big.Int `json:"petersburgBlock,omitempty"`     // Petersburg switch block (nil = same as Constantinople)
   138  	IstanbulBlock       *big.Int `json:"istanbulBlock,omitempty"`       // Istanbul switch block (nil = no fork, 0 = already on istanbul)
   139  	MuirGlacierBlock    *big.Int `json:"muirGlacierBlock,omitempty"`    // Eip-2384 (bomb delay) switch block (nil = no fork, 0 = already activated)
   140  
   141  	// Avalanche Network Upgrades
   142  	ApricotPhase1BlockTimestamp *big.Int `json:"apricotPhase1BlockTimestamp,omitempty"` // Apricot Phase 1 Block Timestamp (nil = no fork, 0 = already activated)
   143  	// Apricot Phase 2 Block Timestamp (nil = no fork, 0 = already activated)
   144  	// Apricot Phase 2 includes a modified version of the Berlin Hard Fork from Ethereum
   145  	ApricotPhase2BlockTimestamp *big.Int `json:"apricotPhase2BlockTimestamp,omitempty"`
   146  	// Apricot Phase 3 introduces dynamic fees and batching of atomic transactions (nil = no fork, 0 = already activated)
   147  	ApricotPhase3BlockTimestamp *big.Int `json:"apricotPhase3BlockTimestamp,omitempty"`
   148  }
   149  
   150  // String implements the fmt.Stringer interface.
   151  func (c *ChainConfig) String() string {
   152  	return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Apricot Phase 1: %v, Apricot Phase 2: %v, Apricot Phase 3: %v, Engine: Dummy Consensus Engine}",
   153  		c.ChainID,
   154  		c.HomesteadBlock,
   155  		c.DAOForkBlock,
   156  		c.DAOForkSupport,
   157  		c.EIP150Block,
   158  		c.EIP155Block,
   159  		c.EIP158Block,
   160  		c.ByzantiumBlock,
   161  		c.ConstantinopleBlock,
   162  		c.PetersburgBlock,
   163  		c.IstanbulBlock,
   164  		c.MuirGlacierBlock,
   165  		c.ApricotPhase1BlockTimestamp,
   166  		c.ApricotPhase2BlockTimestamp,
   167  		c.ApricotPhase3BlockTimestamp,
   168  	)
   169  }
   170  
   171  // IsHomestead returns whether num is either equal to the homestead block or greater.
   172  func (c *ChainConfig) IsHomestead(num *big.Int) bool {
   173  	return isForked(c.HomesteadBlock, num)
   174  }
   175  
   176  // IsDAOFork returns whether num is either equal to the DAO fork block or greater.
   177  func (c *ChainConfig) IsDAOFork(num *big.Int) bool {
   178  	return isForked(c.DAOForkBlock, num)
   179  }
   180  
   181  // IsEIP150 returns whether num is either equal to the EIP150 fork block or greater.
   182  func (c *ChainConfig) IsEIP150(num *big.Int) bool {
   183  	return isForked(c.EIP150Block, num)
   184  }
   185  
   186  // IsEIP155 returns whether num is either equal to the EIP155 fork block or greater.
   187  func (c *ChainConfig) IsEIP155(num *big.Int) bool {
   188  	return isForked(c.EIP155Block, num)
   189  }
   190  
   191  // IsEIP158 returns whether num is either equal to the EIP158 fork block or greater.
   192  func (c *ChainConfig) IsEIP158(num *big.Int) bool {
   193  	return isForked(c.EIP158Block, num)
   194  }
   195  
   196  // IsByzantium returns whether num is either equal to the Byzantium fork block or greater.
   197  func (c *ChainConfig) IsByzantium(num *big.Int) bool {
   198  	return isForked(c.ByzantiumBlock, num)
   199  }
   200  
   201  // IsConstantinople returns whether num is either equal to the Constantinople fork block or greater.
   202  func (c *ChainConfig) IsConstantinople(num *big.Int) bool {
   203  	return isForked(c.ConstantinopleBlock, num)
   204  }
   205  
   206  // IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater.
   207  func (c *ChainConfig) IsMuirGlacier(num *big.Int) bool {
   208  	return isForked(c.MuirGlacierBlock, num)
   209  }
   210  
   211  // IsPetersburg returns whether num is either
   212  // - equal to or greater than the PetersburgBlock fork block,
   213  // - OR is nil, and Constantinople is active
   214  func (c *ChainConfig) IsPetersburg(num *big.Int) bool {
   215  	return isForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isForked(c.ConstantinopleBlock, num)
   216  }
   217  
   218  // IsIstanbul returns whether num is either equal to the Istanbul fork block or greater.
   219  func (c *ChainConfig) IsIstanbul(num *big.Int) bool {
   220  	return isForked(c.IstanbulBlock, num)
   221  }
   222  
   223  // Avalanche Upgrades:
   224  
   225  // IsApricotPhase1 returns whether [blockTimestamp] represents a block
   226  // with a timestamp after the Apricot Phase 1 upgrade time.
   227  func (c *ChainConfig) IsApricotPhase1(blockTimestamp *big.Int) bool {
   228  	return isForked(c.ApricotPhase1BlockTimestamp, blockTimestamp)
   229  }
   230  
   231  // IsApricotPhase2 returns whether [blockTimestamp] represents a block
   232  // with a timestamp after the Apricot Phase 2 upgrade time.
   233  func (c *ChainConfig) IsApricotPhase2(blockTimestamp *big.Int) bool {
   234  	return isForked(c.ApricotPhase2BlockTimestamp, blockTimestamp)
   235  }
   236  
   237  // IsApricotPhase3 returns whether [blockTimestamp] represents a block
   238  // with a timestamp after the Apricot Phase 3 upgrade time.
   239  func (c *ChainConfig) IsApricotPhase3(blockTimestamp *big.Int) bool {
   240  	return isForked(c.ApricotPhase3BlockTimestamp, blockTimestamp)
   241  }
   242  
   243  // CheckCompatible checks whether scheduled fork transitions have been imported
   244  // with a mismatching chain configuration.
   245  func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError {
   246  	bhead := new(big.Int).SetUint64(height)
   247  
   248  	// Iterate checkCompatible to find the lowest conflict.
   249  	var lasterr *ConfigCompatError
   250  	for {
   251  		err := c.checkCompatible(newcfg, bhead)
   252  		if err == nil || (lasterr != nil && err.RewindTo == lasterr.RewindTo) {
   253  			break
   254  		}
   255  		lasterr = err
   256  		bhead.SetUint64(err.RewindTo)
   257  	}
   258  	return lasterr
   259  }
   260  
   261  // CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough
   262  // to guarantee that forks can be implemented in a different order than on official networks
   263  func (c *ChainConfig) CheckConfigForkOrder() error {
   264  	type fork struct {
   265  		name     string
   266  		block    *big.Int
   267  		optional bool // if true, the fork may be nil and next fork is still allowed
   268  	}
   269  	var lastFork fork
   270  	for _, cur := range []fork{
   271  		{name: "homesteadBlock", block: c.HomesteadBlock},
   272  		{name: "daoForkBlock", block: c.DAOForkBlock, optional: true},
   273  		{name: "eip150Block", block: c.EIP150Block},
   274  		{name: "eip155Block", block: c.EIP155Block},
   275  		{name: "eip158Block", block: c.EIP158Block},
   276  		{name: "byzantiumBlock", block: c.ByzantiumBlock},
   277  		{name: "constantinopleBlock", block: c.ConstantinopleBlock},
   278  		{name: "petersburgBlock", block: c.PetersburgBlock},
   279  		{name: "istanbulBlock", block: c.IstanbulBlock},
   280  		{name: "muirGlacierBlock", block: c.MuirGlacierBlock, optional: true},
   281  	} {
   282  		if cur.block != nil && common.Big0.Cmp(cur.block) != 0 {
   283  			return errNonGenesisForkByHeight
   284  		}
   285  		if lastFork.name != "" {
   286  			// Next one must be higher number
   287  			if lastFork.block == nil && cur.block != nil {
   288  				return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at %v",
   289  					lastFork.name, cur.name, cur.block)
   290  			}
   291  			if lastFork.block != nil && cur.block != nil {
   292  				if lastFork.block.Cmp(cur.block) > 0 {
   293  					return fmt.Errorf("unsupported fork ordering: %v enabled at %v, but %v enabled at %v",
   294  						lastFork.name, lastFork.block, cur.name, cur.block)
   295  				}
   296  			}
   297  		}
   298  		// If it was optional and not set, then ignore it
   299  		if !cur.optional || cur.block != nil {
   300  			lastFork = cur
   301  		}
   302  	}
   303  
   304  	// Note: ApricotPhase1 and ApricotPhase2 override the rules set by block number
   305  	// hard forks. In Avalanche, hard forks must take place via block timestamps instead
   306  	// of block numbers since blocks are produced asynchronously. Therefore, we do not
   307  	// check that the block timestamps for Apricot Phase1 and Phase2 in the same way as for
   308  	// the block number forks since it would not be a meaningful comparison.
   309  	// Instead, we check only that Apricot Phases are enabled in order.
   310  	lastFork = fork{}
   311  	for _, cur := range []fork{
   312  		{name: "apricotPhase1BlockTimestamp", block: c.ApricotPhase1BlockTimestamp},
   313  		{name: "apricotPhase2BlockTimestamp", block: c.ApricotPhase2BlockTimestamp},
   314  		{name: "apricotPhase3BlockTimestamp", block: c.ApricotPhase3BlockTimestamp},
   315  	} {
   316  		if lastFork.name != "" {
   317  			// Next one must be higher number
   318  			if lastFork.block == nil && cur.block != nil {
   319  				return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at %v",
   320  					lastFork.name, cur.name, cur.block)
   321  			}
   322  			if lastFork.block != nil && cur.block != nil {
   323  				if lastFork.block.Cmp(cur.block) > 0 {
   324  					return fmt.Errorf("unsupported fork ordering: %v enabled at %v, but %v enabled at %v",
   325  						lastFork.name, lastFork.block, cur.name, cur.block)
   326  				}
   327  			}
   328  		}
   329  		// If it was optional and not set, then ignore it
   330  		if !cur.optional || cur.block != nil {
   331  			lastFork = cur
   332  		}
   333  	}
   334  	// TODO(aaronbuchwald) check that avalanche block timestamps are at least possible with the other rule set changes
   335  	// additional change: require that block number hard forks are either 0 or nil since they should not
   336  	// be enabled at a specific block number.
   337  
   338  	return nil
   339  }
   340  
   341  func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *ConfigCompatError {
   342  	if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) {
   343  		return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock)
   344  	}
   345  	if isForkIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, head) {
   346  		return newCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock)
   347  	}
   348  	if c.IsDAOFork(head) && c.DAOForkSupport != newcfg.DAOForkSupport {
   349  		return newCompatError("DAO fork support flag", c.DAOForkBlock, newcfg.DAOForkBlock)
   350  	}
   351  	if isForkIncompatible(c.EIP150Block, newcfg.EIP150Block, head) {
   352  		return newCompatError("EIP150 fork block", c.EIP150Block, newcfg.EIP150Block)
   353  	}
   354  	if isForkIncompatible(c.EIP155Block, newcfg.EIP155Block, head) {
   355  		return newCompatError("EIP155 fork block", c.EIP155Block, newcfg.EIP155Block)
   356  	}
   357  	if isForkIncompatible(c.EIP158Block, newcfg.EIP158Block, head) {
   358  		return newCompatError("EIP158 fork block", c.EIP158Block, newcfg.EIP158Block)
   359  	}
   360  	if c.IsEIP158(head) && !configNumEqual(c.ChainID, newcfg.ChainID) {
   361  		return newCompatError("EIP158 chain ID", c.EIP158Block, newcfg.EIP158Block)
   362  	}
   363  	if isForkIncompatible(c.ByzantiumBlock, newcfg.ByzantiumBlock, head) {
   364  		return newCompatError("Byzantium fork block", c.ByzantiumBlock, newcfg.ByzantiumBlock)
   365  	}
   366  	if isForkIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, head) {
   367  		return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock)
   368  	}
   369  	if isForkIncompatible(c.PetersburgBlock, newcfg.PetersburgBlock, head) {
   370  		// the only case where we allow Petersburg to be set in the past is if it is equal to Constantinople
   371  		// mainly to satisfy fork ordering requirements which state that Petersburg fork be set if Constantinople fork is set
   372  		if isForkIncompatible(c.ConstantinopleBlock, newcfg.PetersburgBlock, head) {
   373  			return newCompatError("Petersburg fork block", c.PetersburgBlock, newcfg.PetersburgBlock)
   374  		}
   375  	}
   376  	if isForkIncompatible(c.IstanbulBlock, newcfg.IstanbulBlock, head) {
   377  		return newCompatError("Istanbul fork block", c.IstanbulBlock, newcfg.IstanbulBlock)
   378  	}
   379  	if isForkIncompatible(c.MuirGlacierBlock, newcfg.MuirGlacierBlock, head) {
   380  		return newCompatError("Muir Glacier fork block", c.MuirGlacierBlock, newcfg.MuirGlacierBlock)
   381  	}
   382  	// TODO(aaronbuchwald) ensure that Avalanche Blocktimestamps are not modified
   383  	return nil
   384  }
   385  
   386  // isForkIncompatible returns true if a fork scheduled at s1 cannot be rescheduled to
   387  // block s2 because head is already past the fork.
   388  func isForkIncompatible(s1, s2, head *big.Int) bool {
   389  	return (isForked(s1, head) || isForked(s2, head)) && !configNumEqual(s1, s2)
   390  }
   391  
   392  // isForked returns whether a fork scheduled at block s is active at the given head block.
   393  func isForked(s, head *big.Int) bool {
   394  	if s == nil || head == nil {
   395  		return false
   396  	}
   397  	return s.Cmp(head) <= 0
   398  }
   399  
   400  func configNumEqual(x, y *big.Int) bool {
   401  	if x == nil {
   402  		return y == nil
   403  	}
   404  	if y == nil {
   405  		return x == nil
   406  	}
   407  	return x.Cmp(y) == 0
   408  }
   409  
   410  // ConfigCompatError is raised if the locally-stored blockchain is initialised with a
   411  // ChainConfig that would alter the past.
   412  type ConfigCompatError struct {
   413  	What string
   414  	// block numbers of the stored and new configurations
   415  	StoredConfig, NewConfig *big.Int
   416  	// the block number to which the local chain must be rewound to correct the error
   417  	RewindTo uint64
   418  }
   419  
   420  func newCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError {
   421  	var rew *big.Int
   422  	switch {
   423  	case storedblock == nil:
   424  		rew = newblock
   425  	case newblock == nil || storedblock.Cmp(newblock) < 0:
   426  		rew = storedblock
   427  	default:
   428  		rew = newblock
   429  	}
   430  	err := &ConfigCompatError{what, storedblock, newblock, 0}
   431  	if rew != nil && rew.Sign() > 0 {
   432  		err.RewindTo = rew.Uint64() - 1
   433  	}
   434  	return err
   435  }
   436  
   437  func (err *ConfigCompatError) Error() string {
   438  	return fmt.Sprintf("mismatching %s in database (have %d, want %d, rewindto %d)", err.What, err.StoredConfig, err.NewConfig, err.RewindTo)
   439  }
   440  
   441  // Rules wraps ChainConfig and is merely syntactic sugar or can be used for functions
   442  // that do not have or require information about the block.
   443  //
   444  // Rules is a one time interface meaning that it shouldn't be used in between transition
   445  // phases.
   446  type Rules struct {
   447  	ChainID                                                 *big.Int
   448  	IsHomestead, IsEIP150, IsEIP155, IsEIP158               bool
   449  	IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
   450  
   451  	// Rules for Avalanche releases
   452  	IsApricotPhase1 bool
   453  	IsApricotPhase2 bool
   454  	IsApricotPhase3 bool
   455  }
   456  
   457  // Rules ensures c's ChainID is not nil.
   458  func (c *ChainConfig) rules(num *big.Int) Rules {
   459  	chainID := c.ChainID
   460  	if chainID == nil {
   461  		chainID = new(big.Int)
   462  	}
   463  	return Rules{
   464  		ChainID:          new(big.Int).Set(chainID),
   465  		IsHomestead:      c.IsHomestead(num),
   466  		IsEIP150:         c.IsEIP150(num),
   467  		IsEIP155:         c.IsEIP155(num),
   468  		IsEIP158:         c.IsEIP158(num),
   469  		IsByzantium:      c.IsByzantium(num),
   470  		IsConstantinople: c.IsConstantinople(num),
   471  		IsPetersburg:     c.IsPetersburg(num),
   472  		IsIstanbul:       c.IsIstanbul(num),
   473  	}
   474  }
   475  
   476  // AvalancheRules returns the Avalanche modified rules to support Avalanche
   477  // network upgrades
   478  func (c *ChainConfig) AvalancheRules(blockNum, blockTimestamp *big.Int) Rules {
   479  	rules := c.rules(blockNum)
   480  
   481  	rules.IsApricotPhase1 = c.IsApricotPhase1(blockTimestamp)
   482  	rules.IsApricotPhase2 = c.IsApricotPhase2(blockTimestamp)
   483  	rules.IsApricotPhase3 = c.IsApricotPhase3(blockTimestamp)
   484  	return rules
   485  }