mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
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 commita223efc* eip-7623: manually cherry-pick upstream commit0e1a19d* add note about L1 messages * nit * add history storage to dev genesis * EIP-2935: adopt tracer changes from upstreama223efcf* remove todos * update protocol params * add block hash to witness, plus various cleanups
This commit is contained in:
parent
00c5c2bd3e
commit
5148229082
26 changed files with 393 additions and 48 deletions
|
|
@ -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 {
|
||||
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 {
|
||||
msg, err := tx.AsMessage(signer, pre.Env.BaseFee)
|
||||
|
|
|
|||
|
|
@ -140,15 +140,29 @@ func Transaction(ctx *cli.Context) error {
|
|||
r.Address = sender
|
||||
}
|
||||
// Check intrinsic gas
|
||||
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil,
|
||||
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int))); err != nil {
|
||||
rules := chainConfig.Rules(common.Big0, 0)
|
||||
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
|
||||
results = append(results, r)
|
||||
continue
|
||||
} else {
|
||||
r.IntrinsicGas = gas
|
||||
if tx.Gas() < gas {
|
||||
r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), gas)
|
||||
}
|
||||
r.IntrinsicGas = gas
|
||||
if tx.Gas() < gas {
|
||||
r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), gas)
|
||||
results = append(results, r)
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,10 @@ var (
|
|||
// than required to start the invocation.
|
||||
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
|
||||
// current network configuration.
|
||||
ErrTxTypeNotSupported = types.ErrTxTypeNotSupported
|
||||
|
|
|
|||
|
|
@ -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{8}): {Balance: big.NewInt(1)}, // ECPairing
|
||||
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
|
||||
faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 250), big.NewInt(9))},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -167,6 +167,11 @@ func (s *StateDB) WithWitness(witness *stateless.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
|
||||
// state trie concurrently while the state is mutated so that when we reach the
|
||||
// commit phase, most of the needed data is already hot.
|
||||
|
|
|
|||
|
|
@ -94,6 +94,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||
blockContext := NewEVMBlockContext(header, p.bc, p.config, nil)
|
||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
|
||||
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
|
||||
for i, tx := range block.Transactions() {
|
||||
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)
|
||||
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
|
||||
¶ms.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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package core
|
|||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/binary"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
|
|
@ -31,9 +32,11 @@ import (
|
|||
"github.com/scroll-tech/go-ethereum/consensus/ethash"
|
||||
"github.com/scroll-tech/go-ethereum/consensus/misc"
|
||||
"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/vm"
|
||||
"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/trie"
|
||||
)
|
||||
|
|
@ -64,6 +67,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||
DarwinV2Time: new(uint64),
|
||||
EuclidTime: new(uint64),
|
||||
EuclidV2Time: new(uint64),
|
||||
FeynmanTime: new(uint64),
|
||||
Ethash: new(params.EthashConfig),
|
||||
}
|
||||
signer = types.LatestSigner(config)
|
||||
|
|
@ -387,9 +391,9 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||
}{
|
||||
{ // ErrMaxInitCodeSizeExceeded
|
||||
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
|
||||
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
|
||||
return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil))
|
||||
}
|
||||
|
||||
func TestProcessParentBlockHash(t *testing.T) {
|
||||
var (
|
||||
chainConfig = ¶ms.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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"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
|
||||
if dataLen > 0 {
|
||||
// Zero and non-zero bytes are priced differently
|
||||
var nz uint64
|
||||
for _, byt := range data {
|
||||
if byt != 0 {
|
||||
nz++
|
||||
}
|
||||
}
|
||||
z := uint64(bytes.Count(data, []byte{0}))
|
||||
nz := dataLen - z
|
||||
|
||||
// Make sure we don't exceed uint64 for all data combinations
|
||||
nonZeroGas := params.TxDataNonZeroGasFrontier
|
||||
if isEIP2028 {
|
||||
|
|
@ -157,7 +155,6 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
|
|||
}
|
||||
gas += nz * nonZeroGas
|
||||
|
||||
z := dataLen - nz
|
||||
if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
|
@ -181,6 +178,21 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
|
|||
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.
|
||||
func toWordSize(size uint64) uint64 {
|
||||
if size > math.MaxUint64-31 {
|
||||
|
|
@ -380,16 +392,30 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||
sender = vm.AccountRef(msg.From())
|
||||
rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Time.Uint64())
|
||||
contractCreation = msg.To() == nil
|
||||
floorDataGas uint64
|
||||
)
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
// Note: The L1 message queue contract ensures that this cannot happen for L1 messages.
|
||||
return nil, err
|
||||
}
|
||||
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)
|
||||
}
|
||||
// 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
|
||||
|
||||
// Check clause 6
|
||||
|
|
@ -455,13 +481,16 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
if !rules.IsLondon {
|
||||
// Before EIP-3529: refunds were capped to gasUsed / 2
|
||||
st.refundGas(params.RefundQuotient)
|
||||
} else {
|
||||
// After EIP-3529: refunds are capped to gasUsed / 5
|
||||
st.refundGas(params.RefundQuotientEIP3529)
|
||||
// Compute refund counter, capped to a refund quotient.
|
||||
st.gas += st.calcRefund()
|
||||
if rules.IsFeynman {
|
||||
// After EIP-7623: Data-heavy transactions pay the floor gas.
|
||||
if st.gasUsed() < floorDataGas {
|
||||
st.gas = st.initialGas - floorDataGas
|
||||
}
|
||||
}
|
||||
st.returnGas()
|
||||
|
||||
effectiveTip := st.gasPrice
|
||||
|
||||
// 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}
|
||||
}
|
||||
|
||||
func (st *StateTransition) refundGas(refundQuotient uint64) {
|
||||
// Apply refund counter, capped to a refund quotient
|
||||
refund := st.gasUsed() / refundQuotient
|
||||
// calcRefund computes refund counter, capped to a refund quotient.
|
||||
func (st *StateTransition) calcRefund() uint64 {
|
||||
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() {
|
||||
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.
|
||||
remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
|
||||
st.state.AddBalance(st.msg.From(), remaining)
|
||||
|
|
|
|||
|
|
@ -297,6 +297,7 @@ type TxPool struct {
|
|||
eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions.
|
||||
shanghai bool // Fork indicator whether we are in the Shanghai stage.
|
||||
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
|
||||
currentHead *big.Int // Current blockchain head
|
||||
|
|
@ -855,6 +856,16 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
|||
if tx.Gas() < intrGas {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -1583,6 +1594,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
|
|||
pool.eip1559 = pool.chainconfig.IsCurie(next)
|
||||
pool.shanghai = pool.chainconfig.IsShanghai(next)
|
||||
pool.eip7702 = pool.chainconfig.IsEuclidV2(newHead.Time)
|
||||
pool.feynman = pool.chainconfig.IsFeynman(newHead.Time)
|
||||
|
||||
// Update current head
|
||||
pool.currentHead = next
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
|
|||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
|
||||
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: false},
|
||||
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{6}): &bn256AddIstanbul{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: false},
|
||||
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{6}): &bn256AddIstanbul{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: true},
|
||||
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{6}): &bn256AddIstanbul{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{limitInputLength: true},
|
||||
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{6}): &bn256AddIstanbul{},
|
||||
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{0x01, 0x00}): &p256Verify{},
|
||||
}
|
||||
|
|
@ -156,6 +171,7 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
|
|||
}
|
||||
|
||||
var (
|
||||
PrecompiledAddressesFeynman []common.Address
|
||||
PrecompiledAddressesEuclidV2 []common.Address
|
||||
PrecompiledAddressesBernoulli []common.Address
|
||||
PrecompiledAddressesArchimedes []common.Address
|
||||
|
|
@ -187,11 +203,16 @@ func init() {
|
|||
for k := range PrecompiledContractsEuclidV2 {
|
||||
PrecompiledAddressesEuclidV2 = append(PrecompiledAddressesEuclidV2, k)
|
||||
}
|
||||
for k := range PrecompiledContractsFeynman {
|
||||
PrecompiledAddressesFeynman = append(PrecompiledAddressesFeynman, k)
|
||||
}
|
||||
}
|
||||
|
||||
// ActivePrecompiles returns the precompiles enabled with the current configuration.
|
||||
func ActivePrecompiles(rules params.Rules) []common.Address {
|
||||
switch {
|
||||
case rules.IsFeynman:
|
||||
return PrecompiledAddressesFeynman
|
||||
case rules.IsEuclidV2:
|
||||
return PrecompiledAddressesEuclidV2
|
||||
case rules.IsBernoulli:
|
||||
|
|
@ -600,10 +621,6 @@ var (
|
|||
// runBn256Pairing implements the Bn256Pairing precompile, referenced by both
|
||||
// Byzantium and Istanbul operations.
|
||||
func runBn256Pairing(input []byte) ([]byte, error) {
|
||||
// Allow at most 4 inputs
|
||||
if len(input) > 4*192 {
|
||||
return nil, errBadPairingInput
|
||||
}
|
||||
// Handle some corner cases cheaply
|
||||
if len(input)%192 > 0 {
|
||||
return nil, errBadPairingInput
|
||||
|
|
@ -634,7 +651,9 @@ func runBn256Pairing(input []byte) ([]byte, error) {
|
|||
|
||||
// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve
|
||||
// conforming to Istanbul consensus rules.
|
||||
type bn256PairingIstanbul struct{}
|
||||
type bn256PairingIstanbul struct {
|
||||
limitInputLength bool
|
||||
}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
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) {
|
||||
if c.limitInputLength {
|
||||
// Allow at most 4 inputs
|
||||
if len(input) > 4*192 {
|
||||
return nil, errBadPairingInput
|
||||
}
|
||||
}
|
||||
|
||||
return runBn256Pairing(input)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
|
|||
common.BytesToAddress([]byte{16}): &bls12381Pairing{},
|
||||
common.BytesToAddress([]byte{17}): &bls12381MapG1{},
|
||||
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
|
||||
common.BytesToAddress([]byte{0xf8}): &bn256PairingIstanbul{limitInputLength: true},
|
||||
|
||||
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.
|
||||
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 TestPrecompiledBlake2F(t *testing.T) { testJson("blake2F", "09", t) }
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ type (
|
|||
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
||||
var precompiles map[common.Address]PrecompiledContract
|
||||
switch {
|
||||
case evm.chainRules.IsFeynman:
|
||||
precompiles = PrecompiledContractsFeynman
|
||||
case evm.chainRules.IsEuclidV2:
|
||||
precompiles = PrecompiledContractsEuclidV2
|
||||
case evm.chainRules.IsBernoulli:
|
||||
|
|
|
|||
|
|
@ -470,6 +470,32 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
|
|||
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) {
|
||||
scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.FeeRecipient().Bytes()))
|
||||
return nil, nil
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"math/big"
|
||||
|
||||
"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/params"
|
||||
)
|
||||
|
|
@ -85,6 +86,8 @@ type StateDB interface {
|
|||
AddPreimage(common.Hash, []byte)
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
|
|||
if cfg.JumpTable[STOP] == nil {
|
||||
var jt JumpTable
|
||||
switch {
|
||||
case evm.chainRules.IsFeynman:
|
||||
jt = feynmanInstructionSet
|
||||
case evm.chainRules.IsEuclidV2:
|
||||
jt = euclidV2InstructionSet
|
||||
case evm.chainRules.IsDarwin:
|
||||
|
|
|
|||
|
|
@ -62,11 +62,24 @@ var (
|
|||
curieInstructionSet = newCurieInstructionSet()
|
||||
darwinInstructionSet = newDarwinInstructionSet()
|
||||
euclidV2InstructionSet = newEuclidV2InstructionSet()
|
||||
feynmanInstructionSet = newFeynmanInstructionSet()
|
||||
)
|
||||
|
||||
// JumpTable contains the EVM opcodes supported at a given fork.
|
||||
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,
|
||||
// contantinople, istanbul, petersburg, berlin, london, shanghai, curie, darwin and euclidV2 instructions.
|
||||
func newEuclidV2InstructionSet() JumpTable {
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ func setDefaults(cfg *Config) {
|
|||
CurieBlock: new(big.Int),
|
||||
DarwinTime: new(uint64),
|
||||
DarwinV2Time: new(uint64),
|
||||
EuclidV2Time: new(uint64),
|
||||
FeynmanTime: new(uint64),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -337,17 +337,13 @@ func TestBlockhash(t *testing.T) {
|
|||
if zero.BitLen() != 0 {
|
||||
t.Fatalf("expected zeroes, got %x", ret[0:32])
|
||||
}
|
||||
firstExpectedHash := new(big.Int)
|
||||
firstExpectedHash.SetString("13215081625009140218242111988507489764601005198286886925088730931502473149599", 10)
|
||||
if first.Uint64() != firstExpectedHash.Uint64() {
|
||||
t.Fatalf("first hash should be 13215081625009140218242111988507489764601005198286886925088730931502473149599, got %d (%x)", first, ret[32:64])
|
||||
if first.Uint64() != 999 {
|
||||
t.Fatalf("second block should be 999, got %d (%x)", first, ret[32:64])
|
||||
}
|
||||
lastExpectedHash := new(big.Int)
|
||||
lastExpectedHash.SetString("2851160567348483005169712516804956111111231427377973738952179767509712807467", 10)
|
||||
if last.Uint64() != lastExpectedHash.Uint64() {
|
||||
t.Fatalf("last hash should be 2851160567348483005169712516804956111111231427377973738952179767509712807467, got %d (%x)", last, ret[64:96])
|
||||
if last.Uint64() != 744 {
|
||||
t.Fatalf("last block should be 744, 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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
core/vm/testdata/precompiles/bn256Pairing.json
vendored
14
core/vm/testdata/precompiles/bn256Pairing.json
vendored
|
|
@ -76,6 +76,20 @@
|
|||
"Gas": 113000,
|
||||
"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",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
|
|
|
|||
|
|
@ -176,6 +176,12 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec
|
|||
if err != nil {
|
||||
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 {
|
||||
return nil, vm.BlockContext{}, statedb, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,6 +277,11 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
|
|||
for task := range tasks {
|
||||
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)
|
||||
// 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
|
||||
for i, tx := range task.block.Transactions() {
|
||||
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)
|
||||
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() {
|
||||
var (
|
||||
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)
|
||||
}
|
||||
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()
|
||||
blockNumber := block.NumberU64()
|
||||
for th := 0; th < threads; th++ {
|
||||
|
|
@ -748,6 +763,13 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
|||
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() {
|
||||
// Prepare the trasaction for un-traced execution
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -627,15 +627,25 @@ func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorging bo
|
|||
|
||||
// handleForks
|
||||
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 {
|
||||
misc.ApplyCurieHardFork(w.current.state)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Stop/start miner at Euclid fork boundary on zktrie/mpt nodes
|
||||
if w.chainConfig.IsEuclid(w.current.header.Time) {
|
||||
parent := w.chain.GetBlockByHash(w.current.header.ParentHash)
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1404,6 +1404,7 @@ func TestEuclidV2TransitionVerification(t *testing.T) {
|
|||
chainConfig := params.AllCliqueProtocolChanges.Clone()
|
||||
chainConfig.EuclidTime = newUint64(0)
|
||||
chainConfig.EuclidV2Time = newUint64(10000)
|
||||
chainConfig.FeynmanTime = nil
|
||||
chainConfig.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000}
|
||||
chainConfig.SystemContract = ¶ms.SystemContractConfig{Period: 1}
|
||||
|
||||
|
|
|
|||
|
|
@ -330,6 +330,7 @@ var (
|
|||
DarwinV2Time: newUint64(1724832000),
|
||||
EuclidTime: newUint64(1741680000),
|
||||
EuclidV2Time: newUint64(1741852800),
|
||||
FeynmanTime: nil,
|
||||
Clique: &CliqueConfig{
|
||||
Period: 3,
|
||||
Epoch: 30000,
|
||||
|
|
@ -381,6 +382,7 @@ var (
|
|||
DarwinV2Time: newUint64(1725264000),
|
||||
EuclidTime: newUint64(1744815600),
|
||||
EuclidV2Time: newUint64(1745305200),
|
||||
FeynmanTime: nil,
|
||||
Clique: &CliqueConfig{
|
||||
Period: 3,
|
||||
Epoch: 30000,
|
||||
|
|
@ -521,6 +523,7 @@ var (
|
|||
DarwinV2Time: new(uint64),
|
||||
EuclidTime: new(uint64),
|
||||
EuclidV2Time: new(uint64),
|
||||
FeynmanTime: new(uint64),
|
||||
TerminalTotalDifficulty: nil,
|
||||
Ethash: new(EthashConfig),
|
||||
Clique: nil,
|
||||
|
|
@ -662,6 +665,7 @@ type ChainConfig struct {
|
|||
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)
|
||||
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
|
||||
// the network that triggers the consensus upgrade.
|
||||
|
|
@ -852,7 +856,11 @@ func (c *ChainConfig) String() string {
|
|||
if c.EuclidV2Time != nil {
|
||||
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.HomesteadBlock,
|
||||
c.DAOForkBlock,
|
||||
|
|
@ -876,6 +884,7 @@ func (c *ChainConfig) String() string {
|
|||
darwinV2Time,
|
||||
euclidTime,
|
||||
euclidV2Time,
|
||||
feynmanTime,
|
||||
engine,
|
||||
c.Scroll,
|
||||
)
|
||||
|
|
@ -988,6 +997,11 @@ func (c *ChainConfig) IsEuclidV2(now uint64) bool {
|
|||
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.
|
||||
func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool {
|
||||
if c.TerminalTotalDifficulty == nil {
|
||||
|
|
@ -1201,6 +1215,7 @@ type Rules struct {
|
|||
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
|
||||
IsBerlin, IsLondon, IsArchimedes, IsShanghai bool
|
||||
IsBernoulli, IsCurie, IsDarwin, IsEuclid, IsEuclidV2 bool
|
||||
IsFeynman bool
|
||||
}
|
||||
|
||||
// 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),
|
||||
IsEuclid: c.IsEuclid(time),
|
||||
IsEuclidV2: c.IsEuclidV2(time),
|
||||
IsFeynman: c.IsFeynman(time),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,11 @@
|
|||
|
||||
package params
|
||||
|
||||
import "math/big"
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
)
|
||||
|
||||
const (
|
||||
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.
|
||||
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
|
||||
TxAccessListStorageKeyGas uint64 = 1900 // Per storage key specified in EIP 2930 access list
|
||||
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
|
||||
|
||||
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
|
||||
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 (
|
||||
DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations.
|
||||
GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block.
|
||||
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.
|
||||
)
|
||||
|
||||
// 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")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import (
|
|||
const (
|
||||
VersionMajor = 5 // Major 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
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue