摘要
本节介绍如何使用和替换应用侧 mempool。
v0.47 起,应用程序拥有了自己的 mempool,从而能够比此前版本更细粒度地构建区块。该变更由
ABCI 1.0
启用。尤其是,它引入了 ABCI++ 的 PrepareProposal 和 ProcessProposal 步骤。
概述
应用程序 mempool 是应用内部进程中的交易存储,用于让开发者控制交易的排序方式以及如何选择交易纳入区块。与在网络层处理交易接收与 gossip 的 CometBFT mempool 不同,SDK 的应用 mempool 在区块提案阶段运行,用于决定区块内交易的排列顺序。 当一笔交易被提交到节点时,CometBFT 会先接收它。CometBFT 会调用应用的CheckTx 来验证交易,然后将其存入自己的 mempool(默认是 flood mempool),并将其 gossip 给对等节点。
当需要构建区块时,CometBFT 会调用应用的 PrepareProposal。这正是 SDK 应用 mempool 发挥作用的地方:应用会从自己的内部 mempool 中取出交易,并决定将哪些交易纳入区块,以及它们的顺序应该如何安排,例如按优先级、nonce、手续费,或开发者自定义的任意逻辑。
因此,CometBFT 决定哪些交易能够被网络接受;SDK 应用 mempool 决定这些已被接受的交易在区块内如何排序。
Mempool
应用开发者可以为 mempool 设计出无数种方案,SDK 选择仅提供一些简单的 mempool 实现。 具体来说,SDK 提供以下 mempool: 默认情况下,SDK 使用的是空操作 Mempool,但应用开发者可以在app.go 中将其替换:
空操作 Mempool
空操作 mempool 是一种 mempool:当 BaseApp 与其交互时,交易会被完全丢弃并忽略。 使用这种 mempool 时,默认假定应用会依赖 CometBFT 在RequestPrepareProposal 中定义的交易顺序,该顺序默认是 FIFO。
注意:如果使用 NoOp mempool,PrepareProposal和ProcessProposal都应意识到这一点, 因为PrepareProposal可能会包含一些在ProcessProposal中校验失败的交易。
发送者 Nonce Mempool
nonce mempool 会按 nonce 排序保存交易,以避免 nonce 相关问题。 它会将交易存入一个按交易 nonce 排序的列表。当提议者请求将交易纳入区块时,它会随机选择一个发送者,并取出该列表中的第一笔交易。这个过程会不断重复,直到 mempool 为空或区块已满。 它支持以下配置参数:MaxTxs
这是一个整数值,可将 mempool 设为以下三种模式之一:有界、无界 或 禁用。- negative:禁用,mempool 不会插入新交易并会提前返回。
- zero:无界,mempool 没有交易数量限制,也永远不会因为
ErrMempoolTxMaxCapacity而失败。 - positive:有界,当
maxTx的值与CountTx()相同时,会因为ErrMempoolTxMaxCapacity而失败。
Seed
设置随机数生成器的种子,该生成器用于从 mempool 中选择交易。优先级 Nonce Mempool
优先级 nonce mempool 是一种 mempool 实现,它会按两个维度组成的偏序集合来存储交易:- priority
- sender-nonce(序列号)
MaxTxs
这是一个整数值,可将 mempool 设为以下三种模式之一:有界、无界 或 禁用。- negative:禁用,mempool 不会插入新交易并会提前返回。
- zero:无界,mempool 没有交易数量限制,也永远不会因为
ErrMempoolTxMaxCapacity而失败。 - positive:有界,当
maxTx的值与CountTx()相同时,会因为ErrMempoolTxMaxCapacity而失败。
Callback
优先级 nonce mempool 提供了 mempool 选项,允许应用设置回调函数。- OnRead:设置当交易从 mempool 中被读取时调用的回调。
- TxReplacement:设置当 mempool 插入时检测到重复交易 nonce 时调用的回调。应用可以基于交易优先级或某些交易字段定义交易替换规则。
Synopsis
This section describes how the app-side mempool can be used and replaced.
v0.47 the application has its own mempool to allow much more granular
block building than previous versions. This change was enabled by
ABCI 1.0.
Notably it introduces the PrepareProposal and ProcessProposal steps of ABCI++.
Overview
The application mempool is an in-process transaction store within the application that gives developers control over how transactions are ordered and selected for block inclusion. Unlike the CometBFT mempool, which handles transaction receipt and gossip at the network layer, the SDK’s application mempool operates at block proposal time to determine the ordering of transactions within a block. When a transaction is submitted to a node, CometBFT receives it first. CometBFT callsCheckTx on the application to validate the transaction, then stores it
in its own mempool (the flood mempool by default) and gossips it to peers.
When it is time to build a block, CometBFT calls PrepareProposal on the
application. This is where the SDK app mempool comes in: the application pulls
from its own internal mempool and decides which transactions to include and in
what order: by priority, nonce, fees, or any custom logic the developer
chooses.
So CometBFT decides what gets accepted into the network; the SDK app mempool
decides how accepted transactions are ordered within a block.
Mempool
There are countless designs that an application developer can write for a mempool, the SDK opted to provide only simple mempool implementations. Namely, the SDK provides the following mempools: By default, the SDK uses the No-op Mempool, but it can be replaced by the application developer in [app.go:
No-op Mempool
A no-op mempool is a mempool where transactions are completely discarded and ignored when BaseApp interacts with the mempool. When this mempool is used, it is assumed that an application will rely on CometBFT’s transaction ordering defined inRequestPrepareProposal,
which is FIFO-ordered by default.
Note: If a NoOp mempool is used, PrepareProposal and ProcessProposal both should be aware of this as PrepareProposal could include transactions that could fail verification in ProcessProposal.
Sender Nonce Mempool
The nonce mempool is a mempool that keeps transactions from an sorted by nonce in order to avoid the issues with nonces. It works by storing the transaction in a list sorted by the transaction nonce. When the proposer asks for transactions to be included in a block it randomly selects a sender and gets the first transaction in the list. It repeats this until the mempool is empty or the block is full. It is configurable with the following parameters:MaxTxs
It is an integer value that sets the mempool in one of three modes, bounded, unbounded, or disabled.- negative: Disabled, mempool does not insert new transaction and return early.
- zero: Unbounded mempool has no transaction limit and will never fail with
ErrMempoolTxMaxCapacity. - positive: Bounded, it fails with
ErrMempoolTxMaxCapacitywhenmaxTxvalue is the same asCountTx()
Seed
Set the seed for the random number generator used to select transactions from the mempool.Priority Nonce Mempool
The priority nonce mempool is a mempool implementation that stores txs in a partially ordered set by 2 dimensions:- priority
- sender-nonce (sequence number)
MaxTxs
It is an integer value that sets the mempool in one of three modes, bounded, unbounded, or disabled.- negative: Disabled, mempool does not insert new transaction and return early.
- zero: Unbounded mempool has no transaction limit and will never fail with
ErrMempoolTxMaxCapacity. - positive: Bounded, it fails with
ErrMempoolTxMaxCapacitywhenmaxTxvalue is the same asCountTx()
Callback
The priority nonce mempool provides mempool options allowing the application sets callback(s).- OnRead: Set a callback to be called when a transaction is read from the mempool.
- TxReplacement: Sets a callback to be called when duplicated transaction nonce detected during mempool insert. Application can define a transaction replacement rule based on tx priority or certain transaction fields.