feat: feynman upgrade vm changes (#1193)

* add Feynman to chain spec

* remove input size limit from ecPairing

* restore original behavior for blockhash opcode

* eip-2935: manually cherry-pick upstream commit a223efc

* eip-7623: manually cherry-pick upstream commit 0e1a19d

* add note about L1 messages

* nit

* add history storage to dev genesis

* EIP-2935: adopt tracer changes from upstream a223efcf

* remove todos

* update protocol params

* add block hash to witness, plus various cleanups
This commit is contained in:
Péter Garamvölgyi 2025-06-11 14:34:40 +02:00 committed by GitHub
parent 00c5c2bd3e
commit 5148229082
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 393 additions and 48 deletions

View file

@ -152,6 +152,15 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
if chainConfig.CurieBlock != nil && chainConfig.CurieBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 { if chainConfig.CurieBlock != nil && chainConfig.CurieBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
misc.ApplyCurieHardFork(statedb) misc.ApplyCurieHardFork(statedb)
} }
// Apply EIP-2935
if pre.Env.BlockHashes != nil && chainConfig.IsFeynman(pre.Env.Timestamp) {
var (
prevNumber = pre.Env.Number - 1
prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)]
evm = vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
)
core.ProcessParentBlockHash(prevHash, evm, statedb)
}
for i, tx := range txs { for i, tx := range txs {
msg, err := tx.AsMessage(signer, pre.Env.BaseFee) msg, err := tx.AsMessage(signer, pre.Env.BaseFee)

View file

@ -140,18 +140,32 @@ func Transaction(ctx *cli.Context) error {
r.Address = sender r.Address = sender
} }
// Check intrinsic gas // Check intrinsic gas
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules := chainConfig.Rules(common.Big0, 0)
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int))); err != nil { gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai)
if err != nil {
r.Error = err r.Error = err
results = append(results, r) results = append(results, r)
continue continue
} else { }
r.IntrinsicGas = gas r.IntrinsicGas = gas
if tx.Gas() < gas { if tx.Gas() < gas {
r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), gas) r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), gas)
results = append(results, r) results = append(results, r)
continue continue
} }
// For Feynman txs, validate the floor data gas.
if rules.IsFeynman {
floorDataGas, err := core.FloorDataGas(tx.Data())
if err != nil {
r.Error = err
results = append(results, r)
continue
}
if tx.Gas() < floorDataGas {
r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrFloorDataGas, tx.Gas(), floorDataGas)
results = append(results, r)
continue
}
} }
// Validate <256bit fields // Validate <256bit fields
switch { switch {

View file

@ -81,6 +81,10 @@ var (
// than required to start the invocation. // than required to start the invocation.
ErrIntrinsicGas = errors.New("intrinsic gas too low") ErrIntrinsicGas = errors.New("intrinsic gas too low")
// ErrFloorDataGas is returned if the transaction is specified to use less gas
// than required for the data floor cost.
ErrFloorDataGas = errors.New("insufficient gas for floor data gas cost")
// ErrTxTypeNotSupported is returned if a transaction is not supported in the // ErrTxTypeNotSupported is returned if a transaction is not supported in the
// current network configuration. // current network configuration.
ErrTxTypeNotSupported = types.ErrTxTypeNotSupported ErrTxTypeNotSupported = types.ErrTxTypeNotSupported

View file

@ -500,6 +500,8 @@ func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
// Pre-deploy EIP-2935 history contract.
params.HistoryStorageAddress: {Nonce: 1, Code: params.HistoryStorageCode, Balance: common.Big0},
// LSH 250 due to finite field limitation // LSH 250 due to finite field limitation
faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 250), big.NewInt(9))}, faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 250), big.NewInt(9))},
}, },

View file

@ -167,6 +167,11 @@ func (s *StateDB) WithWitness(witness *stateless.Witness) {
s.witness = witness s.witness = witness
} }
// Witness returns the current witness for the state database.
func (s *StateDB) Witness() *stateless.Witness {
return s.witness
}
// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the // StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
// state trie concurrently while the state is mutated so that when we reach the // state trie concurrently while the state is mutated so that when we reach the
// commit phase, most of the needed data is already hot. // commit phase, most of the needed data is already hot.

View file

@ -94,6 +94,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
blockContext := NewEVMBlockContext(header, p.bc, p.config, nil) blockContext := NewEVMBlockContext(header, p.bc, p.config, nil)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
processorBlockTransactionGauge.Update(int64(block.Transactions().Len())) processorBlockTransactionGauge.Update(int64(block.Transactions().Len()))
// Apply EIP-2935
if p.config.IsFeynman(block.Time()) {
ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
}
// Iterate over and process the individual transactions // Iterate over and process the individual transactions
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number, header.Time), header.BaseFee) msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number, header.Time), header.BaseFee)
@ -199,3 +203,30 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
return applyTransaction(msg, config, bc, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) return applyTransaction(msg, config, bc, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
} }
// ProcessParentBlockHash stores the parent block hash in the history storage contract
// as per EIP-2935.
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM, statedb *state.StateDB) {
msg := types.NewMessage(
params.SystemAddress, // from
&params.HistoryStorageAddress, // to
0, // nonce
common.Big0, // amount
30_000_000, // gasLimit
common.Big0, // gasPrice
common.Big0, // gasFeeCap
common.Big0, // gasTipCap
prevHash.Bytes(), // data
nil, // accessList
false, // isFake
nil, // setCodeAuthorizations
)
evm.Reset(NewEVMTxContext(msg), statedb)
statedb.AddAddressToAccessList(params.HistoryStorageAddress)
_, _, err := evm.Call(vm.AccountRef(msg.From()), *msg.To(), msg.Data(), 30_000_000, common.Big0, nil)
if err != nil {
panic(err)
}
statedb.Finalise(true)
}

View file

@ -18,6 +18,7 @@ package core
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"encoding/binary"
"math/big" "math/big"
"testing" "testing"
@ -31,9 +32,11 @@ import (
"github.com/scroll-tech/go-ethereum/consensus/ethash" "github.com/scroll-tech/go-ethereum/consensus/ethash"
"github.com/scroll-tech/go-ethereum/consensus/misc" "github.com/scroll-tech/go-ethereum/consensus/misc"
"github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/core/vm" "github.com/scroll-tech/go-ethereum/core/vm"
"github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/ethdb/memorydb"
"github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/trie" "github.com/scroll-tech/go-ethereum/trie"
) )
@ -64,6 +67,7 @@ func TestStateProcessorErrors(t *testing.T) {
DarwinV2Time: new(uint64), DarwinV2Time: new(uint64),
EuclidTime: new(uint64), EuclidTime: new(uint64),
EuclidV2Time: new(uint64), EuclidV2Time: new(uint64),
FeynmanTime: new(uint64),
Ethash: new(params.EthashConfig), Ethash: new(params.EthashConfig),
} }
signer = types.LatestSigner(config) signer = types.LatestSigner(config)
@ -387,9 +391,9 @@ func TestStateProcessorErrors(t *testing.T) {
}{ }{
{ // ErrMaxInitCodeSizeExceeded { // ErrMaxInitCodeSizeExceeded
txs: []*types.Transaction{ txs: []*types.Transaction{
mkDynamicCreationTx(0, 500000, common.Big0, misc.CalcBaseFee(config, genesis.Header(), parentL1BaseFee), tooBigInitCode[:]), mkDynamicCreationTx(0, 520000, common.Big0, misc.CalcBaseFee(config, genesis.Header(), parentL1BaseFee), tooBigInitCode[:]),
}, },
want: "could not apply tx 0 [0x7b33776d375660694a23ef992c090265682f3687607e0099b14503fdb65d73e3]: max initcode size exceeded: code size 49153 limit 49152", want: "could not apply tx 0 [0xe0d03426cecc04467410064cb4de02012fc069d2462282735d7dfcb9dea9f63b]: max initcode size exceeded: code size 49153 limit 49152",
}, },
{ // ErrIntrinsicGas: Not enough gas to cover init code { // ErrIntrinsicGas: Not enough gas to cover init code
txs: []*types.Transaction{ txs: []*types.Transaction{
@ -453,3 +457,68 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
// Assemble and return the final block for sealing // Assemble and return the final block for sealing
return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil))
} }
func TestProcessParentBlockHash(t *testing.T) {
var (
chainConfig = &params.ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ShanghaiBlock: big.NewInt(0),
BernoulliBlock: big.NewInt(0),
CurieBlock: big.NewInt(0),
DarwinTime: new(uint64),
DarwinV2Time: new(uint64),
EuclidTime: new(uint64),
EuclidV2Time: new(uint64),
FeynmanTime: new(uint64),
Ethash: new(params.EthashConfig),
}
hashA = common.Hash{0x01}
hashB = common.Hash{0x02}
header = &types.Header{ParentHash: hashA, Number: big.NewInt(2), Difficulty: big.NewInt(0)}
parent = &types.Header{ParentHash: hashB, Number: big.NewInt(1), Difficulty: big.NewInt(0)}
coinbase = common.Address{}
)
test := func(statedb *state.StateDB) {
statedb.SetNonce(params.HistoryStorageAddress, 1)
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
statedb.IntermediateRoot(true)
vmContext := NewEVMBlockContext(header, nil, chainConfig, &coinbase)
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{})
ProcessParentBlockHash(header.ParentHash, evm, statedb)
vmContext = NewEVMBlockContext(parent, nil, chainConfig, &coinbase)
evm = vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{})
ProcessParentBlockHash(parent.ParentHash, evm, statedb)
// make sure that the state is correct
if have := getParentBlockHash(statedb, 1); have != hashA {
t.Errorf("want parent hash %v, have %v", hashA, have)
}
if have := getParentBlockHash(statedb, 0); have != hashB {
t.Errorf("want parent hash %v, have %v", hashB, have)
}
}
t.Run("MPT", func(t *testing.T) {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil)
test(statedb)
})
}
func getParentBlockHash(statedb *state.StateDB, number uint64) common.Hash {
ringIndex := number % params.HistoryServeWindow
var key common.Hash
binary.BigEndian.PutUint64(key[24:], ringIndex)
return statedb.GetState(params.HistoryStorageAddress, key)
}

View file

