Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,6 @@ var (
utils.DARecoverySignBlocksFlag,
utils.DARecoveryL2EndBlockFlag,
utils.DARecoveryProduceBlocksFlag,
utils.L2BaseFeeScalarFlag,
utils.L2BaseFeeOverheadFlag,
}

rpcFlags = []cli.Flag{
Expand Down
2 changes: 0 additions & 2 deletions cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,6 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.L1DeploymentBlockFlag,
utils.L1DisableMessageQueueV2Flag,
utils.RollupVerifyEnabledFlag,
utils.L2BaseFeeScalarFlag,
utils.L2BaseFeeOverheadFlag,
utils.DASyncEnabledFlag,
utils.DABlobScanAPIEndpointFlag,
utils.DABlockNativeAPIEndpointFlag,
Expand Down
37 changes: 0 additions & 37 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import (
"github.com/scroll-tech/go-ethereum/consensus"
"github.com/scroll-tech/go-ethereum/consensus/clique"
"github.com/scroll-tech/go-ethereum/consensus/ethash"
"github.com/scroll-tech/go-ethereum/consensus/misc"
"github.com/scroll-tech/go-ethereum/core"
"github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/vm"
Expand Down Expand Up @@ -935,18 +934,6 @@ var (
Name: "da.recovery.produceblocks",
Usage: "Produce unsigned blocks after L1 recovery for permissionless batch submission",
}

// L2 base fee settings
L2BaseFeeScalarFlag = BigFlag{
Name: "basefee.scalar",
Usage: "Scalar used in the l2 base fee formula. Signer nodes will use this for computing the next block's base fee. Follower nodes will use this in RPC.",
Value: misc.DefaultBaseFeeScalar,
}
L2BaseFeeOverheadFlag = BigFlag{
Name: "basefee.overhead",
Usage: "Overhead used in the l2 base fee formula. Signer nodes will use this for computing the next block's base fee. Follower nodes will use this in RPC.",
Value: misc.DefaultBaseFeeOverhead,
}
)

// MakeDataDir retrieves the currently requested data directory, terminating
Expand Down Expand Up @@ -1722,29 +1709,6 @@ func setDA(ctx *cli.Context, cfg *ethconfig.Config) {
}
}

func setBaseFee(ctx *cli.Context, cfg *ethconfig.Config) {
cfg.BaseFeeScalar = misc.DefaultBaseFeeScalar
if ctx.GlobalIsSet(L2BaseFeeScalarFlag.Name) {
cfg.BaseFeeScalar = GlobalBig(ctx, L2BaseFeeScalarFlag.Name)
}
cfg.BaseFeeOverhead = misc.DefaultBaseFeeOverhead
if ctx.GlobalIsSet(L2BaseFeeOverheadFlag.Name) {
cfg.BaseFeeOverhead = GlobalBig(ctx, L2BaseFeeOverheadFlag.Name)
}

log.Info("L2 base fee coefficients", "scalar", cfg.BaseFeeScalar, "overhead", cfg.BaseFeeOverhead)

var minBaseFee uint64
if fee := misc.MinBaseFee(cfg.BaseFeeScalar, cfg.BaseFeeOverhead); fee.IsUint64() {
minBaseFee = fee.Uint64()
}

if cfg.TxPool.PriceLimit < minBaseFee {
log.Warn("Updating txpool price limit to min L2 base fee", "provided", cfg.TxPool.PriceLimit, "updated", minBaseFee)
cfg.TxPool.PriceLimit = minBaseFee
}
}

