github.com/theQRL/go-zond@v0.2.1/params/config.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package params
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  
    23  	"github.com/theQRL/go-zond/common"
    24  )
    25  
    26  // TODO(now.youtrack.cloud/issue/TGZ-16)
    27  // Genesis hashes to enforce below configs on.
    28  var (
    29  	MainnetGenesisHash = common.HexToHash("0xb3de630542cf9acf842e24f428c7c21b7824b38a7718a632e424b58ba0f562c6")
    30  	BetaNetGenesisHash = common.HexToHash("0xab0c2cf4bd9bc1d3bad049a5ae94725177bf2b95f45115415e9941f218c661b1")
    31  	TestnetGenesisHash = common.HexToHash("0x05db5e4aaf4ca0c301ed6912280e20e0f20de36ba3ccc893dc777050216494ea")
    32  )
    33  
    34  // NOTE(rgeraldes24): unused atm
    35  // func newUint64(val uint64) *uint64 { return &val }
    36  
    37  var (
    38  	// MainnetChainConfig is the chain parameters to run a node on the main network.
    39  	MainnetChainConfig = &ChainConfig{
    40  		ChainID: big.NewInt(1),
    41  	}
    42  	// TestnetChainConfig contains the chain parameters to run a node on the BetaNet test network.
    43  	TestnetChainConfig = &ChainConfig{
    44  		ChainID: big.NewInt(32382),
    45  	}
    46  	// BetaNetChainConfig contains the chain parameters to run a node on the BetaNet test network.
    47  	BetaNetChainConfig = &ChainConfig{
    48  		ChainID: big.NewInt(32382),
    49  	}
    50  
    51  	// AllBeaconProtocolChanges contains every protocol change (EIPs) introduced
    52  	// and accepted by the Zond core developers into the Beacon consensus.
    53  	AllBeaconProtocolChanges = &ChainConfig{
    54  		ChainID: big.NewInt(1337),
    55  	}
    56  
    57  	AllDevChainProtocolChanges = &ChainConfig{
    58  		ChainID:   big.NewInt(1337),
    59  		IsDevMode: true,
    60  	}
    61  
    62  	// TestChainConfig contains every protocol change (EIPs) introduced
    63  	// and accepted by the Zond core developers for testing proposes.
    64  	TestChainConfig = &ChainConfig{
    65  		ChainID: big.NewInt(1),
    66  	}
    67  
    68  	// NonActivatedConfig defines the chain configuration without activating
    69  	// any protocol change (EIPs).
    70  	NonActivatedConfig = &ChainConfig{
    71  		ChainID: big.NewInt(1),
    72  	}
    73  	TestRules = TestChainConfig.Rules(new(big.Int), 0)
    74  )
    75  
    76  // NetworkNames are user friendly names to use in the chain spec banner.
    77  var NetworkNames = map[string]string{
    78  	MainnetChainConfig.ChainID.String(): "mainnet",
    79  }
    80  
    81  // ChainConfig is the core config which determines the blockchain settings.
    82  //
    83  // ChainConfig is stored in the database on a per block basis. This means
    84  // that any network, identified by its genesis block, can have its own
    85  // set of configuration options.
    86  type ChainConfig struct {
    87  	ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
    88  
    89  	IsDevMode bool `json:"isDev,omitempty"`
    90  }
    91  
    92  // Description returns a human-readable description of ChainConfig.
    93  func (c *ChainConfig) Description() string {
    94  	var banner string
    95  
    96  	// Create some basic network config output
    97  	network := NetworkNames[c.ChainID.String()]
    98  	if network == "" {
    99  		network = "unknown"
   100  	}
   101  	banner += fmt.Sprintf("Chain ID:  %v (%s)\n", c.ChainID, network)
   102  	banner += "Consensus: Beacon (proof-of-stake)\n"
   103  	banner += "\n"
   104  
   105  	return banner
   106  }
   107  
   108  // CheckCompatible checks whether scheduled fork transitions have been imported
   109  // with a mismatching chain configuration.
   110  func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError {
   111  	var (
   112  		bhead = new(big.Int).SetUint64(height)
   113  		// btime = time
   114  	)
   115  	// Iterate checkCompatible to find the lowest conflict.
   116  	var lasterr *ConfigCompatError
   117  	for {
   118  		err := c.checkCompatible(newcfg /*, bhead, btime*/)
   119  		if err == nil || (lasterr != nil && err.RewindToBlock == lasterr.RewindToBlock && err.RewindToTime == lasterr.RewindToTime) {
   120  			break
   121  		}
   122  		lasterr = err
   123  
   124  		if err.RewindToTime > 0 {
   125  			// btime = err.RewindToTime
   126  		} else {
   127  			bhead.SetUint64(err.RewindToBlock)
   128  		}
   129  	}
   130  	return lasterr
   131  }
   132  
   133  // CheckConfigForkOrder checks that we don't "skip" any forks, gzond isn't pluggable enough
   134  // to guarantee that forks can be implemented in a different order than on official networks
   135  func (c *ChainConfig) CheckConfigForkOrder() error {
   136  	type fork struct {
   137  		name      string
   138  		block     *big.Int // forks up to - and including the merge - were defined with block numbers
   139  		timestamp *uint64  // forks after the merge are scheduled using timestamps
   140  		optional  bool     // if true, the fork may be nil and next fork is still allowed
   141  	}
   142  	var lastFork fork
   143  	for _, cur := range []fork{} {
   144  		if lastFork.name != "" {
   145  			switch {
   146  			// Non-optional forks must all be present in the chain config up to the last defined fork
   147  			case lastFork.block == nil && lastFork.timestamp == nil && (cur.block != nil || cur.timestamp != nil):
   148  				if cur.block != nil {
   149  					return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at block %v",
   150  						lastFork.name, cur.name, cur.block)
   151  				} else {
   152  					return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at timestamp %v",
   153  						lastFork.name, cur.name, cur.timestamp)
   154  				}
   155  
   156  			// Fork (whether defined by block or timestamp) must follow the fork definition sequence
   157  			case (lastFork.block != nil && cur.block != nil) || (lastFork.timestamp != nil && cur.timestamp != nil):
   158  				if lastFork.block != nil && lastFork.block.Cmp(cur.block) > 0 {
   159  					return fmt.Errorf("unsupported fork ordering: %v enabled at block %v, but %v enabled at block %v",
   160  						lastFork.name, lastFork.block, cur.name, cur.block)
   161  				} else if lastFork.timestamp != nil && *lastFork.timestamp > *cur.timestamp {
   162  					return fmt.Errorf("unsupported fork ordering: %v enabled at timestamp %v, but %v enabled at timestamp %v",
   163  						lastFork.name, lastFork.timestamp, cur.name, cur.timestamp)
   164  				}
   165  
   166  				// Timestamp based forks can follow block based ones, but not the other way around
   167  				if lastFork.timestamp != nil && cur.block != nil {
   168  					return fmt.Errorf("unsupported fork ordering: %v used timestamp ordering, but %v reverted to block ordering",
   169  						lastFork.name, cur.name)
   170  				}
   171  			}
   172  		}
   173  		// If it was optional and not set, then ignore it
   174  		if !cur.optional || (cur.block != nil || cur.timestamp != nil) {
   175  			lastFork = cur
   176  		}
   177  	}
   178  	return nil
   179  }
   180  
   181  func (c *ChainConfig) checkCompatible(newcfg *ChainConfig /*, headNumber *big.Int, headTimestamp uint64*/) *ConfigCompatError {
   182  	if !configBlockEqual(c.ChainID, newcfg.ChainID) {
   183  		return newBlockCompatError("chain ID", c.ChainID, newcfg.ChainID)
   184  	}
   185  
   186  	return nil
   187  }
   188  
   189  // BaseFeeChangeDenominator bounds the amount the base fee can change between blocks.
   190  func (c *ChainConfig) BaseFeeChangeDenominator() uint64 {
   191  	return DefaultBaseFeeChangeDenominator
   192  }
   193  
   194  // ElasticityMultiplier bounds the maximum gas limit an EIP-1559 block may have.
   195  func (c *ChainConfig) ElasticityMultiplier() uint64 {
   196  	return DefaultElasticityMultiplier
   197  }
   198  
   199  // isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be
   200  // rescheduled to block s2 because head is already past the fork.
   201  func isForkBlockIncompatible(s1, s2, head *big.Int) bool {
   202  	return (isBlockForked(s1, head) || isBlockForked(s2, head)) && !configBlockEqual(s1, s2)
   203  }
   204  
   205  // isBlockForked returns whether a fork scheduled at block s is active at the
   206  // given head block. Whilst this method is the same as isTimestampForked, they
   207  // are explicitly separate for clearer reading.
   208  func isBlockForked(s, head *big.Int) bool {
   209  	if s == nil || head == nil {
   210  		return false
   211  	}
   212  	return s.Cmp(head) <= 0
   213  }
   214  
   215  func configBlockEqual(x, y *big.Int) bool {
   216  	if x == nil {
   217  		return y == nil
   218  	}
   219  	if y == nil {
   220  		return x == nil
   221  	}
   222  	return x.Cmp(y) == 0
   223  }
   224  
   225  // isForkTimestampIncompatible returns true if a fork scheduled at timestamp s1
   226  // cannot be rescheduled to timestamp s2 because head is already past the fork.
   227  func isForkTimestampIncompatible(s1, s2 *uint64, head uint64) bool {
   228  	return (isTimestampForked(s1, head) || isTimestampForked(s2, head)) && !configTimestampEqual(s1, s2)
   229  }
   230  
   231  // isTimestampForked returns whether a fork scheduled at timestamp s is active
   232  // at the given head timestamp. Whilst this method is the same as isBlockForked,
   233  // they are explicitly separate for clearer reading.
   234  func isTimestampForked(s *uint64, head uint64) bool {
   235  	if s == nil {
   236  		return false
   237  	}
   238  	return *s <= head
   239  }
   240  
   241  func configTimestampEqual(x, y *uint64) bool {
   242  	if x == nil {
   243  		return y == nil
   244  	}
   245  	if y == nil {
   246  		return x == nil
   247  	}
   248  	return *x == *y
   249  }
   250  
   251  // ConfigCompatError is raised if the locally-stored blockchain is initialised with a
   252  // ChainConfig that would alter the past.
   253  type ConfigCompatError struct {
   254  	What string
   255  
   256  	// block numbers of the stored and new configurations if block based forking
   257  	StoredBlock, NewBlock *big.Int
   258  
   259  	// timestamps of the stored and new configurations if time based forking
   260  	StoredTime, NewTime *uint64
   261  
   262  	// the block number to which the local chain must be rewound to correct the error
   263  	RewindToBlock uint64
   264  
   265  	// the timestamp to which the local chain must be rewound to correct the error
   266  	RewindToTime uint64
   267  }
   268  
   269  func newBlockCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError {
   270  	var rew *big.Int
   271  	switch {
   272  	case storedblock == nil:
   273  		rew = newblock
   274  	case newblock == nil || storedblock.Cmp(newblock) < 0:
   275  		rew = storedblock
   276  	default:
   277  		rew = newblock
   278  	}
   279  	err := &ConfigCompatError{
   280  		What:          what,
   281  		StoredBlock:   storedblock,
   282  		NewBlock:      newblock,
   283  		RewindToBlock: 0,
   284  	}
   285  	if rew != nil && rew.Sign() > 0 {
   286  		err.RewindToBlock = rew.Uint64() - 1
   287  	}
   288  	return err
   289  }
   290  
   291  func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCompatError {
   292  	var rew *uint64
   293  	switch {
   294  	case storedtime == nil:
   295  		rew = newtime
   296  	case newtime == nil || *storedtime < *newtime:
   297  		rew = storedtime
   298  	default:
   299  		rew = newtime
   300  	}
   301  	err := &ConfigCompatError{
   302  		What:         what,
   303  		StoredTime:   storedtime,
   304  		NewTime:      newtime,
   305  		RewindToTime: 0,
   306  	}
   307  	if rew != nil {
   308  		err.RewindToTime = *rew - 1
   309  	}
   310  	return err
   311  }
   312  
   313  func (err *ConfigCompatError) Error() string {
   314  	if err.StoredBlock != nil {
   315  		return fmt.Sprintf("mismatching %s in database (have block %d, want block %d, rewindto block %d)", err.What, err.StoredBlock, err.NewBlock, err.RewindToBlock)
   316  	}
   317  	return fmt.Sprintf("mismatching %s in database (have timestamp %d, want timestamp %d, rewindto timestamp %d)", err.What, err.StoredTime, err.NewTime, err.RewindToTime)
   318  }
   319  
   320  // Rules wraps ChainConfig and is merely syntactic sugar or can be used for functions
   321  // that do not have or require information about the block.
   322  //
   323  // Rules is a one time interface meaning that it shouldn't be used in between transition
   324  // phases.
   325  type Rules struct {
   326  	ChainID *big.Int
   327  }
   328  
   329  // Rules ensures c's ChainID is not nil.
   330  func (c *ChainConfig) Rules(num *big.Int, timestamp uint64) Rules {
   331  	chainID := c.ChainID
   332  	if chainID == nil {
   333  		chainID = new(big.Int)
   334  	}
   335  	return Rules{
   336  		ChainID: new(big.Int).Set(chainID),
   337  	}
   338  }