@ -17,6 +17,7 @@
package core package core
import ( import (
"bytes"
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
@ -141,12 +142,9 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
// Bump the required gas by the amount of transactional data // Bump the required gas by the amount of transactional data
if dataLen > 0 { if dataLen > 0 {
// Zero and non-zero bytes are priced differently // Zero and non-zero bytes are priced differently
var nz uint64 z := uint64(bytes.Count(data, []byte{0}))
for _, byt := range data { nz := dataLen - z
if byt != 0 {
nz++
}
}
// Make sure we don't exceed uint64 for all data combinations // Make sure we don't exceed uint64 for all data combinations
nonZeroGas := params.TxDataNonZeroGasFrontier nonZeroGas := params.TxDataNonZeroGasFrontier
if isEIP2028 { if isEIP2028 {
@ -157,7 +155,6 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
} }
gas += nz * nonZeroGas gas += nz * nonZeroGas
z := dataLen - nz
if (math.MaxUint64-gas)/params.TxDataZeroGas < z { if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
} }
@ -181,6 +178,21 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
return gas, nil return gas, nil
} }
// FloorDataGas computes the minimum gas required for a transaction based on its data tokens (EIP-7623).
func FloorDataGas(data []byte) (uint64, error) {
var (
z = uint64(bytes.Count(data, []byte{0}))
nz = uint64(len(data)) - z
tokens = nz*params.TxTokenPerNonZeroByte + z
)
// Check for overflow
if (math.MaxUint64-params.TxGas)/params.TxCostFloorPerToken < tokens {
return 0, ErrGasUintOverflow
}
// Minimum gas required for a transaction based on its data tokens (EIP-7623).
return params.TxGas + tokens*params.TxCostFloorPerToken, nil
}
// toWordSize returns the ceiled word size required for init code payment calculation. // toWordSize returns the ceiled word size required for init code payment calculation.
func toWordSize(size uint64) uint64 { func toWordSize(size uint64) uint64 {
if size > math.MaxUint64-31 { if size > math.MaxUint64-31 {
@ -380,16 +392,30 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
sender = vm.AccountRef(msg.From()) sender = vm.AccountRef(msg.From())
rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Time.Uint64()) rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Time.Uint64())
contractCreation = msg.To() == nil contractCreation = msg.To() == nil
floorDataGas uint64
) )
// Check clauses 4-5, subtract intrinsic gas if everything is correct // Check clauses 4-5, subtract intrinsic gas if everything is correct
gas, err := IntrinsicGas(st.data, st.msg.AccessList(), st.msg.SetCodeAuthorizations(), contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) gas, err := IntrinsicGas(st.data, st.msg.AccessList(), st.msg.SetCodeAuthorizations(), contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai)
if err != nil { if err != nil {
// Note: The L1 message queue contract ensures that this cannot happen for L1 messages.
return nil, err return nil, err
} }
if st.gas < gas { if st.gas < gas {
// Note: The L1 message queue contract ensures that this cannot happen for L1 messages.
return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gas, gas) return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gas, gas)
} }
// Gas limit suffices for the floor data cost (EIP-7623)
if rules.IsFeynman {
floorDataGas, err = FloorDataGas(st.data)
if err != nil {
return nil, err
}
if st.gas < floorDataGas {
// Note: The L1 message queue contract ensures that this cannot happen for L1 messages.
return nil, fmt.Errorf("%w: have %d, want %d", ErrFloorDataGas, st.gas, floorDataGas)
}
}
st.gas -= gas st.gas -= gas
// Check clause 6 // Check clause 6
@ -455,13 +481,16 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
}, nil }, nil
} }
if !rules.IsLondon { // Compute refund counter, capped to a refund quotient.
// Before EIP-3529: refunds were capped to gasUsed / 2 st.gas += st.calcRefund()
st.refundGas(params.RefundQuotient) if rules.IsFeynman {
} else { // After EIP-7623: Data-heavy transactions pay the floor gas.
// After EIP-3529: refunds are capped to gasUsed / 5 if st.gasUsed() < floorDataGas {
st.refundGas(params.RefundQuotientEIP3529) st.gas = st.initialGas - floorDataGas
} }
}
st.returnGas()
effectiveTip := st.gasPrice effectiveTip := st.gasPrice
// only burn the base fee if the fee vault is not enabled // only burn the base fee if the fee vault is not enabled
@ -545,14 +574,25 @@ func (st *StateTransition) applyAuthorization(auth *types.SetCodeAuthorization)
return types.AuthorizationResult{Authority: authority, PreCode: preCode, Success: true} return types.AuthorizationResult{Authority: authority, PreCode: preCode, Success: true}
} }
func (st *StateTransition) refundGas(refundQuotient uint64) { // calcRefund computes refund counter, capped to a refund quotient.
// Apply refund counter, capped to a refund quotient func (st *StateTransition) calcRefund() uint64 {
refund := st.gasUsed() / refundQuotient var refund uint64
if !st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Before EIP-3529: refunds were capped to gasUsed / 2
refund = st.gasUsed() / params.RefundQuotient
} else {
// After EIP-3529: refunds are capped to gasUsed / 5
refund = st.gasUsed() / params.RefundQuotientEIP3529
}
if refund > st.state.GetRefund() { if refund > st.state.GetRefund() {
refund = st.state.GetRefund() refund = st.state.GetRefund()
} }
st.gas += refund return refund
}
// returnGas returns ETH for remaining gas,
// exchanged at the original rate.
func (st *StateTransition) returnGas() {
// Return ETH for remaining gas, exchanged at the original rate. // Return ETH for remaining gas, exchanged at the original rate.
remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
st.state.AddBalance(st.msg.From(), remaining) st.state.AddBalance(st.msg.From(), remaining)

View file

@ -297,6 +297,7 @@ type TxPool struct {
eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions. eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions.
shanghai bool // Fork indicator whether we are in the Shanghai stage. shanghai bool // Fork indicator whether we are in the Shanghai stage.
eip7702 bool // Fork indicator whether we are using EIP-7702 type transactions. eip7702 bool // Fork indicator whether we are using EIP-7702 type transactions.
feynman bool // Fork indicator whether we are in the Feynman stage.
currentState *state.StateDB // Current state in the blockchain head currentState *state.StateDB // Current state in the blockchain head
currentHead *big.Int // Current blockchain head currentHead *big.Int // Current blockchain head
@ -855,6 +856,16 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if tx.Gas() < intrGas { if tx.Gas() < intrGas {
return ErrIntrinsicGas return ErrIntrinsicGas
} }
// Ensure the transaction can cover floor data gas.
if pool.feynman {
floorDataGas, err := FloorDataGas(tx.Data())
if err != nil {
return err
}
if tx.Gas() < floorDataGas {
return fmt.Errorf("%w: gas %v, minimum needed %v", ErrFloorDataGas, tx.Gas(), floorDataGas)
}
}
return nil return nil
} }
@ -1583,6 +1594,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
pool.eip1559 = pool.chainconfig.IsCurie(next) pool.eip1559 = pool.chainconfig.IsCurie(next)
pool.shanghai = pool.chainconfig.IsShanghai(next) pool.shanghai = pool.chainconfig.IsShanghai(next)
pool.eip7702 = pool.chainconfig.IsEuclidV2(newHead.Time) pool.eip7702 = pool.chainconfig.IsEuclidV2(newHead.Time)
pool.feynman = pool.chainconfig.IsFeynman(newHead.Time)
// Update current head // Update current head
pool.currentHead = next pool.currentHead = next

View file

@ -80,7 +80,7 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: false},
common.BytesToAddress([]byte{9}): &blake2F{}, common.BytesToAddress([]byte{9}): &blake2F{},
} }
@ -94,7 +94,7 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: false},
common.BytesToAddress([]byte{9}): &blake2F{}, common.BytesToAddress([]byte{9}): &blake2F{},
} }
@ -108,7 +108,7 @@ var PrecompiledContractsArchimedes = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: true},
common.BytesToAddress([]byte{9}): &blake2FDisabled{}, common.BytesToAddress([]byte{9}): &blake2FDisabled{},
} }
@ -122,7 +122,7 @@ var PrecompiledContractsBernoulli = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: true},
common.BytesToAddress([]byte{9}): &blake2FDisabled{}, common.BytesToAddress([]byte{9}): &blake2FDisabled{},
} }
@ -136,7 +136,22 @@ var PrecompiledContractsEuclidV2 = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: true},
common.BytesToAddress([]byte{9}): &blake2FDisabled{},
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
}
// PrecompiledContractsFeynman contains the default set of pre-compiled Ethereum
// contracts used in the Feynman release.
var PrecompiledContractsFeynman = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{1}): &ecrecover{},
common.BytesToAddress([]byte{2}): &sha256hash{},
common.BytesToAddress([]byte{3}): &ripemd160hashDisabled{},
common.BytesToAddress([]byte{4}): &dataCopy{},
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: false},
common.BytesToAddress([]byte{9}): &blake2FDisabled{}, common.BytesToAddress([]byte{9}): &blake2FDisabled{},
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{}, common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
} }
@ -156,6 +171,7 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
} }
var ( var (
PrecompiledAddressesFeynman []common.Address
PrecompiledAddressesEuclidV2 []common.Address PrecompiledAddressesEuclidV2 []common.Address
PrecompiledAddressesBernoulli []common.Address PrecompiledAddressesBernoulli []common.Address
PrecompiledAddressesArchimedes []common.Address PrecompiledAddressesArchimedes []common.Address
@ -187,11 +203,16 @@ func init() {
for k := range PrecompiledContractsEuclidV2 { for k := range PrecompiledContractsEuclidV2 {
PrecompiledAddressesEuclidV2 = append(PrecompiledAddressesEuclidV2, k) PrecompiledAddressesEuclidV2 = append(PrecompiledAddressesEuclidV2, k)
} }
for k := range PrecompiledContractsFeynman {
PrecompiledAddressesFeynman = append(PrecompiledAddressesFeynman, k)
}
} }
// ActivePrecompiles returns the precompiles enabled with the current configuration. // ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules params.Rules) []common.Address { func ActivePrecompiles(rules params.Rules) []common.Address {
switch { switch {
case rules.IsFeynman:
return PrecompiledAddressesFeynman
case rules.IsEuclidV2: case rules.IsEuclidV2:
return PrecompiledAddressesEuclidV2 return PrecompiledAddressesEuclidV2
case rules.IsBernoulli: case rules.IsBernoulli:
@ -600,10 +621,6 @@ var (
// runBn256Pairing implements the Bn256Pairing precompile, referenced by both // runBn256Pairing implements the Bn256Pairing precompile, referenced by both
// Byzantium and Istanbul operations. // Byzantium and Istanbul operations.
func runBn256Pairing(input []byte) ([]byte, error) { func runBn256Pairing(input []byte) ([]byte, error) {
// Allow at most 4 inputs
if len(input) > 4*192 {
return nil, errBadPairingInput
}
// Handle some corner cases cheaply // Handle some corner cases cheaply
if len(input)%192 > 0 { if len(input)%192 > 0 {
return nil, errBadPairingInput return nil, errBadPairingInput
@ -634,7 +651,9 @@ func runBn256Pairing(input []byte) ([]byte, error) {
// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve // bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve
// conforming to Istanbul consensus rules. // conforming to Istanbul consensus rules.
type bn256PairingIstanbul struct{} type bn256PairingIstanbul struct {
limitInputLength bool
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
@ -642,6 +661,13 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
} }
func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) { func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
if c.limitInputLength {
// Allow at most 4 inputs
if len(input) > 4*192 {
return nil, errBadPairingInput
}
}
return runBn256Pairing(input) return runBn256Pairing(input)
} }

View file

@ -65,6 +65,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{16}): &bls12381Pairing{}, common.BytesToAddress([]byte{16}): &bls12381Pairing{},
common.BytesToAddress([]byte{17}): &bls12381MapG1{}, common.BytesToAddress([]byte{17}): &bls12381MapG1{},
common.BytesToAddress([]byte{18}): &bls12381MapG2{}, common.BytesToAddress([]byte{18}): &bls12381MapG2{},
common.BytesToAddress([]byte{0xf8}): &bn256PairingIstanbul{limitInputLength: true},
common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{}, common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{},
} }
@ -264,7 +265,7 @@ func BenchmarkPrecompiledBn256ScalarMul(b *testing.B) { benchJson("bn256ScalarMu
// Tests the sample inputs from the elliptic curve pairing check EIP 197. // Tests the sample inputs from the elliptic curve pairing check EIP 197.
func TestPrecompiledBn256Pairing(t *testing.T) { testJson("bn256Pairing", "08", t) } func TestPrecompiledBn256Pairing(t *testing.T) { testJson("bn256Pairing", "08", t) }
func TestPrecompiledBn256PairingFail(t *testing.T) { testJsonFail("bn256Pairing", "08", t) } func TestPrecompiledBn256PairingFail(t *testing.T) { testJsonFail("bn256Pairing", "f8", t) }
func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) } func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) }
func TestPrecompiledBlake2F(t *testing.T) { testJson("blake2F", "09", t) } func TestPrecompiledBlake2F(t *testing.T) { testJson("blake2F", "09", t) }

View file

@ -47,6 +47,8 @@ type (
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
var precompiles map[common.Address]PrecompiledContract var precompiles map[common.Address]PrecompiledContract
switch { switch {
case evm.chainRules.IsFeynman:
precompiles = PrecompiledContractsFeynman
case evm.chainRules.IsEuclidV2: case evm.chainRules.IsEuclidV2:
precompiles = PrecompiledContractsEuclidV2 precompiles = PrecompiledContractsEuclidV2
case evm.chainRules.IsBernoulli: case evm.chainRules.IsBernoulli:

View file

@ -470,6 +470,32 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
return nil, nil return nil, nil
} }
func opBlockhashPostFeynman(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
num := scope.Stack.peek()
num64, overflow := num.Uint64WithOverflow()
if overflow {
num.Clear()
return nil, nil
}
var upper, lower uint64
upper = interpreter.evm.Context.BlockNumber.Uint64()
if upper < 257 {
lower = 0
} else {
lower = upper - 256
}
if num64 >= lower && num64 < upper {
res := interpreter.evm.Context.GetHash(num64)
if witness := interpreter.evm.StateDB.Witness(); witness != nil {
witness.AddBlockHash(num64)
}
num.SetBytes(res[:])
} else {
num.Clear()
}
return nil, nil
}
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.FeeRecipient().Bytes())) scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.FeeRecipient().Bytes()))
return nil, nil return nil, nil

View file

@ -20,6 +20,7 @@ import (
"math/big" "math/big"
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/stateless"
"github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/params" "github.com/scroll-tech/go-ethereum/params"
) )
@ -85,6 +86,8 @@ type StateDB interface {
AddPreimage(common.Hash, []byte) AddPreimage(common.Hash, []byte)
ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error
Witness() *stateless.Witness
} }
// CallContext provides a basic interface for the EVM calling conventions. The EVM // CallContext provides a basic interface for the EVM calling conventions. The EVM

View file

@ -74,6 +74,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
if cfg.JumpTable[STOP] == nil { if cfg.JumpTable[STOP] == nil {
var jt JumpTable var jt JumpTable
switch { switch {
case evm.chainRules.IsFeynman:
jt = feynmanInstructionSet
case evm.chainRules.IsEuclidV2: case evm.chainRules.IsEuclidV2:
jt = euclidV2InstructionSet jt = euclidV2InstructionSet
case evm.chainRules.IsDarwin: case evm.chainRules.IsDarwin:

View file

@ -62,11 +62,24 @@ var (
curieInstructionSet = newCurieInstructionSet() curieInstructionSet = newCurieInstructionSet()
darwinInstructionSet = newDarwinInstructionSet() darwinInstructionSet = newDarwinInstructionSet()
euclidV2InstructionSet = newEuclidV2InstructionSet() euclidV2InstructionSet = newEuclidV2InstructionSet()
feynmanInstructionSet = newFeynmanInstructionSet()
) )
// JumpTable contains the EVM opcodes supported at a given fork. // JumpTable contains the EVM opcodes supported at a given fork.
type JumpTable [256]*operation type JumpTable [256]*operation
// newFeynmanInstructionSet returns the frontier, homestead, byzantium,
// contantinople, istanbul, petersburg, berlin, london, shanghai, curie, darwin, euclidV2,
// and feynman instructions.
func newFeynmanInstructionSet() JumpTable {
instructionSet := newEuclidV2InstructionSet()
// change block hash opcode implementation
instructionSet[BLOCKHASH].execute = opBlockhashPostFeynman
return instructionSet
}
// newEuclidV2InstructionSet returns the frontier, homestead, byzantium, // newEuclidV2InstructionSet returns the frontier, homestead, byzantium,
// contantinople, istanbul, petersburg, berlin, london, shanghai, curie, darwin and euclidV2 instructions. // contantinople, istanbul, petersburg, berlin, london, shanghai, curie, darwin and euclidV2 instructions.
func newEuclidV2InstructionSet() JumpTable { func newEuclidV2InstructionSet() JumpTable {

View file

@ -74,6 +74,8 @@ func setDefaults(cfg *Config) {
CurieBlock: new(big.Int), CurieBlock: new(big.Int),
DarwinTime: new(uint64), DarwinTime: new(uint64),
DarwinV2Time: new(uint64), DarwinV2Time: new(uint64),
EuclidV2Time: new(uint64),
FeynmanTime: new(uint64),
} }
} }

View file

@ -337,17 +337,13 @@ func TestBlockhash(t *testing.T) {
if zero.BitLen() != 0 { if zero.BitLen() != 0 {
t.Fatalf("expected zeroes, got %x", ret[0:32]) t.Fatalf("expected zeroes, got %x", ret[0:32])
} }
firstExpectedHash := new(big.Int) if first.Uint64() != 999 {
firstExpectedHash.SetString("13215081625009140218242111988507489764601005198286886925088730931502473149599", 10) t.Fatalf("second block should be 999, got %d (%x)", first, ret[32:64])
if first.Uint64() != firstExpectedHash.Uint64() {
t.Fatalf("first hash should be 13215081625009140218242111988507489764601005198286886925088730931502473149599, got %d (%x)", first, ret[32:64])
} }
lastExpectedHash := new(big.Int) if last.Uint64() != 744 {
lastExpectedHash.SetString("2851160567348483005169712516804956111111231427377973738952179767509712807467", 10) t.Fatalf("last block should be 744, got %d (%x)", last, ret[64:96])
if last.Uint64() != lastExpectedHash.Uint64() {
t.Fatalf("last hash should be 2851160567348483005169712516804956111111231427377973738952179767509712807467, got %d (%x)", last, ret[64:96])
} }
if exp, got := 0, chain.counter; exp != got { if exp, got := 255, chain.counter; exp != got {
t.Errorf("suboptimal; too much chain iteration, expected %d, got %d", exp, got) t.Errorf("suboptimal; too much chain iteration, expected %d, got %d", exp, got)
} }
} }

View file

@ -76,6 +76,20 @@
"Gas": 113000, "Gas": 113000,
"NoBenchmark": false "NoBenchmark": false
}, },
{
"Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
"Name": "ten_point_match_1",
"Gas": 385000,
"NoBenchmark": false
},
{
"Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
"Name": "ten_point_match_2",
"Gas": 385000,
"NoBenchmark": false
},
{ {
"Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
"Expected": "0000000000000000000000000000000000000000000000000000000000000001", "Expected": "0000000000000000000000000000000000000000000000000000000000000001",

View file

@ -176,6 +176,12 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec
if err != nil { if err != nil {
return nil, vm.BlockContext{}, nil, err return nil, vm.BlockContext{}, nil, err
} }
// If feynman hardfork, insert parent block hash in the state as per EIP-2935.
if eth.blockchain.Config().IsFeynman(block.Time()) {
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, eth.blockchain.Config(), nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, eth.blockchain.Config(), vm.Config{})
core.ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
}
if txIndex == 0 && len(block.Transactions()) == 0 { if txIndex == 0 && len(block.Transactions()) == 0 {
return nil, vm.BlockContext{}, statedb, nil return nil, vm.BlockContext{}, statedb, nil
} }

View file

@ -277,6 +277,11 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
for task := range tasks { for task := range tasks {
signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time()) signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time())
blockCtx := core.NewEVMBlockContext(task.block.Header(), api.chainContext(localctx), api.backend.ChainConfig(), nil) blockCtx := core.NewEVMBlockContext(task.block.Header(), api.chainContext(localctx), api.backend.ChainConfig(), nil)
// EIP-2935: Insert parent hash in history contract.
if api.backend.ChainConfig().IsFeynman(task.block.Time()) {
evm := vm.NewEVM(blockCtx, vm.TxContext{}, task.statedb, api.backend.ChainConfig(), vm.Config{})
core.ProcessParentBlockHash(task.block.ParentHash(), evm, task.statedb)
}
// Trace all the transactions contained within // Trace all the transactions contained within
for i, tx := range task.block.Transactions() { for i, tx := range task.block.Transactions() {
msg, _ := tx.AsMessage(signer, task.block.BaseFee()) msg, _ := tx.AsMessage(signer, task.block.BaseFee())
@ -539,6 +544,11 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil) vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
deleteEmptyObjects = chainConfig.IsEIP158(block.Number()) deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
) )
// EIP-2935: Insert parent hash in history contract.
if api.backend.ChainConfig().IsFeynman(block.Time()) {
vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{})
core.ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
}
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
var ( var (
msg, _ = tx.AsMessage(signer, block.BaseFee()) msg, _ = tx.AsMessage(signer, block.BaseFee())
@ -614,6 +624,11 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
threads = len(txs) threads = len(txs)
} }
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil) blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), api.backend.ChainConfig(), nil)
// EIP-2935: Insert parent hash in history contract.
if api.backend.ChainConfig().IsFeynman(block.Time()) {
evm := vm.NewEVM(blockCtx, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
}
blockHash := block.Hash() blockHash := block.Hash()
blockNumber := block.NumberU64() blockNumber := block.NumberU64()
for th := 0; th < threads; th++ { for th := 0; th < threads; th++ {
@ -748,6 +763,13 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
canon = false canon = false
} }
} }
// EIP-2935: Insert parent hash in history contract.
if api.backend.ChainConfig().IsFeynman(block.Time()) {
evm := vm.NewEVM(vmctx, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
}
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
// Prepare the trasaction for un-traced execution // Prepare the trasaction for un-traced execution
var ( var (

View file

@ -627,15 +627,25 @@ func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorging bo
// handleForks // handleForks
func (w *worker) handleForks() (bool, error) { func (w *worker) handleForks() (bool, error) {
// Apply Curie predeployed contract update
if w.chainConfig.CurieBlock != nil && w.chainConfig.CurieBlock.Cmp(w.current.header.Number) == 0 { if w.chainConfig.CurieBlock != nil && w.chainConfig.CurieBlock.Cmp(w.current.header.Number) == 0 {
misc.ApplyCurieHardFork(w.current.state) misc.ApplyCurieHardFork(w.current.state)
return true, nil return true, nil
} }
// Stop/start miner at Euclid fork boundary on zktrie/mpt nodes
if w.chainConfig.IsEuclid(w.current.header.Time) { if w.chainConfig.IsEuclid(w.current.header.Time) {
parent := w.chain.GetBlockByHash(w.current.header.ParentHash) parent := w.chain.GetBlockByHash(w.current.header.ParentHash)
return parent != nil && !w.chainConfig.IsEuclid(parent.Time()), nil return parent != nil && !w.chainConfig.IsEuclid(parent.Time()), nil
} }
// Apply EIP-2935
if w.chainConfig.IsFeynman(w.current.header.Time) {
context := core.NewEVMBlockContext(w.current.header, w.chain, w.chainConfig, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, w.current.state, w.chainConfig, vm.Config{})
core.ProcessParentBlockHash(w.current.header.ParentHash, vmenv, w.current.state)
}
return false, nil return false, nil
} }

View file

@ -1404,6 +1404,7 @@ func TestEuclidV2TransitionVerification(t *testing.T) {
chainConfig := params.AllCliqueProtocolChanges.Clone() chainConfig := params.AllCliqueProtocolChanges.Clone()
chainConfig.EuclidTime = newUint64(0) chainConfig.EuclidTime = newUint64(0)
chainConfig.EuclidV2Time = newUint64(10000) chainConfig.EuclidV2Time = newUint64(10000)
chainConfig.FeynmanTime = nil
chainConfig.Clique = &params.CliqueConfig{Period: 1, Epoch: 30000} chainConfig.Clique = &params.CliqueConfig{Period: 1, Epoch: 30000}
chainConfig.SystemContract = &params.SystemContractConfig{Period: 1} chainConfig.SystemContract = &params.SystemContractConfig{Period: 1}

View file

@ -330,6 +330,7 @@ var (
DarwinV2Time: newUint64(1724832000), DarwinV2Time: newUint64(1724832000),
EuclidTime: newUint64(1741680000), EuclidTime: newUint64(1741680000),
EuclidV2Time: newUint64(1741852800), EuclidV2Time: newUint64(1741852800),
FeynmanTime: nil,
Clique: &CliqueConfig{ Clique: &CliqueConfig{
Period: 3, Period: 3,
Epoch: 30000, Epoch: 30000,
@ -381,6 +382,7 @@ var (
DarwinV2Time: newUint64(1725264000), DarwinV2Time: newUint64(1725264000),
EuclidTime: newUint64(1744815600), EuclidTime: newUint64(1744815600),
EuclidV2Time: newUint64(1745305200), EuclidV2Time: newUint64(1745305200),
FeynmanTime: nil,
Clique: &CliqueConfig{ Clique: &CliqueConfig{
Period: 3, Period: 3,
Epoch: 30000, Epoch: 30000,
@ -521,6 +523,7 @@ var (
DarwinV2Time: new(uint64), DarwinV2Time: new(uint64),
EuclidTime: new(uint64), EuclidTime: new(uint64),
EuclidV2Time: new(uint64), EuclidV2Time: new(uint64),
FeynmanTime: new(uint64),
TerminalTotalDifficulty: nil, TerminalTotalDifficulty: nil,
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
@ -662,6 +665,7 @@ type ChainConfig struct {
DarwinV2Time *uint64 `json:"darwinv2Time,omitempty"` // DarwinV2 switch time (nil = no fork, 0 = already on darwinv2) DarwinV2Time *uint64 `json:"darwinv2Time,omitempty"` // DarwinV2 switch time (nil = no fork, 0 = already on darwinv2)
EuclidTime *uint64 `json:"euclidTime,omitempty"` // Euclid switch time (nil = no fork, 0 = already on euclid) EuclidTime *uint64 `json:"euclidTime,omitempty"` // Euclid switch time (nil = no fork, 0 = already on euclid)
EuclidV2Time *uint64 `json:"euclidv2Time,omitempty"` // EuclidV2 switch time (nil = no fork, 0 = already on euclidv2) EuclidV2Time *uint64 `json:"euclidv2Time,omitempty"` // EuclidV2 switch time (nil = no fork, 0 = already on euclidv2)
FeynmanTime *uint64 `json:"feynmanTime,omitempty"` // Feynman switch time (nil = no fork, 0 = already on feynman)
// TerminalTotalDifficulty is the amount of total difficulty reached by // TerminalTotalDifficulty is the amount of total difficulty reached by
// the network that triggers the consensus upgrade. // the network that triggers the consensus upgrade.
@ -852,7 +856,11 @@ func (c *ChainConfig) String() string {
if c.EuclidV2Time != nil { if c.EuclidV2Time != nil {
euclidV2Time = fmt.Sprintf("@%v", *c.EuclidV2Time) euclidV2Time = fmt.Sprintf("@%v", *c.EuclidV2Time)
} }
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, Berlin: %v, London: %v, Arrow Glacier: %v, Archimedes: %v, Shanghai: %v, Bernoulli: %v, Curie: %v, Darwin: %v, DarwinV2: %v, Euclid: %v, EuclidV2: %v, Engine: %v, Scroll config: %v}", feynmanTime := "<nil>"
if c.FeynmanTime != nil {
feynmanTime = fmt.Sprintf("@%v", *c.FeynmanTime)
}
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, Berlin: %v, London: %v, Arrow Glacier: %v, Archimedes: %v, Shanghai: %v, Bernoulli: %v, Curie: %v, Darwin: %v, DarwinV2: %v, Euclid: %v, EuclidV2: %v, Feynman: %v, Engine: %v, Scroll config: %v}",
c.ChainID, c.ChainID,
c.HomesteadBlock, c.HomesteadBlock,
c.DAOForkBlock, c.DAOForkBlock,
@ -876,6 +884,7 @@ func (c *ChainConfig) String() string {
darwinV2Time, darwinV2Time,
euclidTime, euclidTime,
euclidV2Time, euclidV2Time,
feynmanTime,
engine, engine,
c.Scroll, c.Scroll,
) )
@ -988,6 +997,11 @@ func (c *ChainConfig) IsEuclidV2(now uint64) bool {
return isForkedTime(now, c.EuclidV2Time) return isForkedTime(now, c.EuclidV2Time)
} }
// IsFeynman returns whether time is either equal to the Feynman fork time or greater.
func (c *ChainConfig) IsFeynman(now uint64) bool {
return isForkedTime(now, c.FeynmanTime)
}
// IsTerminalPoWBlock returns whether the given block is the last block of PoW stage. // IsTerminalPoWBlock returns whether the given block is the last block of PoW stage.
func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool { func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool {
if c.TerminalTotalDifficulty == nil { if c.TerminalTotalDifficulty == nil {
@ -1201,6 +1215,7 @@ type Rules struct {
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
IsBerlin, IsLondon, IsArchimedes, IsShanghai bool IsBerlin, IsLondon, IsArchimedes, IsShanghai bool
IsBernoulli, IsCurie, IsDarwin, IsEuclid, IsEuclidV2 bool IsBernoulli, IsCurie, IsDarwin, IsEuclid, IsEuclidV2 bool
IsFeynman bool
} }
// Rules ensures c's ChainID is not nil. // Rules ensures c's ChainID is not nil.
@ -1228,5 +1243,6 @@ func (c *ChainConfig) Rules(num *big.Int, time uint64) Rules {
IsDarwin: c.IsDarwin(time), IsDarwin: c.IsDarwin(time),
IsEuclid: c.IsEuclid(time), IsEuclid: c.IsEuclid(time),
IsEuclidV2: c.IsEuclidV2(time), IsEuclidV2: c.IsEuclidV2(time),
IsFeynman: c.IsFeynman(time),
} }
} }

View file

@ -16,7 +16,11 @@
package params package params
import "math/big" import (
"math/big"
"github.com/scroll-tech/go-ethereum/common"
)
const ( const (
GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations.
@ -87,6 +91,8 @@ const (
TxDataNonZeroGasFrontier uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. TxDataNonZeroGasFrontier uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
TxDataNonZeroGasEIP2028 uint64 = 16 // Per byte of non zero data attached to a transaction after EIP 2028 (part in Istanbul) TxDataNonZeroGasEIP2028 uint64 = 16 // Per byte of non zero data attached to a transaction after EIP 2028 (part in Istanbul)
TxTokenPerNonZeroByte uint64 = 4 // Token cost per non-zero byte as specified by EIP-7623.
TxCostFloorPerToken uint64 = 10 // Cost floor per byte of data as specified by EIP-7623.
TxAccessListAddressGas uint64 = 2400 // Per address specified in EIP 2930 access list TxAccessListAddressGas uint64 = 2400 // Per address specified in EIP 2930 access list
TxAccessListStorageKeyGas uint64 = 1900 // Per storage key specified in EIP 2930 access list TxAccessListStorageKeyGas uint64 = 1900 // Per storage key specified in EIP 2930 access list
TxAuthTupleGas uint64 = 12500 // Per auth tuple code specified in EIP-7702 TxAuthTupleGas uint64 = 12500 // Per auth tuple code specified in EIP-7702
@ -168,14 +174,27 @@ const (
BlobTxBlobGaspriceUpdateFraction = 5007716 // Controls the maximum rate of change for blob gas price, using Prague parameters BlobTxBlobGaspriceUpdateFraction = 5007716 // Controls the maximum rate of change for blob gas price, using Prague parameters
BlobTxTargetBlobGasPerBlock = 6 * BlobTxBlobGasPerBlob // Target consumable blob gas for data blobs per block (for 1559-like pricing), using Prague parameters BlobTxTargetBlobGasPerBlock = 6 * BlobTxBlobGasPerBlob // Target consumable blob gas for data blobs per block (for 1559-like pricing), using Prague parameters
HistoryServeWindow = 8192 // Number of blocks to serve historical block hashes for, EIP-2935.
) )
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations // Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations
var Bls12381MultiExpDiscountTable = [128]uint64{1200, 888, 764, 641, 594, 547, 500, 453, 438, 423, 408, 394, 379, 364, 349, 334, 330, 326, 322, 318, 314, 310, 306, 302, 298, 294, 289, 285, 281, 277, 273, 269, 268, 266, 265, 263, 262, 260, 259, 257, 256, 254, 253, 251, 250, 248, 247, 245, 244, 242, 241, 239, 238, 236, 235, 233, 232, 231, 229, 228, 226, 225, 223, 222, 221, 220, 219, 219, 218, 217, 216, 216, 215, 214, 213, 213, 212, 211, 211, 210, 209, 208, 208, 207, 206, 205, 205, 204, 203, 202, 202, 201, 200, 199, 199, 198, 197, 196, 196, 195, 194, 193, 193, 192, 191, 191, 190, 189, 188, 188, 187, 186, 185, 185, 184, 183, 182, 182, 181, 180, 179, 179, 178, 177, 176, 176, 175, 174} var Bls12381MultiExpDiscountTable = [128]uint64{1200, 888, 764, 641, 594, 547, 500, 453, 438, 423, 408, 394, 379, 364, 349, 334, 330, 326, 322, 318, 314, 310, 306, 302, 298, 294, 289, 285, 281, 277, 273, 269, 268, 266, 265, 263, 262, 260, 259, 257, 256, 254, 253, 251, 250, 248, 247, 245, 244, 242, 241, 239, 238, 236, 235, 233, 232, 231, 229, 228, 226, 225, 223, 222, 221, 220, 219, 219, 218, 217, 216, 216, 215, 214, 213, 213, 212, 211, 211, 210, 209, 208, 208, 207, 206, 205, 205, 204, 203, 202, 202, 201, 200, 199, 199, 198, 197, 196, 196, 195, 194, 193, 193, 192, 191, 191, 190, 189, 188, 188, 187, 186, 185, 185, 184, 183, 182, 182, 181, 180, 179, 179, 178, 177, 176, 176, 175, 174}
// Difficulty parameters.
var ( var (
DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations. DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations.
GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block. GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
) )
// System contracts.
var (
// SystemAddress is where the system-transaction is sent from as per EIP-4788
SystemAddress = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
// EIP-2935 - Serve historical block hashes from state
HistoryStorageAddress = common.HexToAddress("0x0000F90827F1C53a10cb7A02335B175320002935")
HistoryStorageCode = common.FromHex("3373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500")
)

View file

@ -24,7 +24,7 @@ import (
const ( const (
VersionMajor = 5 // Major version component of the current release VersionMajor = 5 // Major version component of the current release
VersionMinor = 8 // Minor version component of the current release VersionMinor = 8 // Minor version component of the current release
VersionPatch = 53 // Patch version component of the current release VersionPatch = 54 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string VersionMeta = "mainnet" // Version metadata to append to the version string
) )