func setMaxBlockRange(ctx *cli.Context, cfg *ethconfig.Config) {
if ctx.GlobalIsSet(MaxBlockRangeFlag.Name) {
cfg.MaxBlockRange = ctx.GlobalInt64(MaxBlockRangeFlag.Name)
Expand Down Expand Up @@ -1821,7 +1785,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
setCircuitCapacityCheck(ctx, cfg)
setEnableRollupVerify(ctx, cfg)
setDA(ctx, cfg)
setBaseFee(ctx, cfg)
setMaxBlockRange(ctx, cfg)
if ctx.GlobalIsSet(ShadowforkPeersFlag.Name) {
cfg.ShadowForkPeerIDs = ctx.GlobalStringSlice(ShadowforkPeersFlag.Name)
Expand Down
53 changes: 37 additions & 16 deletions consensus/misc/eip1559.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ package misc
import (
"fmt"
"math/big"
"sync"

"github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/params"
)

Expand All @@ -33,11 +35,35 @@ const MaximumL2BaseFee = 10000000000
// `scalar` accounts for finalization costs. `overhead` accounts for sequencing and proving costs.
// we use 1e18 for precision to match the contract implementation.
var (
BaseFeePrecision = new(big.Int).SetUint64(1e18)
DefaultBaseFeeScalar = new(big.Int).SetUint64(34000000000000)
DefaultBaseFeeOverhead = new(big.Int).SetUint64(15680000)
BaseFeePrecision = new(big.Int).SetUint64(1e18)

// scalar and overhead are updated automatically in `Blockchain.writeBlockWithState`.
baseFeeScalar = big.NewInt(0)
baseFeeOverhead = big.NewInt(0)

lock sync.RWMutex
)

func UpdateL2BaseFeeOverhead(newOverhead *big.Int) {
if newOverhead == nil {
log.Error("Failed to set L2 base fee overhead, new value is <nil>")
return
}
lock.Lock()
defer lock.Unlock()
baseFeeOverhead.Set(newOverhead)
}

func UpdateL2BaseFeeScalar(newScalar *big.Int) {
if newScalar == nil {
log.Error("Failed to set L2 base fee scalar, new value is <nil>")
return
}
lock.Lock()
defer lock.Unlock()
baseFeeScalar.Set(newScalar)
}

// VerifyEip1559Header verifies some header attributes which were changed in EIP-1559,
// - gas limit check
// - basefee check
Expand Down Expand Up @@ -65,21 +91,16 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header, parentL1BaseF
return big.NewInt(10000000) // 0.01 Gwei
}

scalar := config.Scroll.BaseFeeScalar
if scalar == nil {
scalar = DefaultBaseFeeScalar
}
overhead := config.Scroll.BaseFeeOverhead
if overhead == nil {
overhead = DefaultBaseFeeOverhead
}

return calcBaseFee(scalar, overhead, parentL1BaseFee)
lock.RLock()
defer lock.RUnlock()
return calcBaseFee(baseFeeScalar, baseFeeOverhead, parentL1BaseFee)
}

// MinBaseFee calculates the minimum L2 base fee based on the configured coefficients.
func MinBaseFee(scalar, overhead *big.Int) *big.Int {
return calcBaseFee(scalar, overhead, big.NewInt(0))
// MinBaseFee calculates the minimum L2 base fee based on the current coefficients.
func MinBaseFee() *big.Int {
lock.RLock()
defer lock.RUnlock()
return calcBaseFee(baseFeeScalar, baseFeeOverhead, big.NewInt(0))
}

func calcBaseFee(scalar, overhead, parentL1BaseFee *big.Int) *big.Int {
Expand Down
14 changes: 10 additions & 4 deletions consensus/misc/eip1559_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ func TestCalcBaseFee(t *testing.T) {
}
for i, test := range tests {
config := config()
config.Scroll.BaseFeeScalar = big.NewInt(10000000)
config.Scroll.BaseFeeOverhead = big.NewInt(1)
UpdateL2BaseFeeScalar(big.NewInt(10000000))
UpdateL2BaseFeeOverhead(big.NewInt(1))
if have, want := CalcBaseFee(config, nil, big.NewInt(test.parentL1BaseFee)), big.NewInt(test.expectedL2BaseFee); have.Cmp(want) != 0 {
t.Errorf("test %d: have %d want %d, ", i, have, want)
}
Expand All @@ -142,6 +142,8 @@ func TestCalcBaseFee(t *testing.T) {
{644149677419355, 10000000000}, // cap at max L2 base fee
}
for i, test := range testsWithDefaults {
UpdateL2BaseFeeScalar(big.NewInt(34000000000000))
UpdateL2BaseFeeOverhead(big.NewInt(15680000))
if have, want := CalcBaseFee(config(), nil, big.NewInt(test.parentL1BaseFee)), big.NewInt(test.expectedL2BaseFee); have.Cmp(want) != 0 {
t.Errorf("test %d: have %d want %d, ", i, have, want)
}
Expand All @@ -150,11 +152,15 @@ func TestCalcBaseFee(t *testing.T) {

// TestMinBaseFee assumes all blocks are 1559-blocks
func TestMinBaseFee(t *testing.T) {
if have, want := MinBaseFee(DefaultBaseFeeScalar, DefaultBaseFeeOverhead), big.NewInt(15680000); have.Cmp(want) != 0 {
UpdateL2BaseFeeScalar(big.NewInt(34000000000000))
UpdateL2BaseFeeOverhead(big.NewInt(15680000))
if have, want := MinBaseFee(), big.NewInt(15680000); have.Cmp(want) != 0 {
t.Errorf("have %d want %d, ", have, want)
}

if have, want := MinBaseFee(big.NewInt(10000000), big.NewInt(1)), big.NewInt(1); have.Cmp(want) != 0 {
UpdateL2BaseFeeScalar(big.NewInt(10000000))
UpdateL2BaseFeeOverhead(big.NewInt(1))
if have, want := MinBaseFee(), big.NewInt(1); have.Cmp(want) != 0 {
t.Errorf("have %d want %d, ", have, want)
}
}
33 changes: 32 additions & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/scroll-tech/go-ethereum/common/mclock"
"github.com/scroll-tech/go-ethereum/common/prque"
"github.com/scroll-tech/go-ethereum/consensus"
"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/state/snapshot"
Expand All @@ -45,6 +46,7 @@ import (
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/metrics"
"github.com/scroll-tech/go-ethereum/params"
"github.com/scroll-tech/go-ethereum/rollup/rcfg"
"github.com/scroll-tech/go-ethereum/trie"
)

Expand All @@ -55,7 +57,8 @@ var (
headTimeGapGauge = metrics.NewRegisteredGauge("chain/head/timegap", nil)
headL1MessageGauge = metrics.NewRegisteredGauge("chain/head/l1msg", nil)

l2BaseFeeGauge = metrics.NewRegisteredGauge("chain/fees/l2basefee", nil)
l2BaseFeeGauge = metrics.NewRegisteredGauge("chain/fees/l2basefee", nil)
l2BaseFeeUpdateTimer = metrics.NewRegisteredTimer("chain/fees/updates", nil)

accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
Expand Down Expand Up @@ -1269,6 +1272,34 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
l2BaseFeeGauge.Update(0)
}

// Update L2 base fee coefficients.
// Coefficient updates are written into L2 state and emit an event.
// We could use either here; we read from the event to avoid state reads.
// In the future, if the base fee setting becomes part of block validation,
// reading from state will be more appropriate.
l2SystemConfigAddress := bc.Config().Scroll.L2SystemConfigAddress()
start := time.Now()

for _, r := range logs {
if r.Address != l2SystemConfigAddress {
continue
}
switch r.Topics[0] {
case rcfg.BaseFeeOverheadUpdatedTopic:
old := r.Topics[1].Big()
new := r.Topics[2].Big()
misc.UpdateL2BaseFeeOverhead(new)
log.Info("Updated L2 base fee overhead", "blockNumber", block.NumberU64(), "blockHash", block.Hash().Hex(), "old", old, "new", new)
case rcfg.BaseFeeScalarUpdatedTopic:
old := r.Topics[1].Big()
new := r.Topics[2].Big()
misc.UpdateL2BaseFeeScalar(new)
log.Info("Updated L2 base fee scalar", "blockNumber", block.NumberU64(), "blockHash", block.Hash().Hex(), "old", old, "new", new)
}
}

l2BaseFeeUpdateTimer.Update(time.Since(start))

// Note the latest relayed L1 message queue index (if any)
updateHeadL1msgGauge(block)

Expand Down
4 changes: 2 additions & 2 deletions core/state_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,13 +389,13 @@ func TestStateProcessorErrors(t *testing.T) {
txs: []*types.Transaction{
mkDynamicCreationTx(0, 500000, common.Big0, misc.CalcBaseFee(config, genesis.Header(), parentL1BaseFee), tooBigInitCode[:]),
},
want: "could not apply tx 0 [0x9fff9d187a68f9dce9664475ed9a01a5178992f15b44ce88ee7b1129a183e6af]: max initcode size exceeded: code size 49153 limit 49152",
want: "could not apply tx 0 [0x7b33776d375660694a23ef992c090265682f3687607e0099b14503fdb65d73e3]: max initcode size exceeded: code size 49153 limit 49152",
},
{ // ErrIntrinsicGas: Not enough gas to cover init code
txs: []*types.Transaction{
mkDynamicCreationTx(0, 54299, common.Big0, misc.CalcBaseFee(config, genesis.Header(), parentL1BaseFee), smallInitCode[:]),
},
want: "could not apply tx 0 [0x272eefb0eeb3b973e933ae5dba17e7ecf6bfded5ce358f2a78426153c247f677]: intrinsic gas too low: have 54299, want 54300",
want: "could not apply tx 0 [0x98e54c5ecfa7986a66480d65ba32f2c6a2a6aedc3a67abb91b1e118b0717ed2d]: intrinsic gas too low: have 54299, want 54300",
},
} {
block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config)
Expand Down
9 changes: 9 additions & 0 deletions core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,8 @@ func (pool *TxPool) loop() {
journal = time.NewTicker(pool.config.Rejournal)
// Track the previous head headers for transaction reorgs
head = pool.chain.CurrentBlock()
// Track the min L2 base fee
minBaseFee = big.NewInt(0)
)
defer report.Stop()
defer evict.Stop()
Expand All @@ -443,6 +445,13 @@ func (pool *TxPool) loop() {
}
}

newMinBaseFee := misc.MinBaseFee()
if minBaseFee.Cmp(newMinBaseFee) != 0 {
log.Trace("Updating min base fee", "old", minBaseFee, "new", newMinBaseFee)
minBaseFee = newMinBaseFee
pool.SetGasPrice(minBaseFee)
}

// System shutdown.
case <-pool.chainHeadSub.Err():
close(pool.reorgShutdownCh)
Expand Down
42 changes: 35 additions & 7 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/scroll-tech/go-ethereum/common/hexutil"
"github.com/scroll-tech/go-ethereum/consensus"
"github.com/scroll-tech/go-ethereum/consensus/clique"
"github.com/scroll-tech/go-ethereum/consensus/misc"
"github.com/scroll-tech/go-ethereum/consensus/system_contract"
"github.com/scroll-tech/go-ethereum/consensus/wrapper"
"github.com/scroll-tech/go-ethereum/core"
Expand Down Expand Up @@ -60,6 +61,7 @@ import (
"github.com/scroll-tech/go-ethereum/rollup/ccc"
"github.com/scroll-tech/go-ethereum/rollup/da_syncer"
"github.com/scroll-tech/go-ethereum/rollup/l1"
"github.com/scroll-tech/go-ethereum/rollup/rcfg"
"github.com/scroll-tech/go-ethereum/rollup/rollup_sync_service"
"github.com/scroll-tech/go-ethereum/rollup/sync_service"
"github.com/scroll-tech/go-ethereum/rpc"
Expand Down Expand Up @@ -148,13 +150,6 @@ func New(stack *node.Node, config *ethconfig.Config, l1Client l1.Client) (*Ether
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
return nil, genesisErr
}

// Hacky workaround:
// It's hard to pass these fields to `CalcBaseFee`, etc.
// So pass them as part of the genesis config instead.
chainConfig.Scroll.BaseFeeScalar = config.BaseFeeScalar
chainConfig.Scroll.BaseFeeOverhead = config.BaseFeeOverhead

log.Info("Initialised chain configuration", "config", chainConfig)

if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil {
Expand Down Expand Up @@ -220,6 +215,8 @@ func New(stack *node.Node, config *ethconfig.Config, l1Client l1.Client) (*Ether
eth.blockchain.Validator().WithAsyncValidator(eth.asyncChecker.Check)
}

initializeL2BaseFeeCoefficients(chainConfig, eth.blockchain)

// Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
Expand Down Expand Up @@ -353,6 +350,37 @@ func makeExtraData(extra []byte) []byte {
return extra
}

func initializeL2BaseFeeCoefficients(chainConfig *params.ChainConfig, blockchain *core.BlockChain) error {
state, err := blockchain.State()
if err != nil {
return err
}

l2BaseFeeOverhead := common.Big0
l2BaseFeeScalar := common.Big0

if l2SystemConfig := chainConfig.Scroll.L2SystemConfigAddress(); l2SystemConfig != (common.Address{}) {
l2BaseFeeOverhead = state.GetState(l2SystemConfig, rcfg.L2BaseFeeOverheadSlot).Big()
l2BaseFeeScalar = state.GetState(l2SystemConfig, rcfg.L2BaseFeeScalarSlot).Big()
} else {
log.Warn("L2SystemConfig address is not configured")
}

// fallback to default if contract is not deployed or configured yet
if l2BaseFeeOverhead.Cmp(common.Big0) == 0 {
l2BaseFeeOverhead = big.NewInt(15680000)
}
if l2BaseFeeScalar.Cmp(common.Big0) == 0 {
l2BaseFeeScalar = big.NewInt(34000000000000)
}

// update local view of coefficients
misc.UpdateL2BaseFeeOverhead(l2BaseFeeOverhead)
misc.UpdateL2BaseFeeScalar(l2BaseFeeScalar)
log.Info("Initialized L2 base fee coefficients", "overhead", l2BaseFeeOverhead, "scalar", l2BaseFeeScalar)
return nil
}

// APIs return the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else.
func (s *Ethereum) APIs() []rpc.API {
Expand Down
4 changes: 0 additions & 4 deletions eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,6 @@ type Config struct {

// DA syncer options
DA da_syncer.Config

// L2 base fee coefficients for the formula: `l2BaseFee = (l1BaseFee * scalar) / PRECISION + overhead`.
BaseFeeScalar *big.Int
BaseFeeOverhead *big.Int
}

// CreateConsensusEngine creates a consensus engine for the given chain configuration.
Expand Down
Loading
Loading