Skip to content
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

Unify fee-based transaction comparisions #3508

Merged
merged 7 commits into from
Sep 15, 2022

Conversation

dmkozh
Copy link
Contributor

@dmkozh dmkozh commented Aug 17, 2022

Description

This introduces a common data structure (SurgePricingPriorityQueue) that orders the transactions by the fee rate and is aware of operation limits. This data structure is then used in the 3 places that do fee-based transaction comparisons: TransactionQueue, TxQueueLimiter and TxSetFrame.

The refactoring is functionally a no-op and serves as a preparation for introducing more complex transaction comparison logic.

Checklist

  • Reviewed the contributing document
  • Rebased on top of master (no merge commits)
  • Ran clang-format v8.0.0 (via make format or the Visual Studio extension)
  • Compiles
  • Ran all tests
  • If change impacts performance, include supporting evidence per the performance document

Copy link
Contributor

@MonsieurNicolas MonsieurNicolas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good - only thing I flagged is wrt canFitWithEviction that makes too many assumptions

releaseAssert(iter != mTxStackSet.end());
auto const& evictTxStack = *iter;
auto const& evictTx = *evictTxStack->getTopTx();
auto evictOps = evictTxStack->getNumOperations();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method (canFitWithEviction) should not be in this class, or should be written differently:
what that code does is use the top tx evictTx to decide on evicting the entire stack (and the code in , which does not make sense in the general case, and only in the context of TxQueueLimiter that right now uses SingleTxStack.
If we want to keep it in here, the challenge (I think) is that you can't really iterate over txs in stacks without popping.

Copy link
Contributor Author

@dmkozh dmkozh Aug 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what that code does is use the top tx evictTx to decide on evicting the entire stack

Well, that's the invariant of this method and it happens to work for TxQueueLimiter. I can't say it's incorrect for seq num based stack implementations, as the same invariant would be maintained (whether it's useful or not is up to the caller; currently I guess we know we don't need to reuse it).

I cannot say I'm 100% happy with this class, however I think it's a decent option. The set of supported operations is indeed bespoke and isn't too abstract. This is due to the fact that we have quite specific use cases and there is only so much in common between them. In order to support the upcoming functionality I wanted to encapsulate as much logic as possible in these methods and let as little internals to be exposed as possible. The implementation with lanes is more involved in terms of using the internal structures.

I guess we could make the queue to be 'low-level' data structure that exposes the internals and then a wrapper data structure to be used in TxQueueLimiter with SingleTxStack only. However, I'm not sure how much value does that provide, given that the complexity still lies in the iteration methods. I'd also still rather keep the logic in SurgePricingUtils so that there is a single source for all surge-pricing related stuff.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked offline about potentially getting rid of the "transaction chains" per account in the future, so I think it's fine to keep the code as is. As right now we have no use cases for this method outside of the SingleTxStack, and to avoid surprises if we were to use it in a different context, I think we should just add an assert that there is only one tx in the stack:

        auto const& evictTx = *evictTxStack->getTopTx();
        auto evictOps = evictTxStack->getNumOperations();
        releaseAssert(evictOps == evictTx.getNumOperations());

what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SG, added the assertion.

src/herder/TxQueueLimiter.cpp Show resolved Hide resolved
src/herder/TxQueueLimiter.cpp Show resolved Hide resolved
src/herder/TxQueueLimiter.cpp Outdated Show resolved Hide resolved
src/herder/TxSetFrame.cpp Outdated Show resolved Hide resolved
src/herder/TransactionQueue.cpp Show resolved Hide resolved
src/herder/test/TransactionQueueTests.cpp Show resolved Hide resolved
Copy link
Contributor

@MonsieurNicolas MonsieurNicolas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one suggestion in the only open comment left. We can rebase & squash it as it's pretty much ready to merge

…ons.

The priority queue allows ranking transactions/transaction stacks (seq num ordered) by fee rate and limit the amount of operations.

This replaces 3 existing implementations of surge-pricing-based comparisons and has special operations to support their use cases:
- Building the `TxSetFrame` from transactions via selecting highest fee rate transactions
- Limiting the transactions in `TxQueueLimiter` via evicting lowest fee rate transactions
- Broadcasting the transactions in 'TransactionQueue` via selecting highest fee rate transactions

The respective user changes are in the followup commits.
Noticed this while checking the refactored code.
…QueueLimiter`.

Instead of explicitly looking at the limiter size, verify how many operations were evicted (this also generally improves coverage).

Instead of explicitly looking at the minimum fee stored in limiter, make sure that we can (or can not) add transaction at the fee threshold.
@dmkozh
Copy link
Contributor Author

dmkozh commented Sep 14, 2022

Left one suggestion in the only open comment left. We can rebase & squash it as it's pretty much ready to merge

I've rebased & squashed, just need to wait for the checks to pass.

@MonsieurNicolas MonsieurNicolas added this to In progress in v19.4.0 via automation Sep 14, 2022
@MonsieurNicolas
Copy link
Contributor

r+ 9d3ce58

@latobarita latobarita merged commit a388b5e into stellar:master Sep 15, 2022
v19.4.0 automation moved this from In progress to Done Sep 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

3 participants