feat(feynman): upgrade gas oracle predeploy (#1213)

* feat(feynman): upgrade gas oracle predeploy

* update execution witness

* prettify constants

* fix fork application order
This commit is contained in:
Péter Garamvölgyi 2025-06-25 13:22:25 +02:00 committed by GitHub
parent 02b33db0bf
commit a67863c655
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 115 additions and 26 deletions

View file

@ -152,6 +152,10 @@ 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 Feynman hard fork
if chainConfig.IsFeynmanTransitionBlock(pre.Env.Timestamp, pre.Env.ParentTimestamp) {
misc.ApplyFeynmanHardFork(statedb)
}
// Apply EIP-2935
if pre.Env.BlockHashes != nil && chainConfig.IsFeynman(pre.Env.Timestamp) {
var (

22
consensus/misc/feynman.go Normal file
View file

@ -0,0 +1,22 @@
package misc
import (
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/state"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/rollup/rcfg"
)
// ApplyFeynmanHardFork modifies the state database according to the Feynman hard-fork rules,
// updating the bytecode and storage of the L1GasPriceOracle contract.
func ApplyFeynmanHardFork(statedb *state.StateDB) {
log.Info("Applying Feynman hard fork")
// update contract byte code
statedb.SetCode(rcfg.L1GasPriceOracleAddress, rcfg.FeynmanL1GasPriceOracleBytecode)
// initialize new storage slots
statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.IsFeynmanSlot, common.BytesToHash([]byte{1}))
statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.PenaltyThresholdSlot, common.BigToHash(rcfg.InitialPenaltyThreshold))
statedb.SetState(rcfg.L1GasPriceOracleAddress, rcfg.PenaltyFactorSlot, common.BigToHash(rcfg.InitialPenaltyFactor))
}

View file

@ -249,6 +249,9 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if config.CurieBlock != nil && config.CurieBlock.Cmp(b.header.Number) == 0 {
misc.ApplyCurieHardFork(statedb)
}
if config.IsFeynmanTransitionBlock(b.Time(), parent.Time()) {
misc.ApplyFeynmanHardFork(statedb)
}
// Execute any user modifications to the block
if gen != nil {
gen(i, b)

View file

@ -91,6 +91,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if p.config.CurieBlock != nil && p.config.CurieBlock.Cmp(block.Number()) == 0 {
misc.ApplyCurieHardFork(statedb)
}
// Apply Feynman hard fork
parent := p.bc.GetHeaderByHash(block.ParentHash())
if p.config.IsFeynmanTransitionBlock(block.Time(), parent.Time) {
misc.ApplyFeynmanHardFork(statedb)
}
blockContext := NewEVMBlockContext(header, p.bc, p.config, nil)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
processorBlockTransactionGauge.Update(int64(block.Transactions().Len()))

View file

@ -362,6 +362,11 @@ func generateWitness(blockchain *core.BlockChain, block *types.Block) (*stateles
// Collect storage locations that prover needs but sequencer might not touch necessarily
statedb.GetState(rcfg.L2MessageQueueAddress, rcfg.WithdrawTrieRootSlot)
// Note: scroll-revm detects the Feynman transition block using this storage slot,
// since it does not have access to the parent block timestamp. We need to make
// sure that this is always present in the execution witness.
statedb.GetState(rcfg.L1GasPriceOracleAddress, rcfg.IsFeynmanSlot)
receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, *blockchain.GetVMConfig())
if err != nil {
return nil, fmt.Errorf("failed to process block %d: %w", block.Number(), err)

View file

@ -464,8 +464,7 @@ func (w *worker) collectPendingL1Messages(startIndex uint64) []types.L1MessageTx
}
// newWork
func (w *worker) newWork(now time.Time, parentHash common.Hash, reorging bool, reorgReason error) error {
parent := w.chain.GetBlockByHash(parentHash)
func (w *worker) newWork(now time.Time, parent *types.Block, reorging bool, reorgReason error) error {
header := &types.Header{
ParentHash: parent.Hash(),
Number: new(big.Int).Add(parent.Number(), common.Big1),
@ -586,13 +585,14 @@ func (w *worker) newWork(now time.Time, parentHash common.Hash, reorging bool, r
}
// tryCommitNewWork
func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorging bool, reorgReason error) (common.Hash, error) {
func (w *worker) tryCommitNewWork(now time.Time, parentHash common.Hash, reorging bool, reorgReason error) (common.Hash, error) {
parent := w.chain.GetBlockByHash(parentHash)
err := w.newWork(now, parent, reorging, reorgReason)
if err != nil {
return common.Hash{}, fmt.Errorf("failed creating new work: %w", err)
}
shouldCommit, err := w.handleForks()
shouldCommit, err := w.handleForks(parent)
if err != nil {
return common.Hash{}, fmt.Errorf("failed handling forks: %w", err)
}
@ -626,17 +626,16 @@ func (w *worker) tryCommitNewWork(now time.Time, parent common.Hash, reorging bo
}
// handleForks
func (w *worker) handleForks() (bool, error) {
func (w *worker) handleForks(parent *types.Block) (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 Feynman hard fork
if w.chainConfig.IsFeynmanTransitionBlock(w.current.header.Time, parent.Time()) {
misc.ApplyFeynmanHardFork(w.current.state)
}
// Apply EIP-2935
@ -646,6 +645,12 @@ func (w *worker) handleForks() (bool, error) {
core.ProcessParentBlockHash(w.current.header.ParentHash, vmenv, w.current.state)
}
// 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
}
return false, nil
}

View file

@ -1002,6 +1002,11 @@ func (c *ChainConfig) IsFeynman(now uint64) bool {
return isForkedTime(now, c.FeynmanTime)
}
// IsFeynmanTransitionBlock returns whether the given block timestamp corresponds to the first Feynman block.
func (c *ChainConfig) IsFeynmanTransitionBlock(blockTimestamp uint64, parentTimestamp uint64) bool {
return isForkedTime(blockTimestamp, c.FeynmanTime) && !isForkedTime(parentTimestamp, 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 {

View file

@ -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 = 57 // Patch version component of the current release
VersionPatch = 58 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string
)

File diff suppressed because one or more lines are too long