fix: Count partial batch progress in a TX-set reply - #8091
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves TransactionAcquire::takeNodes() accounting so partial success in a TX-set node batch is preserved (good nodes counted) even when the batch ends with a bad node, and “progress” is recorded based on actual map advancement rather than “overall good.” This aligns TX-set acquisition behavior with how inbound ledger node batches are already handled.
Changes:
- Refactors
TransactionAcquire::takeNodes()to delegate totakeNodesLocked()and record progress on a single exit path based onSHAMapAddNode::isUseful(). - Accumulates a combined
SHAMapAddNodeverdict across the whole batch, including explicit duplicate counting for an already-held root. - Updates
InboundTransactions::gotData()to charge useless-data fees based on!san.isGood()(so duplicate-only replies are not charged) and adds a focused regression test.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/xrpld/app/ledger/detail/TransactionAcquire.h | Documents batch-level verdict semantics and introduces takeNodesLocked() for single-exit progress recording. |
| src/xrpld/app/ledger/detail/TransactionAcquire.cpp | Implements batch verdict accumulation, early-exit returns that preserve prior counts, and progress recording only when the batch added nodes. |
| src/xrpld/app/ledger/detail/InboundTransactions.cpp | Adjusts useless-data charging to use isGood() so duplicate-only replies aren’t penalized while empty/unprocessed replies still are. |
| src/test/app/TransactionAcquire_test.cpp | Adds testPartialBatchIsCounted to validate partial-batch tallying, duplicate handling, and progress flag behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
e3b71c1 to
947fac1
Compare
947fac1 to
eacc0e4
Compare
eacc0e4 to
f325d1e
Compare
f325d1e to
838f6c0
Compare
838f6c0 to
b17ba18
Compare
|
This PR has conflicts, please resolve them in order for the PR to be reviewed. |
b17ba18 to
268450b
Compare
|
All conflicts have been resolved. Assigned reviewers can now start or resume their review. |
|
This PR has conflicts, please resolve them in order for the PR to be reviewed. |
268450b to
15e802f
Compare
|
All conflicts have been resolved. Assigned reviewers can now start or resume their review. |
1 similar comment
|
All conflicts have been resolved. Assigned reviewers can now start or resume their review. |
15e802f to
f9b64b8
Compare
TransactionAcquire::takeNodes() now accumulates one SHAMapAddNode across the whole batch, so a packet ending on one bad node still counts the nodes hooked in ahead of it, matching InboundLedger::receiveNode(). The body moves to takeNodesLocked(); takeNodes() becomes a thin wrapper that records progress once, on the single exit, since several inner exits stop the batch early. Progress turns on the batch being useful rather than merely good, so an all-duplicate batch - an honest second responder to trigger()'s fan-out - records none but still isn't charged.
f9b64b8 to
9c62a52
Compare
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Part 12/16 of a stack. Base: part 11 (
bthomee/shamap-invalid-11-revive-timer).High Level Overview of Change
TransactionAcquire::takeNodes()now accumulates one combined verdict across a whole batch instead ofstopping at the first bad node, so a packet that ends badly still gets credit — and clears the
timeout-postponing progress flag — for the good nodes ahead of it, matching what
InboundLedger::receiveNode()already does.Context of Change
TransactionAcquire::takeNodes()accumulates oneSHAMapAddNodeacross the batch and hands it back, soa packet ending on one bad node still counts the nodes hooked in ahead of it. A root the set already
holds counts as a duplicate rather than passing unremarked, which is what tells a batch of nodes we
already have from one that was never examined at all.
The body moves to
takeNodesLocked()andtakeNodes()becomes a thin wrapper that takes the lock andrecords what the batch achieved on the one exit — several of the inner exits stop the batch early, and
nothing in the compiler catches one that forgets to record progress. Progress turns on the batch being
useful rather than good, so a batch of nothing but duplicates records none: that flag is what keeps the
next timer tick from counting a timeout, and a reply carrying nothing new advanced nothing. It costs
retry budget on the ordinary second responder to a fan-out and nothing else.
InboundTransactions::gotData()asksisGood()rather thanisUseful()for the useless-data charge,which keeps that duplicate free — now that the verdict distinguishes a duplicate from an empty tally,
the useful test would charge for it while the batch that was never examined still needs charging.
testPartialBatchIsCountedfeeds two good nodes followed by one at a position it cannot occupy, andchecks the verdict names both halves and that the flag is set; then a batch of nothing but a root
already held, checking it is good, not useful, and records nothing; then that root alongside a node the
set does need, checking the duplicate is reported as one while the other records the progress.
API Impact
None of the checkboxes below apply: this is an internal
xrpldcorrectness fix with nolibxrpl,public-API, or peer-protocol surface.