Commit 38bff0ff authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

Merge pull request #1408 from ethereum-optimism/fix/l2geth-min-l2-gas-limit

l2geth: configurable min L2 gas limit
parents 911f40d8 0e14855c
---
'@eth-optimism/l2geth': patch
---
Add in min accepted L2 gas limit config flag
......@@ -168,6 +168,7 @@ var (
utils.RollupMaxCalldataSizeFlag,
utils.RollupBackendFlag,
utils.RollupEnforceFeesFlag,
utils.RollupMinL2GasLimitFlag,
utils.RollupFeeThresholdDownFlag,
utils.RollupFeeThresholdUpFlag,
utils.GasPriceOracleOwnerAddress,
......
......@@ -81,6 +81,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.RollupMaxCalldataSizeFlag,
utils.RollupBackendFlag,
utils.RollupEnforceFeesFlag,
utils.RollupMinL2GasLimitFlag,
utils.RollupFeeThresholdDownFlag,
utils.RollupFeeThresholdUpFlag,
utils.GasPriceOracleOwnerAddress,
......
......@@ -892,6 +892,11 @@ var (
Usage: "Disable transactions with 0 gas price",
EnvVar: "ROLLUP_ENFORCE_FEES",
}
RollupMinL2GasLimitFlag = cli.Uint64Flag{
Name: "rollup.minl2gaslimit",
Usage: "Minimum accepted L2 gas limit",
EnvVar: "ROLLUP_MIN_L2_GAS_LIMIT",
}
RollupFeeThresholdDownFlag = cli.Float64Flag{
Name: "rollup.feethresholddown",
Usage: "Allow txs with fees below the current fee up to this amount, must be < 1",
......@@ -1203,6 +1208,10 @@ func setRollup(ctx *cli.Context, cfg *rollup.Config) {
if ctx.GlobalIsSet(RollupEnforceFeesFlag.Name) {
cfg.EnforceFees = true
}
if ctx.GlobalIsSet(RollupMinL2GasLimitFlag.Name) {
val := ctx.GlobalUint64(RollupMinL2GasLimitFlag.Name)
cfg.MinL2GasLimit = new(big.Int).SetUint64(val)
}
if ctx.GlobalIsSet(RollupFeeThresholdDownFlag.Name) {
val := ctx.GlobalFloat64(RollupFeeThresholdDownFlag.Name)
cfg.FeeThresholdDown = new(big.Float).SetFloat64(val)
......
......@@ -39,6 +39,10 @@ type Config struct {
Backend Backend
// Only accept transactions with fees
EnforceFees bool
// Prevent transactions with a L2 gas limit lower than this value
// The L2 gas limit is parsed from the `tx.gasPrice`, see the
// `rollup/fees` package for more information
MinL2GasLimit *big.Int
// Allow fees within a buffer upwards or downwards
// to take fee volatility into account between being
// quoted and the transaction being executed
......
......@@ -18,6 +18,9 @@ var (
// errMissingInput represents the error case of missing required input to
// PaysEnough
errMissingInput = errors.New("missing input")
// ErrL2GasLimitTooLow represents the error case of when a user sends a
// transaction to the sequencer with a L2 gas limit that is too small
ErrL2GasLimitTooLow = errors.New("L2 gas limit too low")
)
// overhead represents the fixed cost of batch submission of a single
......
......@@ -78,6 +78,7 @@ type SyncService struct {
gasPriceOracleOwnerAddressLock *sync.RWMutex
enforceFees bool
signer types.Signer
minL2GasLimit *big.Int
feeThresholdUp *big.Float
feeThresholdDown *big.Float
}
......@@ -135,6 +136,11 @@ func NewSyncService(ctx context.Context, cfg Config, txpool *core.TxPool, bc *co
cfg.FeeThresholdUp)
}
}
if cfg.MinL2GasLimit == nil {
value := new(big.Int)
log.Info("Sanitizing minimum L2 gas limit", "value", value)
cfg.MinL2GasLimit = value
}
service := SyncService{
ctx: ctx,
......@@ -155,6 +161,7 @@ func NewSyncService(ctx context.Context, cfg Config, txpool *core.TxPool, bc *co
gasPriceOracleOwnerAddressLock: new(sync.RWMutex),
enforceFees: cfg.EnforceFees,
signer: types.NewEIP155Signer(chainID),
minL2GasLimit: cfg.MinL2GasLimit,
feeThresholdDown: cfg.FeeThresholdDown,
feeThresholdUp: cfg.FeeThresholdUp,
}
......@@ -855,6 +862,12 @@ func (s *SyncService) verifyFee(tx *types.Transaction) error {
gas := new(big.Int).SetUint64(tx.Gas())
l2GasLimit := fees.DecodeL2GasLimit(gas)
// When the L2 gas limit is smaller than the min L2 gas limit,
// reject the transaction
if l2GasLimit.Cmp(s.minL2GasLimit) == -1 {
return fmt.Errorf("%w: %d, use at least %d", fees.ErrL2GasLimitTooLow, l2GasLimit, s.minL2GasLimit)
}
// Only count the calldata here as the overhead of the fully encoded
// RLP transaction is handled inside of EncodeL2GasLimit
expectedTxGasLimit := fees.EncodeTxGasLimit(tx.Data(), l1GasPrice, l2GasLimit, l2GasPrice)
......
......@@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rollup/fees"
)
func setupLatestEthContextTest() (*SyncService, *EthContext) {
......@@ -548,6 +549,38 @@ func TestSyncServiceL2GasPrice(t *testing.T) {
}
}
func TestSyncServiceMinL2GasPrice(t *testing.T) {
service, _, _, err := newTestSyncService(true)
if err != nil {
t.Fatal(err)
}
service.minL2GasLimit = new(big.Int).SetUint64(10_000_000)
signer := types.NewEIP155Signer(big.NewInt(420))
// Generate a key
key, _ := crypto.GenerateKey()
// Create a transaction
gasLimit := uint64(100)
tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), gasLimit, big.NewInt(15000000), []byte{})
// Make sure the gas limit is set correctly
if tx.Gas() != gasLimit {
t.Fatal("gas limit not set correctly")
}
// Sign the dummy tx with the owner key
signedTx, err := types.SignTx(tx, signer, key)
if err != nil {
t.Fatal(err)
}
// Sanity check the L2 gas limit
if tx.L2Gas() > service.minL2GasLimit.Uint64() {
t.Fatal("L2 gas limit expected to be smaller than min accepted by sequencer")
}
// Verify the fee of the signed tx, ensure it does not error
err = service.verifyFee(signedTx)
if !errors.Is(err, fees.ErrL2GasLimitTooLow) {
t.Fatal(err)
}
}
func TestSyncServiceGasPriceOracleOwnerAddress(t *testing.T) {
service, _, _, err := newTestSyncService(true)
if err != nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment