-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
docs: ADR-60 Prepare & Process Proposal #12838
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work on this ADR! Although I know this is a work in progress, I just wanted to leave some thoughts I had while reading the draft
Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will provide a final link to the v0.37.x spec when available so you can replace the links in this document.
accept, reject, or completely ignore some or all of these transactions. This is | ||
an important consideration to make as the application can essentially define and | ||
control its own mempool allowing it to define sophisticated transaction priority | ||
and filtering mechanisms, by completely ignoring the `TxRecords` Tendermint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: It is the input parameter that you would be ignoring, which is of type bytes
, not TxRecords
|
||
It is important to note that in this phase of ABCI++ integration, the application | ||
is NOT responsible for locking semantics -- Tendermint will still be responsible | ||
for that. In the future, however, the application will be responsible for locking, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, although this was no longer true in v0.36.x, it's (again) accurate for v0.34.x, and therefore for v0.37.x.
We have no plans to play the the locks before releasing v0.37.x.
|
||
Prior to describing the implementation of the two new methods, it is important to | ||
note that the existing ABCI methods, `CheckTx`, `DeliverTx`, etc, still exist and | ||
serve the same functions as they do now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
serve the same functions as they do now. | |
serve the same functions as they do now. Note that the functions of `CheckTx` are extended (see next section). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it somewhat confusing to state that "CheckTx
serves the same functions as now". IIUC, CheckTx
will serve more functions in the new design.
In contrast, the paragraph in lines 56-59 is accurate. Consider adding a sentence similar to the one suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CheckTx
does serve the same function -- tx ante validation, with the added responsibility of mempool insertion/eviction which I mentioned in the ADR.
// casting can be used in the actual mempool implementation. | ||
type MempoolTx interface { | ||
// Size returns the size of the transaction in bytes. | ||
Size(codec.Codec) int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the role of the method's parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The godoc describes it. It will be used for reaping and eviction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @sergio-mena meant why we need a codec here. It's maybe worth putting that in the godoc too.
`PrepareProposal`, since `ProcessProposal` can fail and we do not want to lose | ||
transactions, we need to finally remove the transaction from the app-side mempool | ||
during `DeliverTx` since during this phase, the transactions are being included | ||
in the proposed block. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably none of my business, but have you considered something like a TTL to make sure every transaction is eventually removed from the app-side mempool (e.g., to prevent corner-case TXs from filling up the mempool over time)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure there is a direct need for a TTL as we already have a similar notion on txs directly and the mempool will be capped (by tx size).
Co-authored-by: Sergio Mena <sergio@informal.systems>
Co-authored-by: Sergio Mena <sergio@informal.systems>
Co-authored-by: Sergio Mena <sergio@informal.systems>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, only thing missing it seems is the added unmodified stuff tendermint needs. Id prefer to avoid this but seems like we cant
Previous discussions<sup>1</sup> have come to the agreement that Tendermint will | ||
perform a request to the application, via `RequestPrepareProposal`, with a certain | ||
amount of transactions reaped from Tendermint's local mempool. The exact amount | ||
of transactions reaped will be determined by a local operator configuration. | ||
This is referred to as the "one-shot approach" seen in discussions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the mempool has more transactions than requested, what determines which ones are reaped?
edit: oh, sorry, is this line 119?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's however the mempool wants to define this behavior -- e.g. the lower priority ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it's a Tendermint config option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the application defines the mempool entirely. We will provide a basic one out of the box, whereas applications can define their own if the default one does not suite their needs (e.g. dYdX).
// PrepareTxRecord defines a wrapper around a MempoolTx that is returned from | ||
// PrepareProposal which includes an Action to inform Tendermint what to do with | ||
// the transaction. | ||
type PrepareTxRecord[T MempoolTx] struct { | ||
Tx T | ||
Action abci.TxAction | ||
} | ||
|
||
type Mempool[T MempoolTx] interface { | ||
// Insert attempts to insert a MempoolTx into the app-side mempool returning | ||
// an error upon failure. | ||
Insert(sdk.Context, T) error | ||
// ReapMaxBytes returns the next set of available transactions from the app-side | ||
// mempool, up to maxBytes or until the mempool is empty. The application can | ||
// decide to return transactions from its own mempool or from the incoming | ||
// TxRecords or some combination of both. The notion of 'available' or 'next' | ||
// is defined by the application's mempool implementation. | ||
ReapMaxBytes(ctx sdk.Context, txRecords abci.TxRecords, maxBytes int) ([]PrepareTxRecord[T], error) | ||
// NumTxs returns the number of transactions currently in the mempool. | ||
NumTxs() int | ||
// Remove attempts to remove a transaction from the mempool, returning an error | ||
// upon failure. | ||
Remove(sdk.Context, T) error | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MempoolTx is a regular old interface, right? If so, why bring generics into the picture, versus e.g.
type PrepareTxRecord struct {
Tx MempoolTx
Action abci.TxAction
}
type Mempool interface {
Insert(sdk.Context, MempoolTx) error
ReapMaxBytes(ctx sdk.Context, txRecords abci.TxRecords, maxBytes int) ([]PrepareTxRecord, error)
NumTxs() int
Remove(sdk.Context, MempoolTx) error
}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This won't work directly, of course -- the Remove method implicitly requires that MempoolTx values are comparable, which isn't true at the moment.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I mentioned in a comment above from @williambanfield -- there really isn't a need for generics per se.
|
||
The `PrepareProposal` ABCI method is concerned with a block proposer requesting | ||
the application to evaluate a series of transactions to be included in the next | ||
block, defined as a slice of `TxRecord` objects. The application can either |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
block, defined as a slice of `TxRecord` objects. The application can either | |
block, defined as a slice of [`TxRecord`](todo) objects. The application can either |
Can we add a link to what a TxRecord
is?
// casting can be used in the actual mempool implementation. | ||
type MempoolTx interface { | ||
// Size returns the size of the transaction in bytes. | ||
Size(codec.Codec) int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @sergio-mena meant why we need a codec here. It's maybe worth putting that in the godoc too.
* add layout for abci++ inclusion * prepare proposal * fix doc * updates Co-authored-by: Aleksandr Bezobchuk <aleks.bezobchuk@gmail.com> Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com> Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com> Co-authored-by: Sergio Mena <sergio@informal.systems>
Description
Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
!
to the type prefix if API or client breaking changeCHANGELOG.md
Reviewers Checklist
All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.
I have...
!
in the type prefix if API or client breaking change