From 630a9f6f65f2e3b1d9c8a96cc84ea5a954706bdb Mon Sep 17 00:00:00 2001 From: Simon Oswald Date: Tue, 19 Dec 2023 13:06:49 +0100 Subject: [PATCH] load L1 fee hooks (#8) --- cmd/geth/config.go | 13 +++ cmd/geth/main.go | 3 + cmd/utils/flags.go | 12 +++ core/state_transition.go | 4 +- core/txpool/legacypool/legacypool.go | 106 ++++++++++++++++++++-- core/txpool/legacypool/legacypool_test.go | 29 +++++- core/txpool/legacypool/list.go | 9 +- core/txpool/legacypool/list_test.go | 4 +- core/txpool/validation.go | 18 +++- core/vm/interpreter.go | 5 +- go.mod | 6 +- go.sum | 7 +- params/config.go | 17 +++- 13 files changed, 209 insertions(+), 24 deletions(-) diff --git a/cmd/geth/config.go b/cmd/geth/config.go index a5d628d8af..d6dc8cab3c 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/accounts/usbwallet" "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/ethconfig" @@ -43,6 +44,7 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/naoina/toml" + "github.com/specularL2/specular/lib/el_golang_lib/hook" "github.com/urfave/cli/v2" ) @@ -178,6 +180,17 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { } backend, eth := utils.RegisterEthService(stack, &cfg.Eth) + // + log.Info("initializing specular hooks") + l2ChainId := ctx.Uint64(utils.NetworkIdFlag.Name) + l1FeeRecipient := backend.ChainConfig().L1FeeRecipient + if (l1FeeRecipient != common.Address{}) { + vm := eth.BlockChain().GetVMConfig() + vm.SpecularEVMPreTransferHook = hook.MakeSpecularEVMPreTransferHook(l2ChainId, l1FeeRecipient) + vm.SpecularL1FeeReader = hook.MakeSpecularL1FeeReader(l2ChainId) + } + // + // Create gauge with geth system and build information if eth != nil { // The 'eth' backend may be nil in light mode var protos []string diff --git a/cmd/geth/main.go b/cmd/geth/main.go index f6fa47ad2e..fd822e0427 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -71,6 +71,9 @@ var ( utils.TxPoolLocalsFlag, utils.TxPoolNoLocalsFlag, utils.TxPoolJournalFlag, + // + utils.TxPoolJournalRemotesFlag, + // utils.TxPoolRejournalFlag, utils.TxPoolPriceLimitFlag, utils.TxPoolPriceBumpFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index f5f131951a..b61e3b7609 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -387,6 +387,13 @@ var ( Value: ethconfig.Defaults.TxPool.Lifetime, Category: flags.TxPoolCategory, } + // + TxPoolJournalRemotesFlag = &cli.BoolFlag{ + Name: "txpool.journalremotes", + Usage: "Includes remote transactions in the journal", + Category: flags.TxPoolCategory, + } + // // Blob transaction pool settings BlobPoolDataDirFlag = &cli.StringFlag{ Name: "blobpool.datadir", @@ -1532,6 +1539,11 @@ func setTxPool(ctx *cli.Context, cfg *legacypool.Config) { if ctx.IsSet(TxPoolJournalFlag.Name) { cfg.Journal = ctx.String(TxPoolJournalFlag.Name) } + // + if ctx.IsSet(TxPoolJournalRemotesFlag.Name) { + cfg.JournalRemote = ctx.Bool(TxPoolJournalRemotesFlag.Name) + } + // if ctx.IsSet(TxPoolRejournalFlag.Name) { cfg.Rejournal = ctx.Duration(TxPoolRejournalFlag.Name) } diff --git a/core/state_transition.go b/core/state_transition.go index 1dc0fb8e55..8cbe6b4cf6 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -450,7 +450,9 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { // if st.evm.Config.SpecularEVMPreTransferHook != nil { - err = st.evm.Config.SpecularEVMPreTransferHook(st.msg, st.evm) + // + err = st.evm.Config.SpecularEVMPreTransferHook(st.msg, st.evm.StateDB) + // if err != nil { return nil, err } diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 00e326c4b8..b90d4d625a 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -120,6 +121,11 @@ type BlockChain interface { // StateAt returns a state database for a given root hash (generally the head). StateAt(root common.Hash) (*state.StateDB, error) + + // + // GetVMConfig returns the vm config + GetVMConfig() *vm.Config + // } // Config are the configuration parameters of the transaction pool. @@ -129,6 +135,13 @@ type Config struct { Journal string // Journal of local transactions to survive node restarts Rejournal time.Duration // Time interval to regenerate the local transaction journal + // + // JournalRemote controls whether journaling includes remote transactions or not. + // When true, all transactions loaded from the journal are treated as remote. + JournalRemote bool + // + + PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce) @@ -195,6 +208,10 @@ func (config *Config) sanitize() Config { return conf } +// +type L1CostFn func(tx *types.Transaction) *big.Int // +// + // LegacyPool contains all currently known transactions. Transactions // enter the pool when they are received from the network or submitted // locally. They exit the pool when they are included in the blockchain. @@ -235,6 +252,10 @@ type LegacyPool struct { initDoneCh chan struct{} // is closed once the pool is initialized (for tests) changesSinceReorg int // A counter for how many drops we've performed in-between reorg. + + // + l1CostFn L1CostFn + // } type txpoolResetRequest struct { @@ -271,9 +292,19 @@ func New(config Config, chain BlockChain) *LegacyPool { } pool.priced = newPricedList(pool.all) - if !config.NoLocals && config.Journal != "" { + // + if (!config.NoLocals || config.JournalRemote) && config.Journal != "" { pool.journal = newTxJournal(config.Journal) } + + if pool.chain.GetVMConfig().SpecularL1FeeReader != nil { + pool.l1CostFn = func (tx *types.Transaction) *big.Int { + l1Fee, _ := pool.chain.GetVMConfig().SpecularL1FeeReader(tx, pool.currentState) + return l1Fee + } + } + // + return pool } @@ -307,12 +338,18 @@ func (pool *LegacyPool) Init(gasTip *big.Int, head *types.Header, reserve txpool // If local transactions and journaling is enabled, load from disk if pool.journal != nil { - if err := pool.journal.load(pool.addLocals); err != nil { + // + add := pool.addLocals + if pool.config.JournalRemote { + add = pool.addRemotesSync // Use sync version to match pool.AddLocals + } + if err := pool.journal.load(add); err != nil { log.Warn("Failed to load transaction journal", "err", err) } - if err := pool.journal.rotate(pool.local()); err != nil { + if err := pool.journal.rotate(pool.toJournal()); err != nil { log.Warn("Failed to rotate transaction journal", "err", err) } + // } pool.wg.Add(1) go pool.loop() @@ -380,7 +417,7 @@ func (pool *LegacyPool) loop() { case <-journal.C: if pool.journal != nil { pool.mu.Lock() - if err := pool.journal.rotate(pool.local()); err != nil { + if err := pool.journal.rotate(pool.toJournal()); err != nil { log.Warn("Failed to rotate local tx journal", "err", err) } pool.mu.Unlock() @@ -555,6 +592,26 @@ func (pool *LegacyPool) Locals() []common.Address { return pool.locals.flatten() } +// +// toJournal retrieves all transactions that should be included in the journal, +// grouped by origin account and sorted by nonce. +// The returned transaction set is a copy and can be freely modified by calling code. +func (pool *LegacyPool) toJournal() map[common.Address]types.Transactions { + if !pool.config.JournalRemote { + return pool.local() + } + txs := make(map[common.Address]types.Transactions) + for addr, pending := range pool.pending { + txs[addr] = append(txs[addr], pending.Flatten()...) + } + for addr, queued := range pool.queue { + txs[addr] = append(txs[addr], queued.Flatten()...) + } + return txs +} + +// + // local retrieves all currently known local transactions, grouped by origin // account and sorted by nonce. The returned transaction set is a copy and can be // freely modified by calling code. @@ -620,7 +677,13 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction, local bool) error { ExistingCost: func(addr common.Address, nonce uint64) *big.Int { if list := pool.pending[addr]; list != nil { if tx := list.txs.Get(nonce); tx != nil { - return tx.Cost() + // + cost := tx.Cost() + if pool.chain.GetVMConfig().SpecularL1FeeReader != nil { + l1Fee, _ := pool.chain.GetVMConfig().SpecularL1FeeReader(tx, pool.currentState) + cost.Add(cost, l1Fee) + } + // } } return nil @@ -747,7 +810,7 @@ func (pool *LegacyPool) add(tx *types.Transaction, local bool) (replaced bool, e // Try to replace an existing transaction in the pending pool if list := pool.pending[from]; list != nil && list.Contains(tx.Nonce()) { // Nonce already pending, check if required price bump is met - inserted, old := list.Add(tx, pool.config.PriceBump) + inserted, old := list.Add(tx, pool.config.PriceBump, pool.l1CostFn) if !inserted { pendingDiscardMeter.Mark(1) return false, txpool.ErrReplaceUnderpriced @@ -821,7 +884,7 @@ func (pool *LegacyPool) enqueueTx(hash common.Hash, tx *types.Transaction, local if pool.queue[from] == nil { pool.queue[from] = newList(false) } - inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump) + inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump, pool.l1CostFn) if !inserted { // An older transaction was better, discard this queuedDiscardMeter.Mark(1) @@ -875,7 +938,7 @@ func (pool *LegacyPool) promoteTx(addr common.Address, hash common.Hash, tx *typ } list := pool.pending[addr] - inserted, old := list.Add(tx, pool.config.PriceBump) + inserted, old := list.Add(tx, pool.config.PriceBump, pool.l1CostFn) if !inserted { // An older transaction was better, discard this pool.all.Remove(hash) @@ -1406,6 +1469,23 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) { pool.addTxsLocked(reinject, false) } +// +// getBalanceWithL1Fee returns the balance of the addr minus the L1 fee of the first tx in the list +func (pool *LegacyPool) getBalanceWithL1Fee(addr common.Address, txList *list) *big.Int { + balance := pool.currentState.GetBalance(addr) + if !txList.Empty() && pool.chain.GetVMConfig().SpecularL1FeeReader != nil { + // Reduce the cost-cap by L1 rollup cost of the first tx if necessary. Other txs will get filtered out afterwards. + first := txList.txs.Get((*txList.txs.index)[0]) + l1Fee, _ := pool.chain.GetVMConfig().SpecularL1FeeReader(first, pool.currentState) + + balance = new(big.Int).Sub(balance, l1Fee) // negative big int is fine + } + + return balance +} + +// + // promoteExecutables moves transactions that have become processable from the // future queue to the set of pending transactions. During this process, all // invalidated transactions (low nonce, low balance) are deleted. @@ -1428,7 +1508,10 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T } log.Trace("Removed old queued transactions", "count", len(forwards)) // Drop all transactions that are too costly (low balance or out of gas) - drops, _ := list.Filter(pool.currentState.GetBalance(addr), gasLimit) + // + balance := pool.getBalanceWithL1Fee(addr, list) + drops, _ := list.Filter(balance, gasLimit) + // for _, tx := range drops { hash := tx.Hash() pool.all.Remove(hash) @@ -1629,7 +1712,10 @@ func (pool *LegacyPool) demoteUnexecutables() { log.Trace("Removed old pending transaction", "hash", hash) } // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later - drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit) + // + balance := pool.getBalanceWithL1Fee(addr, list) + drops, invalids := list.Filter(balance, gasLimit) + // for _, tx := range drops { hash := tx.Hash() log.Trace("Removed unpayable pending transaction", "hash", hash) diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index a8f3dd7d86..4d69548ee3 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" @@ -65,14 +66,19 @@ type testBlockChain struct { gasLimit atomic.Uint64 statedb *state.StateDB chainHeadFeed *event.Feed + vmConfig vm.Config } func newTestBlockChain(config *params.ChainConfig, gasLimit uint64, statedb *state.StateDB, chainHeadFeed *event.Feed) *testBlockChain { - bc := testBlockChain{config: config, statedb: statedb, chainHeadFeed: new(event.Feed)} + bc := testBlockChain{config: config, statedb: statedb, chainHeadFeed: new(event.Feed), vmConfig: vm.Config{}} bc.gasLimit.Store(gasLimit) return &bc } +func (bc *testBlockChain) GetVMConfig() *vm.Config { + return &bc.vmConfig +} + func (bc *testBlockChain) Config() *params.ChainConfig { return bc.config } @@ -171,6 +177,27 @@ func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *ecdsa.Privat return pool, key } +// returns a tx pool with an injected L1 Fee function +// L1 fee is hardcoded to 100 wei +func setupTxPoolWithL1Fee() (*LegacyPool, *ecdsa.PrivateKey) { + config := params.TestChainConfig + statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) + blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed)) + blockchain.vmConfig.SpecularL1FeeReader = + func(tx *types.Transaction, db vm.StateDB) (*big.Int, error) { + return big.NewInt(100), nil + } + + key, _ := crypto.GenerateKey() + pool := New(testTxPoolConfig, blockchain) + if err := pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver()); err != nil { + panic(err) + } + // wait for the pool to initialize + <-pool.initDoneCh + return pool, key +} + // validatePoolInternals checks various consistency invariants within the pool. func validatePoolInternals(pool *LegacyPool) error { pool.mu.RLock() diff --git a/core/txpool/legacypool/list.go b/core/txpool/legacypool/list.go index 384fa7b61b..88a7b08490 100644 --- a/core/txpool/legacypool/list.go +++ b/core/txpool/legacypool/list.go @@ -298,7 +298,7 @@ func (l *list) Contains(nonce uint64) bool { // // If the new transaction is accepted into the list, the lists' cost and gas // thresholds are also potentially updated. -func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) { +func (l *list) Add(tx *types.Transaction, priceBump uint64, l1CostFn L1CostFn) (bool, *types.Transaction) { // If there's an older better transaction, abort old := l.txs.Get(tx.Nonce()) if old != nil { @@ -326,6 +326,13 @@ func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transa } // Add new tx cost to totalcost l.totalcost.Add(l.totalcost, tx.Cost()) + // + if l1CostFn != nil { + if l1Cost := l1CostFn(tx); l1Cost != nil { + l.totalcost.Add(l.totalcost, l1Cost) + } + } + // // Otherwise overwrite the old transaction with the current one l.txs.Put(tx) if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 { diff --git a/core/txpool/legacypool/list_test.go b/core/txpool/legacypool/list_test.go index b5cd34b23b..b1f6ec305d 100644 --- a/core/txpool/legacypool/list_test.go +++ b/core/txpool/legacypool/list_test.go @@ -38,7 +38,7 @@ func TestStrictListAdd(t *testing.T) { // Insert the transactions in a random order list := newList(true) for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], DefaultConfig.PriceBump) + list.Add(txs[v], DefaultConfig.PriceBump, nil) } // Verify internal state if len(list.txs.items) != len(txs) { @@ -65,7 +65,7 @@ func BenchmarkListAdd(b *testing.B) { for i := 0; i < b.N; i++ { list := newList(true) for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], DefaultConfig.PriceBump) + list.Add(txs[v], DefaultConfig.PriceBump, nil) list.Filter(priceLimit, DefaultConfig.PriceBump) } } diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 630d5340cf..a55f6f18ed 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -30,6 +30,22 @@ import ( "github.com/ethereum/go-ethereum/params" ) +// +// L1Oracle Update Overhead is the amount of gas consumed by updating the L1Oracle every epoch +const l1OracleUpdateOverhead = uint64(70_000) + +func EffectiveGasLimit(gasLimit uint64, config *params.ChainConfig) uint64 { + if (config.L1FeeRecipient != common.Address{}) { + if l1OracleUpdateOverhead < gasLimit { + gasLimit -= l1OracleUpdateOverhead + } else { + gasLimit = 0 + } + } + return gasLimit +} +// + // ValidationOptions define certain differences between transaction validation // across the different pools without having to duplicate those checks. type ValidationOptions struct { @@ -76,7 +92,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types return ErrNegativeValue } // Ensure the transaction doesn't exceed the current block limit gas - if head.GasLimit < tx.Gas() { + if EffectiveGasLimit(head.GasLimit, opts.Config) < tx.Gas() { return ErrGasLimit } // Sanity check for extremely large numbers (supported by RLP or RPC) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index ecfbd9c0d0..41d083550b 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -43,8 +43,8 @@ type MessageInterface interface { GetSkipAccountChecks() bool } -type EVMHook func(msg MessageInterface, evm *EVM) error - +type EVMHook func(msg MessageInterface, db StateDB) error +type EVMReader func(tx *types.Transaction, db StateDB) (*big.Int, error) // // // Config are the configuration options for the Interpreter @@ -56,6 +56,7 @@ type Config struct { // SpecularEVMPreTransferHook EVMHook + SpecularL1FeeReader EVMReader // } diff --git a/go.mod b/go.mod index 8061220aa6..b03f82e940 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/ethereum/go-ethereum go 1.20 +replace github.com/specularL2/specular/lib/el_golang_lib => ../../../lib/el_golang_lib + require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 github.com/Microsoft/go-winio v0.6.1 @@ -24,7 +26,7 @@ require ( github.com/fatih/color v1.7.0 github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 - github.com/fsnotify/fsnotify v1.6.0 + github.com/fsnotify/fsnotify v1.7.0 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b github.com/go-stack/stack v1.8.1 @@ -56,6 +58,7 @@ require ( github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 github.com/rs/cors v1.7.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible + github.com/specularL2/specular/lib/el_golang_lib v0.0.0-00010101000000-000000000000 github.com/status-im/keycard-go v0.2.0 github.com/stretchr/testify v1.8.1 github.com/supranational/blst v0.3.11 @@ -123,6 +126,7 @@ require ( github.com/prometheus/procfs v0.7.3 // indirect github.com/rogpeppe/go-internal v1.6.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/specularL2/specular/ops v0.0.0-20231129092153-13f66846bd07 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect diff --git a/go.sum b/go.sum index 9c6fd74e4a..0207a5e92f 100644 --- a/go.sum +++ b/go.sum @@ -186,8 +186,8 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+ github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc= github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= @@ -517,6 +517,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/specularL2/specular/ops v0.0.0-20231129092153-13f66846bd07 h1:1GATCkcQ+bFcTq+JBr18jOrS0WKZ5B62gob7zFm0Rac= +github.com/specularL2/specular/ops v0.0.0-20231129092153-13f66846bd07/go.mod h1:hxwB50nU3AN6FEWsb+RQ4zSrfTIIO6JGlKXPbsa5C2c= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= @@ -754,7 +756,6 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/params/config.go b/params/config.go index 2cc45eae3e..8615f4e886 100644 --- a/params/config.go +++ b/params/config.go @@ -335,8 +335,10 @@ type ChainConfig struct { IsDevMode bool `json:"isDev,omitempty"` // - EnableL2EngineApi bool `json:"enableL2EngineApi,omitempty"` - L2BaseFeeRecipient common.Address `json:"l2BaseFeeRecipient,omitempty"` + EnableL2EngineApi bool `json:"enableL2EngineApi,omitempty"` + EnableL2GasLimitApi bool `json:"enableL2GasLimitApi,omitempty"` + L2BaseFeeRecipient common.Address `json:"l2BaseFeeRecipient,omitempty"` + L1FeeRecipient common.Address `json:"l1FeeRecipient,omitempty"` // } @@ -374,6 +376,9 @@ func (c *ChainConfig) Description() string { case c.EnableL2EngineApi: banner += "Consensus: L2 gas limit API enabled\n" banner += fmt.Sprintf(" - L2 Base fee recipient: %s\n", c.L2BaseFeeRecipient) + case c.L1FeeRecipient != common.Address{}: + banner += "Consensus: L1 Fee is enabled\n" + banner += fmt.Sprintf("Consensus: L1 Fee Recipient: %s\n", c.L1FeeRecipient) // case c.Ethash != nil: if c.TerminalTotalDifficulty == nil { @@ -396,6 +401,14 @@ func (c *ChainConfig) Description() string { } banner += "\n" + // + if (c.L1FeeRecipient != common.Address{}) { + banner += "Rollup: L1 Fee is enabled\n" + banner += fmt.Sprintf("Rollup: L1 Fee Recipient: %s\n", c.L1FeeRecipient) + banner += "\n" + } + // + // Create a list of forks with a short description of them. Forks that only // makes sense for mainnet should be optional at printing to avoid bloating // the output for testnets and private networks.