| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | package params | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-11-23 13:32:25 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-24 11:40:58 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	// MainnetChainConfig is the chain parameters to run a node on the main network. | 
					
						
							|  |  |  | 	MainnetChainConfig = &ChainConfig{ | 
					
						
							|  |  |  | 		ChainId:        MainNetChainID, | 
					
						
							|  |  |  | 		HomesteadBlock: MainNetHomesteadBlock, | 
					
						
							|  |  |  | 		DAOForkBlock:   MainNetDAOForkBlock, | 
					
						
							|  |  |  | 		DAOForkSupport: true, | 
					
						
							|  |  |  | 		EIP150Block:    MainNetHomesteadGasRepriceBlock, | 
					
						
							|  |  |  | 		EIP150Hash:     MainNetHomesteadGasRepriceHash, | 
					
						
							|  |  |  | 		EIP155Block:    MainNetSpuriousDragon, | 
					
						
							|  |  |  | 		EIP158Block:    MainNetSpuriousDragon, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TestnetChainConfig contains the chain parameters to run a node on the ropsten test network. | 
					
						
							|  |  |  | 	TestnetChainConfig = &ChainConfig{ | 
					
						
							|  |  |  | 		ChainId:        big.NewInt(3), | 
					
						
							|  |  |  | 		HomesteadBlock: big.NewInt(0), | 
					
						
							|  |  |  | 		DAOForkBlock:   nil, | 
					
						
							|  |  |  | 		DAOForkSupport: true, | 
					
						
							|  |  |  | 		EIP150Block:    big.NewInt(0), | 
					
						
							|  |  |  | 		EIP150Hash:     common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"), | 
					
						
							|  |  |  | 		EIP155Block:    big.NewInt(10), | 
					
						
							|  |  |  | 		EIP158Block:    big.NewInt(10), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// AllProtocolChanges contains every protocol change (EIPs) | 
					
						
							|  |  |  | 	// introduced and accepted by the Ethereum core developers. | 
					
						
							|  |  |  | 	// TestChainConfig is like AllProtocolChanges but has chain ID 1. | 
					
						
							|  |  |  | 	// | 
					
						
							|  |  |  | 	// This configuration is intentionally not using keyed fields. | 
					
						
							|  |  |  | 	// This configuration must *always* have all forks enabled, which | 
					
						
							|  |  |  | 	// means that all fields must be set at all times. This forces | 
					
						
							|  |  |  | 	// anyone adding flags to the config to also have to set these | 
					
						
							|  |  |  | 	// fields. | 
					
						
							|  |  |  | 	AllProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0)} | 
					
						
							|  |  |  | 	TestChainConfig    = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0)} | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2017-02-28 23:18:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | // ChainConfig is the core config which determines the blockchain settings. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // ChainConfig is stored in the database on a per block basis. This means | 
					
						
							|  |  |  | // that any network, identified by its genesis block, can have its own | 
					
						
							|  |  |  | // set of configuration options. | 
					
						
							|  |  |  | type ChainConfig struct { | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	ChainId *big.Int `json:"chainId"` // Chain id identifies the current chain and is used for replay protection | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 18:48:17 +03:00
										 |  |  | 	HomesteadBlock *big.Int `json:"homesteadBlock"` // Homestead switch block (nil = no fork, 0 = already homestead) | 
					
						
							|  |  |  | 	DAOForkBlock   *big.Int `json:"daoForkBlock"`   // TheDAO hard-fork switch block (nil = no fork) | 
					
						
							|  |  |  | 	DAOForkSupport bool     `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 	// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	EIP150Block *big.Int    `json:"eip150Block"` // EIP150 HF block (nil = no fork) | 
					
						
							|  |  |  | 	EIP150Hash  common.Hash `json:"eip150Hash"`  // EIP150 HF hash (fast sync aid) | 
					
						
							| 
									
										
										
										
											2016-10-08 00:23:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	EIP155Block *big.Int `json:"eip155Block"` // EIP155 HF block | 
					
						
							|  |  |  | 	EIP158Block *big.Int `json:"eip158Block"` // EIP158 HF block | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | // String implements the fmt.Stringer interface. | 
					
						
							| 
									
										
										
										
											2016-11-23 13:32:25 +01:00
										 |  |  | func (c *ChainConfig) String() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v}", | 
					
						
							|  |  |  | 		c.ChainId, | 
					
						
							|  |  |  | 		c.HomesteadBlock, | 
					
						
							|  |  |  | 		c.DAOForkBlock, | 
					
						
							|  |  |  | 		c.DAOForkSupport, | 
					
						
							|  |  |  | 		c.EIP150Block, | 
					
						
							|  |  |  | 		c.EIP155Block, | 
					
						
							|  |  |  | 		c.EIP158Block, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | // IsHomestead returns whether num is either equal to the homestead block or greater. | 
					
						
							|  |  |  | func (c *ChainConfig) IsHomestead(num *big.Int) bool { | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	return isForked(c.HomesteadBlock, num) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // IsDAO returns whether num is either equal to the DAO fork block or greater. | 
					
						
							|  |  |  | func (c *ChainConfig) IsDAOFork(num *big.Int) bool { | 
					
						
							|  |  |  | 	return isForked(c.DAOForkBlock, num) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *ChainConfig) IsEIP150(num *big.Int) bool { | 
					
						
							|  |  |  | 	return isForked(c.EIP150Block, num) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *ChainConfig) IsEIP155(num *big.Int) bool { | 
					
						
							|  |  |  | 	return isForked(c.EIP155Block, num) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *ChainConfig) IsEIP158(num *big.Int) bool { | 
					
						
							|  |  |  | 	return isForked(c.EIP158Block, num) | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-10-08 00:23:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice). | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The returned GasTable's fields shouldn't, under any circumstances, be changed. | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | func (c *ChainConfig) GasTable(num *big.Int) GasTable { | 
					
						
							|  |  |  | 	if num == nil { | 
					
						
							|  |  |  | 		return GasTableHomestead | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch { | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	case c.IsEIP158(num): | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 		return GasTableEIP158 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	case c.IsEIP150(num): | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 		return GasTableHomesteadGasRepriceFork | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return GasTableHomestead | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | // CheckCompatible checks whether scheduled fork transitions have been imported | 
					
						
							|  |  |  | // with a mismatching chain configuration. | 
					
						
							|  |  |  | func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError { | 
					
						
							|  |  |  | 	bhead := new(big.Int).SetUint64(height) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Iterate checkCompatible to find the lowest conflict. | 
					
						
							|  |  |  | 	var lasterr *ConfigCompatError | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		err := c.checkCompatible(newcfg, bhead) | 
					
						
							|  |  |  | 		if err == nil || (lasterr != nil && err.RewindTo == lasterr.RewindTo) { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		lasterr = err | 
					
						
							|  |  |  | 		bhead.SetUint64(err.RewindTo) | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	return lasterr | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *ConfigCompatError { | 
					
						
							|  |  |  | 	if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) { | 
					
						
							|  |  |  | 		return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if isForkIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, head) { | 
					
						
							|  |  |  | 		return newCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock) | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	if c.IsDAOFork(head) && c.DAOForkSupport != newcfg.DAOForkSupport { | 
					
						
							|  |  |  | 		return newCompatError("DAO fork support flag", c.DAOForkBlock, newcfg.DAOForkBlock) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if isForkIncompatible(c.EIP150Block, newcfg.EIP150Block, head) { | 
					
						
							|  |  |  | 		return newCompatError("EIP150 fork block", c.EIP150Block, newcfg.EIP150Block) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if isForkIncompatible(c.EIP155Block, newcfg.EIP155Block, head) { | 
					
						
							|  |  |  | 		return newCompatError("EIP155 fork block", c.EIP155Block, newcfg.EIP155Block) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if isForkIncompatible(c.EIP158Block, newcfg.EIP158Block, head) { | 
					
						
							|  |  |  | 		return newCompatError("EIP158 fork block", c.EIP158Block, newcfg.EIP158Block) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if c.IsEIP158(head) && !configNumEqual(c.ChainId, newcfg.ChainId) { | 
					
						
							|  |  |  | 		return newCompatError("EIP158 chain ID", c.EIP158Block, newcfg.EIP158Block) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | // isForkIncompatible returns true if a fork scheduled at s1 cannot be rescheduled to | 
					
						
							|  |  |  | // block s2 because head is already past the fork. | 
					
						
							|  |  |  | func isForkIncompatible(s1, s2, head *big.Int) bool { | 
					
						
							|  |  |  | 	return (isForked(s1, head) || isForked(s2, head)) && !configNumEqual(s1, s2) | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | // isForked returns whether a fork scheduled at block s is active at the given head block. | 
					
						
							|  |  |  | func isForked(s, head *big.Int) bool { | 
					
						
							|  |  |  | 	if s == nil || head == nil { | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2016-10-08 00:23:45 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	return s.Cmp(head) <= 0 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-10-08 00:23:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | func configNumEqual(x, y *big.Int) bool { | 
					
						
							|  |  |  | 	if x == nil { | 
					
						
							|  |  |  | 		return y == nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if y == nil { | 
					
						
							|  |  |  | 		return x == nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return x.Cmp(y) == 0 | 
					
						
							| 
									
										
										
										
											2016-10-08 00:23:45 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | // ConfigCompatError is raised if the locally-stored blockchain is initialised with a | 
					
						
							|  |  |  | // ChainConfig that would alter the past. | 
					
						
							|  |  |  | type ConfigCompatError struct { | 
					
						
							|  |  |  | 	What string | 
					
						
							|  |  |  | 	// block numbers of the stored and new configurations | 
					
						
							|  |  |  | 	StoredConfig, NewConfig *big.Int | 
					
						
							|  |  |  | 	// the block number to which the local chain must be rewound to correct the error | 
					
						
							|  |  |  | 	RewindTo uint64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError { | 
					
						
							|  |  |  | 	var rew *big.Int | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case storedblock == nil: | 
					
						
							|  |  |  | 		rew = newblock | 
					
						
							|  |  |  | 	case newblock == nil || storedblock.Cmp(newblock) < 0: | 
					
						
							|  |  |  | 		rew = storedblock | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		rew = newblock | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err := &ConfigCompatError{what, storedblock, newblock, 0} | 
					
						
							|  |  |  | 	if rew != nil && rew.Sign() > 0 { | 
					
						
							|  |  |  | 		err.RewindTo = rew.Uint64() - 1 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | func (err *ConfigCompatError) Error() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("mismatching %s in database (have %d, want %d, rewindto %d)", err.What, err.StoredConfig, err.NewConfig, err.RewindTo) | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | } |