-
Notifications
You must be signed in to change notification settings - Fork 23
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
Consolidate TxLimits #1175
Consolidate TxLimits #1175
Conversation
ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Eras.hs
Outdated
Show resolved
Hide resolved
...-consensus/src/ouroboros-consensus/Ouroboros/Consensus/MiniProtocol/LocalTxMonitor/Server.hs
Outdated
Show resolved
Hide resolved
...nsus/src/ouroboros-consensus/Ouroboros/Consensus/HardFork/Combinator/Abstract/CanHardFork.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Update.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Init.hs
Outdated
Show resolved
Hide resolved
f2f942b
to
604c811
Compare
ouroboros-consensus/test/consensus-test/Test/Consensus/Mempool.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Ledger/Forge.hs
Outdated
Show resolved
Hide resolved
Phew! I think it's compiling without warnings and I'm optimistic the tests will pass on CI. But the commit history is a total mess, and some new comments are missing, at the very least. |
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Capacity.hs
Outdated
Show resolved
Hide resolved
I also have some questions about what the |
6a9ec88
to
fb968f8
Compare
I rebased |
fb968f8
to
489476f
Compare
The next step for this PR is to merge #1182. Eventually I'll rebase this one on top of that. |
282735a
to
cedd6f7
Compare
I don't know if we want to merge this before the Chang fork, so this remains in Draft.
I'm not surprised the benchmark itself is a bit slower: the arithmetic in the mempool are now routed through dictionaries, since the size (it's just I'm pretty sure the setup is ~3x slower just because I'm using |
288ccbb
to
ccfc73b
Compare
87f7f18
to
a866dbb
Compare
OK. I added a few commits, after chatting with Esgen.
The last one supersedes the middle one. The last's commit message already asserting the performance penalty is acceptable, but this deserves some due diligence. I have a relatively simple idea for that: use (a trivial new) db-analyser to emit the (new) TxMeasure for two recent epochs from mainnet. Build a benchmark that simply adds and removes "transactions" that are nothing except one of those recorded measurements (in the same order as observed on mainnet). This can be done at the Such a benchmark will yield a characteristic cost (eg "total runtime / number of txs"), which I'm hoping/expecting will be quite smaller than the (comparably averaged) cost of fully validating a tx. |
9ed2a72
to
94de084
Compare
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Update.hs
Outdated
Show resolved
Hide resolved
I haven't yet reorganized the commits into a nice sequence yet, but review can commence --- I will ensure the final diff matches that of the current tip (ie fe778a3) |
I'm now attempting to split the monolithic commit. I consider it to have the following components.
I'm hoping I can tease out a separate commit for at least a few of those. Edit: I pulled out a couple. Especially the one that removes |
f15f603
to
a7bd1c5
Compare
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.
Excellent 🎉
Only minor comments
ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Ledger/Mempool.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Ledger/Mempool.hs
Outdated
Show resolved
Hide resolved
...-consensus-cardano/src/unstable-cardano-testlib/Test/ThreadNet/Infra/ShelleyBasedHardFork.hs
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/HardFork/Combinator/Mempool.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Ledger/SupportsMempool.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Ledger/SupportsMempool.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Ledger/SupportsMempool.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/TxSeq.hs
Outdated
Show resolved
Hide resolved
ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Update.hs
Show resolved
Hide resolved
a7bd1c5
to
88e8bfd
Compare
Some collisions with |
703c758
to
2f5f06c
Compare
2f5f06c
to
6ad371d
Compare
The
Joris helpfully shared the numbers from the latest baseline file:
The failing case is the setup step, which increases from 500 nanoseconds to 1750 nanoseconds. It is very plausible that the additional calculation in So I'm merging despite these failures --- they are not required "checks" and this benchmark is the only FAIL within the checks. |
BoundedMeasure is no longer necessary, as of PR #1182.
The 'LedgerSupportsMempool.txInBlockSize' method suffices, and is already in scope within the mempool itself. Adding sizes to the `MempoolSnapshot` interface replaces the other use of `getTxSize`, in the `NodeKernel`.
Transaction size, block capacity, and mempool capacity are multi-dimensional vectors (incl ExUnits, etc), instead of merely bytes: see `TxMeasure`. `TxLimits` has fittingly been promoted from the `Capacity` module to the proper `SupportsMempool` module, cannibalizing some methds from the `LedgerSupporstMempool` class. A transaction cannot be added if it would push any component of the size over that component's capacity. The capacity override is still only specified in byte size, but the value is interpreted as a block count (rounded up). Enforce block capacity _before_ the forging logic. Now the forging logic simply includes whatever transactions its given, which is reasonable and simpler. It's the NodeKernel logic that uses the mempool's finger tree in order to slice an appropriately-sized prefix, which is then passed to the now-dumb forging function. Explicit attention is given to overflow and the DoS vector of providing an erroneously massive tx that would block the mempool's growth, were it not for the new guards. Also, anachronistically use ConwayMeasure in Babbage, since it should have been counting ref script bytes, as Conway now does. Many comments are improved and also updated for the new scheme.
6ad371d
to
9c022f3
Compare
Closes #1226 In addition to the previously valid/invalid txs (purely based on the UTxO ledger rules), we add an optional per-tx limit to the mock block. As a second step, we generate very large txs that are larger than an entire mempool, in order to test that we do *not* block when adding them (just like the other txs), which is important as explained in #1226. --- One way to validate this PR is to introduce a bug that would cause us to block on such transactions, and observe that the test now indeed catches that. For example, retrying when the per-tx limited is not satisfied (this is basically what happened in #1168 and was fixed by #1225) via ```diff diff --git a/ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Update.hs b/ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Update.hs index 372ea15c29..31abe25fbf 100644 --- a/ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Update.hs +++ b/ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Update.hs @@ -170,25 +170,8 @@ pureTryAddTx :: -> TryAddTx blk pureTryAddTx cfg wti tx is = case runExcept $ txMeasure cfg (isLedgerState is) tx of - Left err -> - -- The transaction does not have a valid measure (eg its ExUnits is - -- greater than what this ledger state allows for a single transaction). - -- - -- It might seem simpler to remove the failure case from 'txMeasure' and - -- simply fully validate the tx before determining whether it'd fit in - -- the mempool; that way we could reject invalid txs ASAP. However, for a - -- valid tx, we'd pay that validation cost every time the node's - -- selection changed, even if the tx wouldn't fit. So it'd very much be - -- as if the mempool were effectively over capacity! What's worse, each - -- attempt would not be using 'extendVRPrevApplied'. - TryAddTx - Nothing - (MempoolTxRejected tx err) - (TraceMempoolRejectedTx - tx - err - (isMempoolSize is) - ) + Left _err -> + NotEnoughSpaceLeft Right txsz -- Check for overflow -- ``` or here ```diff diff --git a/ouroboros-consensus/src/unstable-mock-block/Ouroboros/Consensus/Mock/Ledger/Block.hs b/ouroboros-consensus/src/unstable-mock-block/Ouroboros/Consensus/Mock/Ledger/Block.hs index 743e11bc61..e01d8cfe5a 100644 --- a/ouroboros-consensus/src/unstable-mock-block/Ouroboros/Consensus/Mock/Ledger/Block.hs +++ b/ouroboros-consensus/src/unstable-mock-block/Ouroboros/Consensus/Mock/Ledger/Block.hs @@ -452,10 +452,7 @@ instance TxLimits (SimpleBlock c ext) where -- But not 'maxbound'!, since the mempool sometimes holds multiple blocks worth. blockCapacityTxMeasure _cfg _st = IgnoringOverflow simpleBlockCapacity - txMeasure cfg _st = - fmap IgnoringOverflow - . checkTxSize (simpleLedgerMockConfig cfg) - . simpleGenTx + txMeasure _cfg _st = pure . IgnoringOverflow . txSize . simpleGenTx simpleBlockCapacity :: ByteSize32 simpleBlockCapacity = ByteSize32 512 ``` will cause many test failures with `FailureDeadlock [Labelled (ThreadId []) (Just "main")]'` via `io-sim`'s nice deadlock detection. --- Stacked on top of #1175 to avoid boring rebase work
Closes #1177.
Beyond that Issue, this PR also changes the mempool's definition of full. The mempool will accepte transactions until the tx chosen to next enter the mempool would cause any component of the capacity vector (byte size, exunit steps, exunit mems, ref script byte size) to exceed its limit. The default capacity is chosen as twice the capacity of a block. Such a capacity can admit more txs than could fit into two back-to-back blocks, but no single component (eg ExUnits) of the mempool's contents' size could exceed what could fit in two blocks.
The mempool capacity has two consequences.
Also closes #1168 by superseding the "ad-hoc" mempool reference scripts capacity limit.
This PR also moves the logic for choosing which prefix of the mempool to put in the block out of the forging functions and into the NodeKernel forging thread --- the mempool snapshot is the perfect place to do that, since tx measurements (each using the correct ledger state) are already determined.