Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal/sequencerapi,miner: move conditional rate limiter to the rpc layer instead of miner #377

Merged
merged 1 commit into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ var (
utils.GpoIgnoreGasPriceFlag,
utils.GpoMinSuggestedPriorityFeeFlag,
utils.RollupSequencerHTTPFlag,
utils.RollupSequencerEnableTxConditionalFlag,
utils.RollupSequencerTxConditionalRateLimitFlag,
utils.RollupSequencerTxConditionalEnabledFlag,
utils.RollupSequencerTxConditionalCostRateLimitFlag,
utils.RollupHistoricalRPCFlag,
utils.RollupHistoricalRPCTimeoutFlag,
utils.RollupDisableTxPoolGossipFlag,
Expand Down
14 changes: 6 additions & 8 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -976,14 +976,14 @@ var (
Category: flags.RollupCategory,
Value: true,
}
RollupSequencerEnableTxConditionalFlag = &cli.BoolFlag{
Name: "rollup.sequencerenabletxconditional",
RollupSequencerTxConditionalEnabledFlag = &cli.BoolFlag{
Name: "rollup.sequencertxconditionalenabled",
Usage: "Serve the eth_sendRawTransactionConditional endpoint and apply the conditional constraints on mempool inclusion & block building",
Category: flags.RollupCategory,
Value: false,
}
RollupSequencerTxConditionalRateLimitFlag = &cli.IntFlag{
Name: "rollup.sequencertxconditionalratelimit",
RollupSequencerTxConditionalCostRateLimitFlag = &cli.IntFlag{
Name: "rollup.sequencertxconditionalcostratelimit",
Usage: "Maximum cost -- storage lookups -- allowed for conditional transactions in a given second",
tynes marked this conversation as resolved.
Show resolved Hide resolved
Category: flags.RollupCategory,
Value: 5000,
Expand Down Expand Up @@ -1729,9 +1729,6 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
if ctx.IsSet(RollupComputePendingBlock.Name) {
cfg.RollupComputePendingBlock = ctx.Bool(RollupComputePendingBlock.Name)
}

// This flag has a default rate limit so always set
cfg.RollupTransactionConditionalRateLimit = ctx.Int(RollupSequencerTxConditionalRateLimitFlag.Name)
}

func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
Expand Down Expand Up @@ -1970,7 +1967,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.RollupDisableTxPoolAdmission = cfg.RollupSequencerHTTP != "" && !ctx.Bool(RollupEnableTxPoolAdmissionFlag.Name)
cfg.RollupHaltOnIncompatibleProtocolVersion = ctx.String(RollupHaltOnIncompatibleProtocolVersionFlag.Name)
cfg.ApplySuperchainUpgrades = ctx.Bool(RollupSuperchainUpgradesFlag.Name)
cfg.RollupSequencerEnableTxConditional = ctx.Bool(RollupSequencerEnableTxConditionalFlag.Name)
cfg.RollupSequencerTxConditionalEnabled = ctx.Bool(RollupSequencerTxConditionalEnabledFlag.Name)
cfg.RollupSequencerTxConditionalCostRateLimit = ctx.Int(RollupSequencerTxConditionalCostRateLimitFlag.Name)

// Override any default configs for hard coded networks.
switch {
Expand Down
6 changes: 4 additions & 2 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"golang.org/x/time/rate"
)

// Config contains the configuration options of the ETH protocol.
Expand Down Expand Up @@ -376,9 +377,10 @@ func (s *Ethereum) APIs() []rpc.API {
apis = append(apis, s.engine.APIs(s.BlockChain())...)

// Append any Sequencer APIs as enabled
if s.config.RollupSequencerEnableTxConditional {
if s.config.RollupSequencerTxConditionalEnabled {
log.Info("Enabling eth_sendRawTransactionConditional endpoint support")
apis = append(apis, sequencerapi.GetSendRawTxConditionalAPI(s.APIBackend, s.seqRPCService))
costRateLimit := rate.Limit(s.config.RollupSequencerTxConditionalCostRateLimit)
apis = append(apis, sequencerapi.GetSendRawTxConditionalAPI(s.APIBackend, s.seqRPCService, costRateLimit))
}

// Append all the local APIs and return
Expand Down
15 changes: 8 additions & 7 deletions eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,14 @@ type Config struct {
// ApplySuperchainUpgrades requests the node to load chain-configuration from the superchain-registry.
ApplySuperchainUpgrades bool `toml:",omitempty"`

RollupSequencerHTTP string
RollupSequencerEnableTxConditional bool
RollupHistoricalRPC string
RollupHistoricalRPCTimeout time.Duration
RollupDisableTxPoolGossip bool
RollupDisableTxPoolAdmission bool
RollupHaltOnIncompatibleProtocolVersion string
RollupSequencerHTTP string
RollupSequencerTxConditionalEnabled bool
RollupSequencerTxConditionalCostRateLimit int
RollupHistoricalRPC string
RollupHistoricalRPCTimeout time.Duration
RollupDisableTxPoolGossip bool
RollupDisableTxPoolAdmission bool
RollupHaltOnIncompatibleProtocolVersion string
}

// CreateConsensusEngine creates a consensus engine for the given chain config.
Expand Down
21 changes: 17 additions & 4 deletions internal/sequencerapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"golang.org/x/time/rate"
)

var (
Expand All @@ -22,14 +23,18 @@ var (
)

type sendRawTxCond struct {
b ethapi.Backend
seqRPC *rpc.Client
b ethapi.Backend
seqRPC *rpc.Client
costLimiter *rate.Limiter
}

func GetSendRawTxConditionalAPI(b ethapi.Backend, seqRPC *rpc.Client) rpc.API {
func GetSendRawTxConditionalAPI(b ethapi.Backend, seqRPC *rpc.Client, costRateLimit rate.Limit) rpc.API {
// Applying a manual bump to the burst to allow conditional txs to queue. Metrics will
// will inform of adjustments that may need to be made here.
costLimiter := rate.NewLimiter(costRateLimit, 3*params.TransactionConditionalMaxCost)
return rpc.API{
Namespace: "eth",
Service: &sendRawTxCond{b, seqRPC},
Service: &sendRawTxCond{b, seqRPC, costLimiter},
}
}

Expand Down Expand Up @@ -83,6 +88,14 @@ func (s *sendRawTxCond) SendRawTransactionConditional(ctx context.Context, txByt
}
}

// enforce rate limit on the cost to be observed
if err := s.costLimiter.WaitN(ctx, cost); err != nil {
anacrolix marked this conversation as resolved.
Show resolved Hide resolved
return common.Hash{}, &rpc.JsonError{
Message: fmt.Sprintf("cost %d rate limited", cost),
Code: params.TransactionConditionalCostExceededMaxErrCode,
}
}

tx := new(types.Transaction)
if err := tx.UnmarshalBinary(txBytes); err != nil {
return common.Hash{}, err
Expand Down
6 changes: 0 additions & 6 deletions miner/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
"golang.org/x/time/rate"
)

// Backend wraps all methods required for mining. Only full node is capable
Expand Down Expand Up @@ -87,9 +86,6 @@ type Miner struct {
pendingMu sync.Mutex // Lock protects the pending block

backend Backend

// TransactionConditional safegaurds
conditionalLimiter *rate.Limiter
}

// New creates a new miner with provided config.
Expand All @@ -102,8 +98,6 @@ func New(eth Backend, config Config, engine consensus.Engine) *Miner {
txpool: eth.TxPool(),
chain: eth.BlockChain(),
pending: &pending{},
// setup the rate limit imposed on conditional transactions when block building
conditionalLimiter: rate.NewLimiter(rate.Limit(config.RollupTransactionConditionalRateLimit), params.TransactionConditionalMaxCost),
}
}

Expand Down
21 changes: 1 addition & 20 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ const (
)

var (
errTxConditionalInvalid = errors.New("transaction conditional failed")
errTxConditionalRateLimited = errors.New("transaction conditional rate limited")
errTxConditionalInvalid = errors.New("transaction conditional failed")

errBlockInterruptedByNewHead = errors.New("new head arrived while building block")
errBlockInterruptedByRecommit = errors.New("recommit interrupt while building block")
Expand Down Expand Up @@ -297,16 +296,6 @@ func (miner *Miner) commitTransaction(env *environment, tx *types.Transaction) e

// If a conditional is set, check prior to applying
if conditional := tx.Conditional(); conditional != nil {
now, cost := time.Now(), conditional.Cost()
res := miner.conditionalLimiter.ReserveN(now, cost)
if !res.OK() {
return fmt.Errorf("exceeded rate limiter burst: cost %d, burst %d: %w", cost, miner.conditionalLimiter.Burst(), errTxConditionalInvalid)
}
if res.Delay() > 0 {
res.Cancel()
return fmt.Errorf("exceeded rate limit: cost %d, available tokens %f: %w", cost, miner.conditionalLimiter.Tokens(), errTxConditionalRateLimited)
}

txConditionalMinedTimer.UpdateSince(tx.Time())

// check the conditional
Expand Down Expand Up @@ -462,14 +451,6 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
log.Warn("Skipping account, transaction with failed conditional", "sender", from, "hash", ltx.Hash, "err", err)
txs.Pop()

case errors.Is(err, errTxConditionalRateLimited):
// err contains contextual info of the cost and limiter tokens available
txConditionalRejectedCounter.Inc(1)

// note: we do not mark the tx as rejected as it is still eligible for inclusion at a later time
log.Warn("Skipping account, transaction with conditional rate limited", "sender", from, "hash", ltx.Hash, "err", err)
txs.Pop()

case errors.Is(err, nil):
// Everything ok, collect the logs and shift in the next transaction from the same account
txs.Shift()
Expand Down
Loading