Skip to Content
EVMTx Prioritizer

Transaction Prioritizer

Sei now ships a dedicated transaction prioritizer. Rather than scattering priority tweaks across Ante handlers, the app answers a focused ABCI call—GetTxPriorityHint—whenever Tendermint’s mempool nears capacity. This page nails down the priority tiers, the knobs exposed in sei-chain and sei-tendermint@c6c5a8f3, and the checks that prove the system is working.

Surface
abci.GetTxPriorityHint

Fires after utilisation exceeds drop-utilisation-threshold and returns the hint Tendermint uses to admit or reject the tx.

View internal/mempool/mempool.go

Surface
SeiTxPrioritizer

Stateless Cosmos/EVM prioritizer that inspects the tx, validates fees, and emits an int64 hint without touching state.

View app/prioritizer.go

Tiering

OraclePriority > EVMAssociatePriority > fee-derived Cosmos/EVM priority (capped at MaxPriority) keeps mission-critical flows at the front.

View app/prioritizer.go

Version guard

Ships enabled in current releases; older binaries ignore the hook, so mixed-version networks continue to make progress.

View app/app.go

How the Hint Is Calculated

OraclePriority

Oracle votes (MsgAggregateExchangeRateVote) ride with math.MaxInt64 - 100, guaranteeing feeders clear the mempool immediately.

View app/prioritizer.go

EVMAssociatePriority

Unassociated evm_associate calls bypass congestion so UX wallets can link addresses without fee gymnastics.

View app/prioritizer.go

Gas price normalisation

Regular EVM traffic uses priority = gasPrice / priority_normalizer and clamps to MaxPriority so outliers can’t blow up the scale.

View app/prioritizer.go

Cosmos fee fallback

SDK txs reuse GetTxPriority, so whitelisted fee denoms and gas estimates map into the same priority lane.

View app/prioritizer.go

The prioritizer is intentionally pure: it decodes the tx, validates sane fee caps, probes association status, and returns an int64. Panics are caught and logged, and the mempool falls back to priority 0 so attackers cannot halt CheckTx.

From Hint to Eviction

When Tendermint’s mempool utilisation crosses drop-utilisation-threshold, the reactor calls GetTxPriorityHint before deciding whether to drop low-priority transactions. A new reservoir sampler tracks recent hints so the node compares incoming priority against a moving cutoff.

drop-utilisation-thresholdUtilisation ratio that activates hint-based dropping. Default 1.0 (disabled).
drop-priority-thresholdPercentile of hints considered droppable once utilisation triggers. Default 0.1 (bottom 10%).
drop-priority-reservoir-sizeSample size the reservoir keeps to estimate distribution. Default 10240.
Reservoir refreshPercentile cached for 5s; recomputed if new hints arrive. (internal/libs/reservoir/reservoir.go)
[mempool] size = 5000 drop-utilisation-threshold = 0.80 # start hinting once 80% full drop-priority-threshold = 0.20 # shed bottom 20% priority drop-priority-reservoir-size = 8192 # tune for memory vs accuracy

With these values, once the mempool is ≥80% utilised, any new tx with priority below the sampled 20th percentile is rejected with priority not high enough for mempool.

Operator Checklist

Confirm hints flow

seid debug mempool-stats should show priority_cutoff moving under sustained load; if it’s flat, hints aren’t being sampled.

Grafana panel

Alert on CheckTxMetDropUtilisationThreshold and CheckTxDroppedByPriorityHint to spot accidental throttling.

Normalizer sanity

sei q evm params priority-normalizer must stay positive; lock it down in Terraform/Ansible defaults.

RPC parity

Compare eth_pendingTransactions with seid debug mempool-stats; a growing gap usually means clients are retrying after drops.

CLI validation

# Inspect priority reservoir stats seid debug mempool-stats | jq '.priority' # Query EVM priority normalizer (decides gasPrice → hint scaling) seid query evm params | jq -r '.params.priority_normalizer' # Force an associate tx hint seid tx evm associate --from wallet --evm-address <addr> --gas-prices 1usei --gas 120000 --simulate

Developer Considerations

  • SDK integration: Clients may receive priority not high enough for mempool when bursting the chain. Surface this to end users with context (e.g., “bump gas price or retry later”).
  • Fee markets: EIP-1559 style tips (gasTipCap) remain valid; the prioritizer only checks tip ≥ 0 and gasFeeCap ≥ base fee & minimum fee.
  • Panic-proof: The prioritizer recovers from panics and logs tx prioritizer panicked. Falling back on no priority. Instrument alerting on this string.
  • Testing: Unit suite (app/prioritizer_test.go) covers oracle, zero-fee, and multi-denom cases. Extend tests when adding new high-priority msg types.

Troubleshooting

ErrorCauseFix
`priority not high enough for mempool` on legitimate txsReservoir cutoff too aggressive or priority normalizer mis-set.Lower drop-priority-threshold, raise normalizer, or temporarily disable threshold while load stabilises.
Hints always 0priority_normalizer zeroed or prioritizer panic fallback triggered.Verify sei query evm params; check logs for tx prioritizer panicked.
Oracle votes delayedOracle msgs lost special tier (regression).Confirm OraclePriority constant and verify all nodes run a prioritizer-enabled release.
Assoc tx rejected with “already associated”Wallet already linked so prioritizer returns error.Surface clearer UX; instruct signer to send standard tx instead.
Last updated on