This commit is contained in:
ia 2018-12-10 15:39:06 -06:00
parent 06c609da29
commit 29fbfd5de1
No known key found for this signature in database
GPG key ID: F36487257419D94C
13 changed files with 50413 additions and 166 deletions

View file

@ -313,9 +313,9 @@ func (ethash *Ethash) CalcDifficulty(chain consensus.ChainReader, time uint64, p
func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {
next := new(big.Int).Add(parent.Number, big1) next := new(big.Int).Add(parent.Number, big1)
switch { switch {
case config.IsConstantinople(next): case config.IsEIP1234(next):
return calcDifficultyConstantinople(time, parent) return calcDifficultyConstantinople(time, parent)
case config.IsByzantium(next): case config.IsEIP100(next):
return calcDifficultyByzantium(time, parent) return calcDifficultyByzantium(time, parent)
case config.IsHomestead(next): case config.IsHomestead(next):
return calcDifficultyHomestead(time, parent) return calcDifficultyHomestead(time, parent)
@ -608,10 +608,10 @@ var (
func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
// Select the correct block reward based on chain progression // Select the correct block reward based on chain progression
blockReward := FrontierBlockReward blockReward := FrontierBlockReward
if config.IsByzantium(header.Number) { if config.IsEIP649(header.Number) {
blockReward = ByzantiumBlockReward blockReward = ByzantiumBlockReward
} }
if config.IsConstantinople(header.Number) { if config.IsEIP1234(header.Number) {
blockReward = ConstantinopleBlockReward blockReward = ConstantinopleBlockReward
} }
// Accumulate the rewards for the miner and any included uncles // Accumulate the rewards for the miner and any included uncles

View file

@ -102,7 +102,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
} }
// Update the state with pending changes // Update the state with pending changes
var root []byte var root []byte
if config.IsByzantium(header.Number) { if config.IsEIP658(header.Number) {
statedb.Finalise(true) statedb.Finalise(true)
} else { } else {
root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes()

View file

@ -46,9 +46,8 @@ var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{4}): &dataCopy{}, common.BytesToAddress([]byte{4}): &dataCopy{},
} }
// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum // AllPrecompiledContracts returns all possible precompiled contracts.
// contracts used in the Byzantium release. var AllPrecompiledContracts = map[common.Address]PrecompiledContract{
var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{1}): &ecrecover{}, common.BytesToAddress([]byte{1}): &ecrecover{},
common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{2}): &sha256hash{},
common.BytesToAddress([]byte{3}): &ripemd160hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{},
@ -59,6 +58,22 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{8}): &bn256Pairing{}, common.BytesToAddress([]byte{8}): &bn256Pairing{},
} }
// PrecompiledContracts returns the corresponding set of precompiled contracts for a given chain config and block number.
func PrecompiledContracts(config *params.ChainConfig, num *big.Int) map[common.Address]PrecompiledContract {
var contracts = PrecompiledContractsHomestead
if config.IsEIP198(num) {
contracts[common.BytesToAddress([]byte{5})] = &bigModExp{}
}
if config.IsEIP212(num) {
contracts[common.BytesToAddress([]byte{8})] = &bn256Pairing{}
}
if config.IsEIP213(num) {
contracts[common.BytesToAddress([]byte{6})] = &bn256Add{}
contracts[common.BytesToAddress([]byte{7})] = &bn256ScalarMul{}
}
return contracts
}
// RunPrecompiledContract runs and evaluates the output of a precompiled contract. // RunPrecompiledContract runs and evaluates the output of a precompiled contract.
func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) { func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) {
gas := p.RequiredGas(input) gas := p.RequiredGas(input)

View file

@ -337,9 +337,10 @@ var bn256PairingTests = []precompiledTest{
} }
func testPrecompiled(addr string, test precompiledTest, t *testing.T) { func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
p := PrecompiledContractsByzantium[common.HexToAddress(addr)] p := AllPrecompiledContracts[common.HexToAddress(addr)]
in := common.Hex2Bytes(test.input) in := common.Hex2Bytes(test.input)
contract := NewContract(AccountRef(common.HexToAddress("1337")), contract := NewContract(AccountRef(common.HexToAddress("1337")),
nil, new(big.Int), p.RequiredGas(in)) nil, new(big.Int), p.RequiredGas(in))
t.Run(fmt.Sprintf("%s-Gas=%d", test.name, contract.Gas), func(t *testing.T) { t.Run(fmt.Sprintf("%s-Gas=%d", test.name, contract.Gas), func(t *testing.T) {
if res, err := RunPrecompiledContract(p, in, contract); err != nil { if res, err := RunPrecompiledContract(p, in, contract); err != nil {
@ -354,7 +355,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
if test.noBenchmark { if test.noBenchmark {
return return
} }
p := PrecompiledContractsByzantium[common.HexToAddress(addr)] p := AllPrecompiledContracts[common.HexToAddress(addr)]
in := common.Hex2Bytes(test.input) in := common.Hex2Bytes(test.input)
reqGas := p.RequiredGas(in) reqGas := p.RequiredGas(in)
contract := NewContract(AccountRef(common.HexToAddress("1337")), contract := NewContract(AccountRef(common.HexToAddress("1337")),

View file

@ -43,10 +43,7 @@ type (
// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) { func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) {
if contract.CodeAddr != nil { if contract.CodeAddr != nil {
precompiles := PrecompiledContractsHomestead precompiles := PrecompiledContracts(evm.ChainConfig(), evm.BlockNumber)
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
precompiles = PrecompiledContractsByzantium
}
if p := precompiles[*contract.CodeAddr]; p != nil { if p := precompiles[*contract.CodeAddr]; p != nil {
return RunPrecompiledContract(p, input, contract) return RunPrecompiledContract(p, input, contract)
} }
@ -197,10 +194,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
snapshot = evm.StateDB.Snapshot() snapshot = evm.StateDB.Snapshot()
) )
if !evm.StateDB.Exist(addr) { if !evm.StateDB.Exist(addr) {
precompiles := PrecompiledContractsHomestead precompiles := PrecompiledContracts(evm.ChainConfig(), evm.BlockNumber)
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
precompiles = PrecompiledContractsByzantium
}
if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 { if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
// Calling a non existing account, don't do anything, but ping the tracer // Calling a non existing account, don't do anything, but ping the tracer
if evm.vmConfig.Debug && evm.depth == 0 { if evm.vmConfig.Debug && evm.depth == 0 {

View file

@ -121,7 +121,7 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x)) current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
) )
// The legacy gas metering only takes into consideration the current state // The legacy gas metering only takes into consideration the current state
if !evm.chainRules.IsConstantinople { if !evm.chainRules.IsEIP1283 {
// This checks for 3 scenario's and calculates gas accordingly: // This checks for 3 scenario's and calculates gas accordingly:
// //
// 1. From a zero-value address to a non-zero value (NEW VALUE) // 1. From a zero-value address to a non-zero value (NEW VALUE)

View file

@ -99,16 +99,7 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
// the jump table was initialised. If it was not // the jump table was initialised. If it was not
// we'll set the default jump table. // we'll set the default jump table.
if !cfg.JumpTable[STOP].valid { if !cfg.JumpTable[STOP].valid {
switch { cfg.JumpTable = instructionSet(evm.ChainConfig(), evm.BlockNumber)
case evm.ChainConfig().IsConstantinople(evm.BlockNumber):
cfg.JumpTable = constantinopleInstructionSet
case evm.ChainConfig().IsByzantium(evm.BlockNumber):
cfg.JumpTable = byzantiumInstructionSet
case evm.ChainConfig().IsHomestead(evm.BlockNumber):
cfg.JumpTable = homesteadInstructionSet
default:
cfg.JumpTable = frontierInstructionSet
}
} }
return &EVMInterpreter{ return &EVMInterpreter{
@ -119,7 +110,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
} }
func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error { func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
if in.evm.chainRules.IsByzantium { // STATICCALL
if in.evm.chainRules.IsEIP214 {
if in.readOnly { if in.readOnly {
// If the interpreter is operating in readonly mode, make sure no // If the interpreter is operating in readonly mode, make sure no
// state-modifying operation is performed. The 3rd stack item // state-modifying operation is performed. The 3rd stack item

View file

@ -50,109 +50,109 @@ type operation struct {
returns bool // determines whether the operations sets the return data content returns bool // determines whether the operations sets the return data content
} }
var ( // instructionSet returns the corresponding jump table for a given blocknumber within a chain configuration
frontierInstructionSet = newFrontierInstructionSet() func instructionSet(config *params.ChainConfig, num *big.Int) [256]operation {
homesteadInstructionSet = newHomesteadInstructionSet()
byzantiumInstructionSet = newByzantiumInstructionSet()
constantinopleInstructionSet = newConstantinopleInstructionSet()
)
// NewConstantinopleInstructionSet returns the frontier, homestead
// byzantium and contantinople instructions.
func newConstantinopleInstructionSet() [256]operation {
// instructions that can be executed during the byzantium phase.
instructionSet := newByzantiumInstructionSet()
instructionSet[SHL] = operation{
execute: opSHL,
gasCost: constGasFunc(GasFastestStep),
validateStack: makeStackFunc(2, 1),
valid: true,
}
instructionSet[SHR] = operation{
execute: opSHR,
gasCost: constGasFunc(GasFastestStep),
validateStack: makeStackFunc(2, 1),
valid: true,
}
instructionSet[SAR] = operation{
execute: opSAR,
gasCost: constGasFunc(GasFastestStep),
validateStack: makeStackFunc(2, 1),
valid: true,
}
instructionSet[EXTCODEHASH] = operation{
execute: opExtCodeHash,
gasCost: gasExtCodeHash,
validateStack: makeStackFunc(1, 1),
valid: true,
}
instructionSet[CREATE2] = operation{
execute: opCreate2,
gasCost: gasCreate2,
validateStack: makeStackFunc(4, 1),
memorySize: memoryCreate2,
valid: true,
writes: true,
returns: true,
}
return instructionSet
}
// NewByzantiumInstructionSet returns the frontier, homestead and
// byzantium instructions.
func newByzantiumInstructionSet() [256]operation {
// instructions that can be executed during the homestead phase.
instructionSet := newHomesteadInstructionSet()
instructionSet[STATICCALL] = operation{
execute: opStaticCall,
gasCost: gasStaticCall,
validateStack: makeStackFunc(6, 1),
memorySize: memoryStaticCall,
valid: true,
returns: true,
}
instructionSet[RETURNDATASIZE] = operation{
execute: opReturnDataSize,
gasCost: constGasFunc(GasQuickStep),
validateStack: makeStackFunc(0, 1),
valid: true,
}
instructionSet[RETURNDATACOPY] = operation{
execute: opReturnDataCopy,
gasCost: gasReturnDataCopy,
validateStack: makeStackFunc(3, 0),
memorySize: memoryReturnDataCopy,
valid: true,
}
instructionSet[REVERT] = operation{
execute: opRevert,
gasCost: gasRevert,
validateStack: makeStackFunc(2, 0),
memorySize: memoryRevert,
valid: true,
reverts: true,
returns: true,
}
return instructionSet
}
// NewHomesteadInstructionSet returns the frontier and homestead
// instructions that can be executed during the homestead phase.
func newHomesteadInstructionSet() [256]operation {
instructionSet := newFrontierInstructionSet() instructionSet := newFrontierInstructionSet()
instructionSet[DELEGATECALL] = operation{
execute: opDelegateCall, // Homestead
gasCost: gasDelegateCall, //
validateStack: makeStackFunc(6, 1), if config.IsEIP7(num) {
memorySize: memoryDelegateCall, instructionSet[DELEGATECALL] = operation{
valid: true, execute: opDelegateCall,
returns: true, gasCost: gasDelegateCall,
validateStack: makeStackFunc(6, 1),
memorySize: memoryDelegateCall,
valid: true,
returns: true,
}
} }
// Byzantium
//
if config.IsEIP140(num) {
instructionSet[REVERT] = operation{
execute: opRevert,
gasCost: gasRevert,
validateStack: makeStackFunc(2, 0),
memorySize: memoryRevert,
valid: true,
reverts: true,
returns: true,
}
}
if config.IsEIP214(num) {
instructionSet[STATICCALL] = operation{
execute: opStaticCall,
gasCost: gasStaticCall,
validateStack: makeStackFunc(6, 1),
memorySize: memoryStaticCall,
valid: true,
returns: true,
}
}
if config.IsEIP211(num) {
instructionSet[RETURNDATASIZE] = operation{
execute: opReturnDataSize,
gasCost: constGasFunc(GasQuickStep),
validateStack: makeStackFunc(0, 1),
valid: true,
}
instructionSet[RETURNDATACOPY] = operation{
execute: opReturnDataCopy,
gasCost: gasReturnDataCopy,
validateStack: makeStackFunc(3, 0),
memorySize: memoryReturnDataCopy,
valid: true,
}
}
// Constantinople
//
if config.IsEIP145(num) {
instructionSet[SHL] = operation{
execute: opSHL,
gasCost: constGasFunc(GasFastestStep),
validateStack: makeStackFunc(2, 1),
valid: true,
}
instructionSet[SHR] = operation{
execute: opSHR,
gasCost: constGasFunc(GasFastestStep),
validateStack: makeStackFunc(2, 1),
valid: true,
}
instructionSet[SAR] = operation{
execute: opSAR,
gasCost: constGasFunc(GasFastestStep),
validateStack: makeStackFunc(2, 1),
valid: true,
}
}
if config.IsEIP1014(num) {
instructionSet[CREATE2] = operation{
execute: opCreate2,
gasCost: gasCreate2,
validateStack: makeStackFunc(4, 1),
memorySize: memoryCreate2,
valid: true,
writes: true,
returns: true,
}
}
if config.IsEIP1052(num) {
instructionSet[EXTCODEHASH] = operation{
execute: opExtCodeHash,
gasCost: gasExtCodeHash,
validateStack: makeStackFunc(1, 1),
valid: true,
}
}
return instructionSet return instructionSet
} }
// NewFrontierInstructionSet returns the frontier instructions // NewFrontierInstructionSet returns the frontier instructions
// that can be executed during the frontier phase. // that can be executed during and after the frontier phase.
func newFrontierInstructionSet() [256]operation { func newFrontierInstructionSet() [256]operation {
return [256]operation{ return [256]operation{
STOP: { STOP: {

View file

@ -368,7 +368,7 @@ func New(code string) (*Tracer, error) {
return 1 return 1
}) })
tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int { tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int {
_, ok := vm.PrecompiledContractsByzantium[common.BytesToAddress(popSlice(ctx))] _, ok := vm.AllPrecompiledContracts[common.BytesToAddress(popSlice(ctx))]
ctx.PushBoolean(ok) ctx.PushBoolean(ok)
return 1 return 1
}) })

View file

@ -111,17 +111,130 @@ var (
// //
// This configuration is intentionally not using keyed fields to force anyone // This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields. // adding flags to the config to also have to set these fields.
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} AllEthashProtocolChanges = &ChainConfig{
big.NewInt(1337), // ChainID
big.NewInt(0), // HomesteadBlock
nil, // EIP7Block
nil, // DAOForkBlock
false, // DAOForkSupport
big.NewInt(0), // EIP150Block
common.Hash{}, // EIP150Hash
big.NewInt(0), // EIP155Block
big.NewInt(0), // EIP158Block
big.NewInt(0), // ByzantiumBlock
nil, // EIP140Block
nil, // EIP658Block
nil, // EIP100Block
nil, // EIP198Block
nil, // EIP212Block
nil, // EIP213Block
nil, // EIP214Block
nil, // EIP211Block
nil, // EIP649Block
nil, // EIP684Block
big.NewInt(0), // ConstantinopleBlock
nil, // EIP145Block
nil, // EIP1014Block
nil, // EIP1052Block
nil, // EIP1283Block
nil, // EIP1234Block
nil, // EWASMBlock
new(EthashConfig), // Ethash
nil, // Clique
}
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus. // and accepted by the Ethereum core developers into the Clique consensus.
// //
// This configuration is intentionally not using keyed fields to force anyone // This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields. // adding flags to the config to also have to set these fields.
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}} AllCliqueProtocolChanges = &ChainConfig{
big.NewInt(1337), // ChainID
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), nil, new(EthashConfig), nil} big.NewInt(0), // HomesteadBlock
TestRules = TestChainConfig.Rules(new(big.Int)) nil, // EIP7Block
nil, // DAOForkBlock
false, // DAOForkSupport
big.NewInt(0), // EIP150Block
common.Hash{}, // EIP150Hash
big.NewInt(0), // EIP155Block
big.NewInt(0), // EIP158Block
big.NewInt(0), // ByzantiumBlock
nil, // EIP140Block
nil, // EIP658Block
nil, // EIP100Block
nil, // EIP198Block
nil, // EIP212Block
nil, // EIP213Block
nil, // EIP214Block
nil, // EIP211Block
nil, // EIP649Block
nil, // EIP684Block
big.NewInt(0), // ConstantinopleBlock
nil, // EIP145Block
nil, // EIP1014Block
nil, // EIP1052Block
nil, // EIP1283Block
nil, // EIP1234Block
nil, // EWASMBlock
nil, // Ethash
&CliqueConfig{
Period: 0,
Epoch: 30000,
},
}
// TestChainConfig is used for tests.
TestChainConfig = &ChainConfig{
big.NewInt(1), // ChainID
big.NewInt(0), // HomesteadBlock
nil, // EIP7Block
nil, // DAOForkBlock
false, // DAOForkSupport
big.NewInt(0), // EIP150Block
common.Hash{}, // EIP150Hash
big.NewInt(0), // EIP155Block
big.NewInt(0), // EIP158Block
big.NewInt(0), // ByzantiumBlock
nil, // EIP140Block
nil, // EIP658Block
nil, // EIP100Block
nil, // EIP198Block
nil, // EIP212Block
nil, // EIP213Block
nil, // EIP214Block
nil, // EIP211Block
nil, // EIP649Block
nil, // EIP684Block
big.NewInt(0), // ConstantinopleBlock
nil, // EIP145Block
nil, // EIP1014Block
nil, // EIP1052Block
nil, // EIP1283Block
nil, // EIP1234Block
nil, // EWASMBlock
new(EthashConfig), // Ethash
nil, // Clique
}
TestRules = TestChainConfig.Rules(new(big.Int))
) )
// TrustedCheckpoint represents a set of post-processed trie roots (CHT and // TrustedCheckpoint represents a set of post-processed trie roots (CHT and
@ -145,6 +258,10 @@ type ChainConfig struct {
ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection ChainID *big.Int `json:"chainId"` // chainId identifies the current chain and is used for replay protection
HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead) HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead)
//
// DELEGATECALL
// https://eips.ethereum.org/EIPS/eip-7
EIP7Block *big.Int `json:"eip7Block,omitempy"`
DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` // TheDAO hard-fork switch block (nil = no fork) 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 DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork
@ -156,24 +273,16 @@ type ChainConfig struct {
EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block
EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block
ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium)
ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated)
// Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty"`
Clique *CliqueConfig `json:"clique,omitempty"`
// Homestead
// DELEGATECALL
// https://eips.ethereum.org/EIPS/eip-7
EIP7Block *big.Int `json:"eip7Block,omitempy"`
// Byzantium // Byzantium
// https://github.com/ethereum/go-ethereum/releases/tag/v1.7.0 // https://github.com/ethereum/go-ethereum/releases/tag/v1.7.0
ByzantiumBlock *big.Int `json:"byzantiumBlock,omitempty"` // Byzantium switch block (nil = no fork, 0 = already on byzantium)
// //
// REVERT instruction
// https://eips.ethereum.org/EIPS/eip-140
EIP140Block *big.Int `json:"eip140Block,omitempty"`
// transaction receipt status // transaction receipt status
// https://github.com/ethereum/EIPs/issues/98
// https://github.com/ethereum/EIPs/issues/98#issuecomment-318670322
// https://github.com/ethereum/EIPs/issues/658 // https://github.com/ethereum/EIPs/issues/658
EIP658Block *big.Int `json:"eip658Block,omitempty"` EIP658Block *big.Int `json:"eip658Block,omitempty"`
// Change difficulty adjustment to target mean block time including uncles // Change difficulty adjustment to target mean block time including uncles
@ -194,15 +303,16 @@ type ChainConfig struct {
// RETURNDATACOPY, RETURNDATASIZE // RETURNDATACOPY, RETURNDATASIZE
// https://github.com/ethereum/EIPs/issues/211 // https://github.com/ethereum/EIPs/issues/211
EIP211Block *big.Int `json:"eip211Block,omitempty"` EIP211Block *big.Int `json:"eip211Block,omitempty"`
// metropolis diff bomb delay // metropolis diff bomb delay and reducing block reward
// https://github.com/ethereum/EIPs/issues/649 // https://github.com/ethereum/EIPs/issues/649
EIP649Block *big.Int `json:"eip649Block,omitempty"` EIP649Block *big.Int `json:"eip649Block,omitempty"`
// prevent overwriting contracts // prevent overwriting contracts
// NOTE(whilei): NOT CONFIGURABLE
// https://github.com/ethereum/EIPs/issues/684 // https://github.com/ethereum/EIPs/issues/684
EIP684Block *big.Int `json:"eip684Block,omitempty"` EIP684Block *big.Int `json:"eip684Block,omitempty"`
// Constantinople
// https://github.com/ethereum/pm/wiki/Constantinople-Progress-Tracker // https://github.com/ethereum/pm/wiki/Constantinople-Progress-Tracker
ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
// //
// bitwise shifts // bitwise shifts
// https://eips.ethereum.org/EIPS/eip-145 // https://eips.ethereum.org/EIPS/eip-145
@ -219,6 +329,12 @@ type ChainConfig struct {
// constantinople difficulty bomb delay and block reward adjustment // constantinople difficulty bomb delay and block reward adjustment
// https://eips.ethereum.org/EIPS/eip-1234 // https://eips.ethereum.org/EIPS/eip-1234
EIP1234Block *big.Int `json:"eip1234Block,omitempty"` EIP1234Block *big.Int `json:"eip1234Block,omitempty"`
EWASMBlock *big.Int `json:"ewasmBlock,omitempty"` // EWASM switch block (nil = no fork, 0 = already activated)
// 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. // EthashConfig is the consensus engine configs for proof-of-work based sealing.
@ -294,9 +410,29 @@ func (c *ChainConfig) IsEIP158(num *big.Int) bool {
return isForked(c.EIP158Block, num) return isForked(c.EIP158Block, num)
} }
// IsByzantium returns whether num is either equal to the Byzantium fork block or greater. // IsByzantium returns whether num is either equal to the Byzantium fork block or greater,
// or whether the configured params satisfy all requirements fulfilling the Byzantium fork.
func (c *ChainConfig) IsByzantium(num *big.Int) bool { func (c *ChainConfig) IsByzantium(num *big.Int) bool {
return isForked(c.ByzantiumBlock, num) return isForked(c.ConstantinopleBlock, num) || func(n *big.Int) bool {
for _, block := range []*big.Int{
c.EIP198Block,
c.EIP212Block,
c.EIP213Block,
c.EIP214Block,
c.EIP211Block,
c.EIP649Block,
c.EIP684Block,
} {
if !isForked(block, n) {
return false
}
}
return true
}(num)
}
func (c *ChainConfig) IsEIP140(num *big.Int) bool {
return c.IsByzantium(num) || isForked(c.EIP140Block, num)
} }
// Embedding transaction status code in receipts // Embedding transaction status code in receipts
@ -337,9 +473,23 @@ func (c *ChainConfig) IsEIP684(num *big.Int) bool {
return c.IsByzantium(num) || isForked(c.EIP684Block, num) return c.IsByzantium(num) || isForked(c.EIP684Block, num)
} }
// IsConstantinople returns whether num is either equal to the Constantinople fork block or greater. // IsConstantinople returns whether num is either equal to the Constantinople fork block or greater,
// or whether configured params satisfy all requirements fulfilling the Constantinople fork.
func (c *ChainConfig) IsConstantinople(num *big.Int) bool { func (c *ChainConfig) IsConstantinople(num *big.Int) bool {
return isForked(c.ConstantinopleBlock, num) return isForked(c.ConstantinopleBlock, num) || func(n *big.Int) bool {
for _, block := range []*big.Int{
c.EIP145Block,
c.EIP1014Block,
c.EIP1052Block,
c.EIP1283Block,
c.EIP1234Block,
} {
if !isForked(block, n) {
return false
}
}
return true
}(num)
} }
func (c *ChainConfig) IsEIP145(num *big.Int) bool { func (c *ChainConfig) IsEIP145(num *big.Int) bool {
@ -375,8 +525,8 @@ func (c *ChainConfig) GasTable(num *big.Int) GasTable {
return GasTableHomestead return GasTableHomestead
} }
switch { switch {
case c.IsConstantinople(num): case c.IsEIP1052(num):
return GasTableConstantinople return GasTableEIP1052
case c.IsEIP158(num): case c.IsEIP158(num):
return GasTableEIP158 return GasTableEIP158
case c.IsEIP150(num): case c.IsEIP150(num):
@ -499,9 +649,11 @@ func (err *ConfigCompatError) Error() string {
// Rules is a one time interface meaning that it shouldn't be used in between transition // Rules is a one time interface meaning that it shouldn't be used in between transition
// phases. // phases.
type Rules struct { type Rules struct {
ChainID *big.Int ChainID *big.Int
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsHomestead, IsEIP7 bool
IsByzantium, IsConstantinople bool IsEIP150, IsEIP155, IsEIP158 bool
IsByzantium, IsEIP140, IsEIP658, IsEIP100, IsEIP198, IsEIP212, IsEIP213, IsEIP214, IsEIP211, IsEIP649, IsEIP684 bool
IsConstantinople, IsEIP145, IsEIP1014, IsEIP1052, IsEIP1283, IsEIP1234 bool
} }
// Rules ensures c's ChainID is not nil. // Rules ensures c's ChainID is not nil.
@ -511,12 +663,32 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
chainID = new(big.Int) chainID = new(big.Int)
} }
return Rules{ return Rules{
ChainID: new(big.Int).Set(chainID), ChainID: new(big.Int).Set(chainID),
IsHomestead: c.IsHomestead(num),
IsEIP150: c.IsEIP150(num), IsHomestead: c.IsHomestead(num),
IsEIP155: c.IsEIP155(num), IsEIP7: c.IsEIP7(num),
IsEIP158: c.IsEIP158(num),
IsByzantium: c.IsByzantium(num), IsEIP150: c.IsEIP150(num),
IsEIP155: c.IsEIP155(num),
IsEIP158: c.IsEIP158(num),
IsByzantium: c.IsByzantium(num),
IsEIP140: c.IsEIP140(num),
IsEIP658: c.IsEIP658(num),
IsEIP100: c.IsEIP100(num),
IsEIP198: c.IsEIP198(num),
IsEIP212: c.IsEIP212(num),
IsEIP213: c.IsEIP213(num),
IsEIP214: c.IsEIP214(num),
IsEIP211: c.IsEIP211(num),
IsEIP649: c.IsEIP649(num),
IsEIP684: c.IsEIP684(num),
IsConstantinople: c.IsConstantinople(num), IsConstantinople: c.IsConstantinople(num),
IsEIP145: c.IsEIP145(num),
IsEIP1014: c.IsEIP1014(num),
IsEIP1052: c.IsEIP1052(num),
IsEIP1283: c.IsEIP1283(num),
IsEIP1234: c.IsEIP1234(num),
} }
} }

View file

@ -76,9 +76,9 @@ var (
CreateBySuicide: 25000, CreateBySuicide: 25000,
} }
// GasTableConstantinople contain the gas re-prices for // GasTableEIP1052 contain the gas re-prices for
// the constantinople phase. // the constantinople phase.
GasTableConstantinople = GasTable{ GasTableEIP1052 = GasTable{
ExtcodeSize: 700, ExtcodeSize: 700,
ExtcodeCopy: 700, ExtcodeCopy: 700,
ExtcodeHash: 400, ExtcodeHash: 400,

50073
test.out Normal file

File diff suppressed because it is too large Load diff

@ -1 +1 @@
Subproject commit c02a2a17c0288a255572b37dc7ec1fcb838b9dbf Subproject commit 4cfaa3e600f45d34bc00d88a4b142d2f27762912