2016-03-01 16:32:43 -06: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 06:36:29 -05:00
package params
2016-03-01 16:32:43 -06:00
import (
2016-11-23 06:32:25 -06:00
"fmt"
2017-07-04 04:28:58 -05:00
"math"
2016-03-01 16:32:43 -06:00
"math/big"
2016-10-24 03:40:58 -05:00
"github.com/ethereum/go-ethereum/common"
2016-03-01 16:32:43 -06:00
)
2017-07-04 04:28:58 -05:00
var (
MainnetGenesisHash = common . HexToHash ( "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" ) // Mainnet genesis hash to enforce below configs on
TestnetGenesisHash = common . HexToHash ( "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d" ) // Testnet genesis hash to enforce below configs on
)
2017-03-02 07:03:33 -06:00
var (
// MainnetChainConfig is the chain parameters to run a node on the main network.
MainnetChainConfig = & ChainConfig {
2017-07-04 04:28:58 -05:00
ChainId : big . NewInt ( 1 ) ,
HomesteadBlock : big . NewInt ( 1150000 ) ,
DAOForkBlock : big . NewInt ( 1920000 ) ,
2017-02-01 15:36:51 -06:00
DAOForkSupport : true ,
2017-07-04 04:28:58 -05:00
EIP150Block : big . NewInt ( 2463000 ) ,
EIP150Hash : common . HexToHash ( "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0" ) ,
EIP155Block : big . NewInt ( 2675000 ) ,
EIP158Block : big . NewInt ( 2675000 ) ,
MetropolisBlock : big . NewInt ( math . MaxInt64 ) , // Don't enable yet
2017-02-01 15:36:51 -06:00
Ethash : new ( EthashConfig ) ,
2017-03-02 07:03:33 -06:00
}
2017-05-04 04:36:20 -05:00
// TestnetChainConfig contains the chain parameters to run a node on the Ropsten test network.
2017-03-02 07:03:33 -06:00
TestnetChainConfig = & ChainConfig {
2017-02-01 15:36:51 -06:00
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 ) ,
2017-07-04 04:28:58 -05:00
MetropolisBlock : big . NewInt ( math . MaxInt64 ) , // Don't enable yet
2017-02-01 15:36:51 -06:00
Ethash : new ( EthashConfig ) ,
2017-03-02 07:03:33 -06:00
}
2017-05-04 04:36:20 -05:00
// RinkebyChainConfig contains the chain parameters to run a node on the Rinkeby test network.
RinkebyChainConfig = & ChainConfig {
2017-05-12 14:35:45 -05:00
ChainId : big . NewInt ( 4 ) ,
HomesteadBlock : big . NewInt ( 1 ) ,
DAOForkBlock : nil ,
DAOForkSupport : true ,
EIP150Block : big . NewInt ( 2 ) ,
EIP150Hash : common . HexToHash ( "0x9b095b36c15eaf13044373aef8ee0bd3a382a5abb92e402afa44b8249c3a90e9" ) ,
EIP155Block : big . NewInt ( 3 ) ,
EIP158Block : big . NewInt ( 3 ) ,
2017-07-04 04:28:58 -05:00
MetropolisBlock : big . NewInt ( math . MaxInt64 ) , // Don't enable yet
2017-05-12 14:35:45 -05:00
2017-05-04 04:36:20 -05:00
Clique : & CliqueConfig {
Period : 15 ,
Epoch : 30000 ,
} ,
}
2017-03-02 07:03:33 -06:00
// AllProtocolChanges contains every protocol change (EIPs)
// introduced and accepted by the Ethereum core developers.
//
// 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.
2017-07-04 04:28:58 -05:00
AllProtocolChanges = & ChainConfig { big . NewInt ( 1337 ) , big . NewInt ( 0 ) , nil , false , big . NewInt ( 0 ) , common . Hash { } , big . NewInt ( 0 ) , big . NewInt ( 0 ) , big . NewInt ( math . MaxInt64 ) /*disabled*/ , new ( EthashConfig ) , nil }
2017-02-01 15:36:51 -06:00
TestChainConfig = & ChainConfig { big . NewInt ( 1 ) , big . NewInt ( 0 ) , nil , false , big . NewInt ( 0 ) , common . Hash { } , big . NewInt ( 0 ) , big . NewInt ( 0 ) , nil , new ( EthashConfig ) , nil }
TestRules = TestChainConfig . Rules ( new ( big . Int ) )
2017-03-02 07:03:33 -06:00
)
2017-02-28 16:18:13 -06:00
2016-03-01 16:32:43 -06: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 07:44:13 -05:00
ChainId * big . Int ` json:"chainId" ` // Chain id identifies the current chain and is used for replay protection
2017-04-10 05:24:12 -05:00
HomesteadBlock * big . Int ` json:"homesteadBlock,omitempty" ` // Homestead switch block (nil = no fork, 0 = already homestead)
DAOForkBlock * big . Int ` json:"daoForkBlock,omitempty" ` // TheDAO hard-fork switch block (nil = no fork)
DAOForkSupport bool ` json:"daoForkSupport,omitempty" ` // Whether the nodes supports or opposes the DAO hard-fork
2016-03-01 16:32:43 -06:00
2016-10-20 06:36:29 -05:00
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
2017-04-10 05:24:12 -05:00
EIP150Block * big . Int ` json:"eip150Block,omitempty" ` // EIP150 HF block (nil = no fork)
EIP150Hash common . Hash ` json:"eip150Hash,omitempty" ` // EIP150 HF hash (fast sync aid)
2016-10-07 17:23:45 -05:00
2017-05-12 14:35:45 -05:00
EIP155Block * big . Int ` json:"eip155Block,omitempty" ` // EIP155 HF block
EIP158Block * big . Int ` json:"eip158Block,omitempty" ` // EIP158 HF block
2017-02-01 15:36:51 -06:00
2017-05-12 14:35:45 -05:00
MetropolisBlock * big . Int ` json:"metropolisBlock,omitempty" ` // Metropolis switch block (nil = no fork, 0 = alraedy on homestead)
2017-04-10 05:24:12 -05:00
// Various consensus engines
Ethash * EthashConfig ` json:"ethash,omitempty" `
Clique * CliqueConfig ` json:"clique,omitempty" `
}
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
type EthashConfig struct { }
// String implements the stringer interface, returning the consensus engine details.
func ( c * EthashConfig ) String ( ) string {
return "ethash"
}
// CliqueConfig is the consensus engine configs for proof-of-authority based sealing.
type CliqueConfig struct {
Period uint64 ` json:"period" ` // Number of seconds between blocks to enforce
Epoch uint64 ` json:"epoch" ` // Epoch length to reset votes and checkpoint
}
// String implements the stringer interface, returning the consensus engine details.
func ( c * CliqueConfig ) String ( ) string {
return "clique"
2016-03-01 16:32:43 -06:00
}
2017-03-02 07:03:33 -06:00
// String implements the fmt.Stringer interface.
2016-11-23 06:32:25 -06:00
func ( c * ChainConfig ) String ( ) string {
2017-04-10 05:24:12 -05:00
var engine interface { }
switch {
case c . Ethash != nil :
engine = c . Ethash
case c . Clique != nil :
engine = c . Clique
default :
engine = "unknown"
}
2017-04-24 03:32:14 -05:00
return fmt . Sprintf ( "{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Metropolis: %v Engine: %v}" ,
2016-11-23 06:32:25 -06:00
c . ChainId ,
c . HomesteadBlock ,
c . DAOForkBlock ,
c . DAOForkSupport ,
c . EIP150Block ,
c . EIP155Block ,
c . EIP158Block ,
2017-02-01 15:36:51 -06:00
c . MetropolisBlock ,
2017-04-10 05:24:12 -05:00
engine ,
2016-11-23 06:32:25 -06:00
)
}
2016-03-01 16:32:43 -06: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 07:03:33 -06: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 16:32:43 -06:00
}
2016-10-07 17:23:45 -05:00
2017-05-12 14:35:45 -05:00
func ( c * ChainConfig ) IsMetropolis ( num * big . Int ) bool {
return isForked ( c . MetropolisBlock , num )
}
2016-10-07 17:23:45 -05: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 06:36:29 -05:00
func ( c * ChainConfig ) GasTable ( num * big . Int ) GasTable {
if num == nil {
return GasTableHomestead
}
switch {
2017-03-02 07:03:33 -06:00
case c . IsEIP158 ( num ) :
2016-10-20 06:36:29 -05:00
return GasTableEIP158
2017-03-02 07:03:33 -06:00
case c . IsEIP150 ( num ) :
2016-10-20 06:36:29 -05:00
return GasTableHomesteadGasRepriceFork
default :
return GasTableHomestead
}
}
2017-03-02 07:03:33 -06: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 06:36:29 -05:00
}
2017-03-02 07:03:33 -06:00
return lasterr
2016-10-20 06:36:29 -05:00
}
2017-03-02 07:03:33 -06: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 07:44:13 -05:00
}
2017-03-02 07:03:33 -06: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 )
}
2017-05-12 14:35:45 -05:00
if isForkIncompatible ( c . MetropolisBlock , newcfg . MetropolisBlock , head ) {
return newCompatError ( "Metropolis fork block" , c . MetropolisBlock , newcfg . MetropolisBlock )
}
2017-03-02 07:03:33 -06:00
return nil
}
2016-11-02 07:44:13 -05:00
2017-03-02 07:03:33 -06: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 07:44:13 -05:00
}
2017-03-02 07:03:33 -06: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 06:36:29 -05:00
return false
2016-10-07 17:23:45 -05:00
}
2017-03-02 07:03:33 -06:00
return s . Cmp ( head ) <= 0
}
2016-10-07 17:23:45 -05:00
2017-03-02 07:03:33 -06: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-07 17:23:45 -05:00
}
2016-11-02 07:44:13 -05:00
2017-03-02 07:03:33 -06: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 07:44:13 -05:00
}
2017-03-02 07:03:33 -06: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 07:44:13 -05:00
}
2017-02-01 15:36:51 -06:00
// Rules wraps ChainConfig and is merely syntatic sugar or can be used for functions
// that do not have or require information about the block.
//
// Rules is a one time interface meaning that it shouldn't be used in between transition
// phases.
type Rules struct {
ChainId * big . Int
IsHomestead , IsEIP150 , IsEIP155 , IsEIP158 bool
IsMetropolis bool
}
func ( c * ChainConfig ) Rules ( num * big . Int ) Rules {
chainId := c . ChainId
if chainId == nil {
chainId = new ( big . Int )
}
return Rules { ChainId : new ( big . Int ) . Set ( chainId ) , IsHomestead : c . IsHomestead ( num ) , IsEIP150 : c . IsEIP150 ( num ) , IsEIP155 : c . IsEIP155 ( num ) , IsEIP158 : c . IsEIP158 ( num ) , IsMetropolis : c . IsMetropolis ( num ) }
}