diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68ca8f229..81d0d7843 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,8 +23,8 @@ jobs: uses: golangci/golangci-lint-action@v3 with: working-directory: op-node - version: latest - args: -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" + version: v1.63.4 + args: -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 15m -e "errors.As" -e "errors.Is" op-batcher-lint: runs-on: ubuntu-latest @@ -42,8 +42,8 @@ jobs: uses: golangci/golangci-lint-action@v3 with: working-directory: op-batcher - version: latest - args: -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" + version: v1.63.4 + args: -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 15m -e "errors.As" -e "errors.Is" op-proposer-lint: runs-on: ubuntu-latest @@ -61,8 +61,8 @@ jobs: uses: golangci/golangci-lint-action@v3 with: working-directory: op-proposer - version: latest - args: -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" + version: v1.63.4 + args: -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 15m -e "errors.As" -e "errors.Is" op-service-lint: runs-on: ubuntu-latest @@ -80,8 +80,8 @@ jobs: uses: golangci/golangci-lint-action@v3 with: working-directory: op-service - version: latest - args: -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 5m -e "errors.As" -e "errors.Is" + version: v1.63.4 + args: -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint --timeout 15m -e "errors.As" -e "errors.Is" op-node-test: runs-on: ubuntu-latest diff --git a/go.mod b/go.mod index 3e5d4a828..77bcf120c 100644 --- a/go.mod +++ b/go.mod @@ -277,7 +277,7 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/ethereum/go-ethereum v1.13.15 => github.com/bnb-chain/op-geth v1.101315.2-0.0.20240823030609-c0f12a4e1b05 +replace github.com/ethereum/go-ethereum v1.13.15 => github.com/bnb-chain/op-geth v1.101315.2-0.0.20250213114253-fbecb252643d replace github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v1.0.0 diff --git a/go.sum b/go.sum index bf3c1d73c..dda996ef9 100644 --- a/go.sum +++ b/go.sum @@ -184,8 +184,8 @@ github.com/bnb-chain/fastssz v0.1.2 h1:vTcXw5SwCtRYnl/BEclujiml7GXiVOZ74tub4GHpv github.com/bnb-chain/fastssz v0.1.2/go.mod h1:KcabV+OEw2QwgyY8Fc88ZG79CKYkFdu0kKWyfA3dI6o= github.com/bnb-chain/greenfield-cometbft v1.0.0 h1:0r6hOJWD/+es0gxP/exKuN/krgXAr3LCn5/XlcgDWr8= github.com/bnb-chain/greenfield-cometbft v1.0.0/go.mod h1:f35mk/r5ab6yvzlqEWZt68LfUje68sYgMpVlt2CUYMk= -github.com/bnb-chain/op-geth v1.101315.2-0.0.20240823030609-c0f12a4e1b05 h1:Tyov2UCjIxxHt6ZX46T09CiKpKDY72AtjHzUQFK3SBA= -github.com/bnb-chain/op-geth v1.101315.2-0.0.20240823030609-c0f12a4e1b05/go.mod h1:hyHrrcHkUe3lRwfJs+JGrbOHp+pRdheRk+ren4TPhF8= +github.com/bnb-chain/op-geth v1.101315.2-0.0.20250213114253-fbecb252643d h1:zYSisO6VUWaQzieOnP7NcEXfwbcYa86CipNS+sXHb7Q= +github.com/bnb-chain/op-geth v1.101315.2-0.0.20250213114253-fbecb252643d/go.mod h1:hyHrrcHkUe3lRwfJs+JGrbOHp+pRdheRk+ren4TPhF8= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index b70ffe239..0df382ac1 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -1,6 +1,7 @@ package batcher import ( + "bytes" "context" "errors" "fmt" @@ -12,6 +13,14 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-batcher/metrics" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -20,12 +29,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/txmgr" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" ) const LimitLoadBlocksOneTime uint64 = 30 @@ -678,10 +681,31 @@ func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, que candidate = l.calldataTxCandidate(data) } - intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, false, true, true, false) + intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, nil, true, true, false, false) if err != nil { // we log instead of return an error here because txmgr can do its own gas estimation l.Log.Error("Failed to calculate intrinsic gas", "err", err) + } else if candidate.Blobs == nil { + minimumGasRequired, err := func(data []byte) (uint64, error) { + var ( + z = uint64(bytes.Count(data, []byte{0})) + nz = uint64(len(data)) - z + tokens = nz*params.TxTokenPerNonZeroByte + z + ) + if (math.MaxUint64-params.TxGas)/params.TxCostFloorPerToken < tokens { + return 0, errors.New("intrinsic gas too low") + } + return params.TxGas + tokens*params.TxCostFloorPerToken, nil + }(candidate.TxData) + + if err != nil { + return err + } + // + baseGas := intrinsicGas - params.TxGas + finalGasLimit := max(baseGas, minimumGasRequired) + params.TxGas + + candidate.GasLimit = finalGasLimit } else { candidate.GasLimit = intrinsicGas } diff --git a/op-chain-ops/cmd/check-derivation/main.go b/op-chain-ops/cmd/check-derivation/main.go index dd5d63194..b867ea23a 100644 --- a/op-chain-ops/cmd/check-derivation/main.go +++ b/op-chain-ops/cmd/check-derivation/main.go @@ -225,7 +225,7 @@ func getRandomSignedTransaction(ctx context.Context, ethClient *ethclient.Client var txData types.TxData switch txType { case types.LegacyTxType: - gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false) + gasLimit, err := core.IntrinsicGas(data, nil, nil, false, true, false, false) if err != nil { return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) } @@ -242,7 +242,7 @@ func getRandomSignedTransaction(ctx context.Context, ethClient *ethclient.Client Address: randomAddress, StorageKeys: []common.Hash{common.HexToHash("0x1234")}, }} - gasLimit, err := core.IntrinsicGas(data, accessList, false, true, true, false) + gasLimit, err := core.IntrinsicGas(data, accessList, nil, false, true, false, false) if err != nil { return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) } @@ -257,7 +257,7 @@ func getRandomSignedTransaction(ctx context.Context, ethClient *ethclient.Client Data: data, } case types.DynamicFeeTxType: - gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false) + gasLimit, err := core.IntrinsicGas(data, nil, nil, false, true, false, false) if err != nil { return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) } diff --git a/op-e2e/actions/l2_batcher.go b/op-e2e/actions/l2_batcher.go index 310a6cade..1a955f851 100644 --- a/op-e2e/actions/l2_batcher.go +++ b/op-e2e/actions/l2_batcher.go @@ -277,7 +277,7 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic opt(rawTx) } - gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false) + gas, err := core.IntrinsicGas(rawTx.Data, nil, nil, false, true, false, false) require.NoError(t, err, "need to compute intrinsic gas") rawTx.Gas = gas txData = rawTx @@ -468,7 +468,7 @@ func (s *L2Batcher) ActL2BatchSubmitGarbage(t Testing, kind GarbageKind) { GasFeeCap: gasFeeCap, Data: outputFrame, } - gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false) + gas, err := core.IntrinsicGas(rawTx.Data, nil, nil, false, true, false, false) require.NoError(t, err, "need to compute intrinsic gas") rawTx.Gas = gas diff --git a/op-e2e/actions/l2_batcher_test.go b/op-e2e/actions/l2_batcher_test.go index 3a137ce99..27f567b32 100644 --- a/op-e2e/actions/l2_batcher_test.go +++ b/op-e2e/actions/l2_batcher_test.go @@ -496,7 +496,7 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { data := make([]byte, 120_000) // very large L2 txs, as large as the tx-pool will accept _, err := rng.Read(data[:]) // fill with random bytes, to make compression ineffective require.NoError(t, err) - gas, err := core.IntrinsicGas(data, nil, false, true, true, false) + gas, err := core.IntrinsicGas(data, nil, nil, false, true, true, false) require.NoError(t, err) if gas > engine.engineApi.RemainingBlockGas() { break diff --git a/op-e2e/actions/span_batch_test.go b/op-e2e/actions/span_batch_test.go index 6ccb76a46..b3bc2d0d1 100644 --- a/op-e2e/actions/span_batch_test.go +++ b/op-e2e/actions/span_batch_test.go @@ -524,7 +524,7 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) { data := make([]byte, rand.Intn(100)) _, err := crand.Read(data[:]) // fill with random bytes require.NoError(t, err) - gas, err := core.IntrinsicGas(data, nil, false, true, true, false) + gas, err := core.IntrinsicGas(data, nil, nil, false, true, false, false) require.NoError(t, err) baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee nonce, err := cl.PendingNonceAt(t.Ctx(), addrs[userIdx]) @@ -663,7 +663,7 @@ func TestBatchEquivalence(gt *testing.T) { data := make([]byte, rand.Intn(100)) _, err := crand.Read(data[:]) // fill with random bytes require.NoError(t, err) - gas, err := core.IntrinsicGas(data, nil, false, true, true, false) + gas, err := core.IntrinsicGas(data, nil, nil, false, true, false, false) require.NoError(t, err) baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee nonce, err := seqEngCl.PendingNonceAt(t.Ctx(), addrs[userIdx]) diff --git a/op-e2e/actions/sync_test.go b/op-e2e/actions/sync_test.go index e7521bdd8..b856413f3 100644 --- a/op-e2e/actions/sync_test.go +++ b/op-e2e/actions/sync_test.go @@ -896,7 +896,7 @@ func TestInvalidPayloadInSpanBatch(gt *testing.T) { aliceNonce, err := seqEng.EthClient().PendingNonceAt(t.Ctx(), dp.Addresses.Alice) require.NoError(t, err) data := make([]byte, rand.Intn(100)) - gas, err := core.IntrinsicGas(data, nil, false, true, true, false) + gas, err := core.IntrinsicGas(data, nil, nil, false, true, false, false) require.NoError(t, err) baseFee := seqEng.l2Chain.CurrentBlock().BaseFee tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ diff --git a/op-e2e/brotli_batcher_test.go b/op-e2e/brotli_batcher_test.go index 97211c471..c000a6f42 100644 --- a/op-e2e/brotli_batcher_test.go +++ b/op-e2e/brotli_batcher_test.go @@ -85,7 +85,7 @@ func TestBrotliBatcherFjord(t *testing.T) { opts.Value = big.NewInt(1_000_000_000) opts.Nonce = 1 // Already have deposit opts.ToAddr = &common.Address{0xff, 0xff} - opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false) + opts.Gas, err = core.IntrinsicGas(opts.Data, nil, nil, false, true, false, false) require.NoError(t, err) opts.VerifyOnClients(l2Verif) }) diff --git a/op-e2e/eip4844_test.go b/op-e2e/eip4844_test.go index 5b5cc1d53..37b243ffb 100644 --- a/op-e2e/eip4844_test.go +++ b/op-e2e/eip4844_test.go @@ -102,7 +102,7 @@ func testSystem4844E2E(t *testing.T, multiBlob bool) { opts.ToAddr = &common.Address{0xff, 0xff} // put some random data in the tx to make it fill up 6 blobs (multi-blob case) opts.Data = testutils.RandomData(rand.New(rand.NewSource(420)), 400) - opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false) + opts.Gas, err = core.IntrinsicGas(opts.Data, nil, nil, false, true, false, false) require.NoError(t, err) opts.VerifyOnClients(l2Verif) }) diff --git a/op-node/rollup/derive/span_batch_tx.go b/op-node/rollup/derive/span_batch_tx.go index cd0a471ab..f489dafed 100644 --- a/op-node/rollup/derive/span_batch_tx.go +++ b/op-node/rollup/derive/span_batch_tx.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" ) type spanBatchTxData interface { @@ -45,6 +46,17 @@ type spanBatchDynamicFeeTxData struct { func (txData *spanBatchDynamicFeeTxData) txType() byte { return types.DynamicFeeTxType } +type spanBatchSetCodeTxData struct { + Value *big.Int // wei amount + GasTipCap *big.Int // maxPriorityFeePerGas (EIP-1559) + GasFeeCap *big.Int // maxFeePerGas (EIP-1559) + Data []byte // contract invocation input data + AccessList types.AccessList // EIP-2930 access list + AuthList []types.SetCodeAuthorization // EIP-7702 authorization list +} + +func (txData *spanBatchSetCodeTxData) txType() byte { return types.SetCodeTxType } + // Type returns the transaction type. func (tx *spanBatchTx) Type() uint8 { return tx.inner.txType() @@ -93,6 +105,13 @@ func (tx *spanBatchTx) decodeTyped(b []byte) (spanBatchTxData, error) { return nil, fmt.Errorf("failed to decode spanBatchDynamicFeeTxData: %w", err) } return &inner, nil + case types.SetCodeTxType: + var inner spanBatchSetCodeTxData + err := rlp.DecodeBytes(b[1:], &inner) + if err != nil { + return nil, fmt.Errorf("failed to decode spanBatchSetCodeTxData: %w", err) + } + return &inner, nil default: return nil, types.ErrTxTypeNotSupported } @@ -168,6 +187,23 @@ func (tx *spanBatchTx) convertToFullTx(nonce, gas uint64, to *common.Address, ch R: R, S: S, } + case types.SetCodeTxType: + batchTxInner := tx.inner.(*spanBatchSetCodeTxData) + inner = &types.SetCodeTx{ + ChainID: uint256.MustFromBig(chainID), + Nonce: nonce, + GasTipCap: uint256.MustFromBig(batchTxInner.GasTipCap), + GasFeeCap: uint256.MustFromBig(batchTxInner.GasFeeCap), + Gas: gas, + To: *to, + Value: uint256.MustFromBig(batchTxInner.Value), + Data: batchTxInner.Data, + AccessList: batchTxInner.AccessList, + AuthList: batchTxInner.AuthList, + V: uint256.MustFromBig(V), + R: uint256.MustFromBig(R), + S: uint256.MustFromBig(S), + } default: return nil, fmt.Errorf("invalid tx type: %d", tx.Type()) } @@ -199,6 +235,16 @@ func newSpanBatchTx(tx types.Transaction) (*spanBatchTx, error) { Data: tx.Data(), AccessList: tx.AccessList(), } + case types.SetCodeTxType: + inner = &spanBatchSetCodeTxData{ + GasTipCap: tx.GasTipCap(), + GasFeeCap: tx.GasFeeCap(), + Value: tx.Value(), + Data: tx.Data(), + AccessList: tx.AccessList(), + AuthList: tx.SetCodeAuthorizations(), + } + default: return nil, fmt.Errorf("invalid tx type: %d", tx.Type()) } diff --git a/op-node/rollup/derive/span_batch_txs.go b/op-node/rollup/derive/span_batch_txs.go index 305aafefe..35d2a2f55 100644 --- a/op-node/rollup/derive/span_batch_txs.go +++ b/op-node/rollup/derive/span_batch_txs.go @@ -271,6 +271,8 @@ func (btx *spanBatchTxs) recoverV(chainID *big.Int) error { v = bit case types.DynamicFeeTxType: v = bit + case types.SetCodeTxType: + v = bit default: return fmt.Errorf("invalid tx type: %d", txType) } @@ -386,6 +388,8 @@ func convertVToYParity(v uint64, txType int) (uint, error) { yParityBit = uint(v) case types.DynamicFeeTxType: yParityBit = uint(v) + case types.SetCodeTxType: + yParityBit = uint(v) default: return 0, fmt.Errorf("invalid tx type: %d", txType) } diff --git a/op-program/client/mpt/db.go b/op-program/client/mpt/db.go index 6728d4101..460d571c2 100644 --- a/op-program/client/mpt/db.go +++ b/op-program/client/mpt/db.go @@ -1,6 +1,8 @@ package mpt -import "github.com/ethereum/go-ethereum/ethdb" +import ( + "github.com/ethereum/go-ethereum/ethdb" +) type Hooks struct { Get func(key []byte) []byte @@ -13,6 +15,42 @@ type DB struct { db Hooks } +func (p *DB) StateStoreReader() ethdb.Reader { + return p +} + +func (p *DB) BlockStoreReader() ethdb.Reader { + return p +} + +func (p *DB) BlockStoreWriter() ethdb.Writer { + return p +} + +func (p *DB) StateStore() ethdb.Database { + return p +} + +func (p *DB) SetStateStore(state ethdb.Database) { + panic("not supported") +} + +func (p *DB) GetStateStore() ethdb.Database { + return p +} + +func (p *DB) BlockStore() ethdb.Database { + return p +} + +func (p *DB) SetBlockStore(block ethdb.Database) { + panic("not supported") +} + +func (p *DB) HasSeparateBlockStore() bool { + return false +} + func (p *DB) Has(key []byte) (bool, error) { panic("not supported") } diff --git a/op-service/sources/eth_client.go b/op-service/sources/eth_client.go index 5ffa3f07e..e6879047f 100644 --- a/op-service/sources/eth_client.go +++ b/op-service/sources/eth_client.go @@ -285,7 +285,9 @@ func (s *EthClient) InfoByLabel(ctx context.Context, label eth.BlockLabel) (eth. func (s *EthClient) BSCInfoByLabel(ctx context.Context, label eth.BlockLabel) (eth.BlockInfo, error) { // can't hit the cache when querying the head due to reorgs / changes. if label == eth.Finalized { - return s.bscFinalizedHeader(ctx, 21) + // -3 means automatically use the len(validators) of BSC network + // refs: https://github.com/bnb-chain/bsc/pull/2844 + return s.bscFinalizedHeader(ctx, -3) } return s.headerCall(ctx, "eth_getBlockByNumber", label) }