Skip to content

Conversation

hvanz
Copy link
Member

@hvanz hvanz commented Jun 28, 2023

Closes #1042
Depends on #1010

In Mempool interface:

  • Add NewIterator for iterating the mempool entries
  • Add SetLogger

Changes in the mempool reactor:

  • NewReactor now takes a Mempool interface as a parameter, instead of CListMempool,
  • replace calls to implementation specific methods such as TxsWaitChan and TxsFront for iterating through CListMempool's entries,
  • remove calls to methods NextWaitChan and Next from mempoolTx.

PR checklist

  • Tests written/updated
  • Changelog entry added in .changelog (we use unclog to manage our changelog)
  • Updated relevant documentation (docs/ or spec/) and code comments

@hvanz hvanz added the mempool label Jun 28, 2023
@hvanz hvanz added this to the 2023-Q3 milestone Jun 28, 2023
@hvanz hvanz self-assigned this Jun 28, 2023
@hvanz hvanz removed this from the 2023-Q3 milestone Jun 29, 2023
Comment on lines 54 to 57
// Concurrent linked-list of valid txs.
// `txsMap`: txKey -> CElement is for quick access to txs.
// Transactions in both `txs` and `txsMap` must to be kept in sync.
txs *clist.CList
Copy link
Contributor

@lasarojc lasarojc Jul 3, 2023

Choose a reason for hiding this comment

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

When generating documentation from code, it will be confusing if the comment is related to two fields. I suggest commenting both, even if there is some redundancy.

Suggested change
// Concurrent linked-list of valid txs.
// `txsMap`: txKey -> CElement is for quick access to txs.
// Transactions in both `txs` and `txsMap` must to be kept in sync.
txs *clist.CList
// Concurrent linked-list of valid txs.
// `txs` must to be kept in sync with `txsMap` .
txs *clist.CList
// `txsMap`: txKey -> CElement is for quick access to txs.
// `txsMap` must to be kept in sync with `txs` .

@hvanz hvanz changed the title mempool: Separate reactor from implementation (WIP) mempool: Separate reactor from implementation Jul 19, 2023
@hvanz hvanz marked this pull request as ready for review July 19, 2023 15:58
@hvanz hvanz requested a review from a team as a code owner July 19, 2023 15:58
@hvanz hvanz requested a review from a team July 19, 2023 15:58
@hvanz hvanz removed the wip Work in progress label Jul 19, 2023
Copy link

@cason cason left a comment

Choose a reason for hiding this comment

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

I would use here the same arguments I have presented for PR #1010:
#1010 (review)

I think we should define and discuss a new mempool API before implementing the (breaking) changes in multiple PRs.

Copy link
Contributor

@lasarojc lasarojc left a comment

Choose a reason for hiding this comment

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

There seems to be a problem in the loop over the transactions, causing transactions to be skipped and violating the expected delivery order.
PR #1153 adds a test to show the problem and addresses the issue by bring the test for nil back.

hvanz and others added 3 commits July 24, 2023 16:01
Co-authored-by: Lasaro <lasaro@informal.systems>
* Adding a test for when peers are late

* passes the test added in the previous commit

* passes the test added in the previous commit

* Fix iteration and typo

* Making the sleep dependendant on a smaller sleep we want to wait for
Copy link
Contributor

@otrack otrack left a comment

Choose a reason for hiding this comment

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

I believe that changing CheckTx is necessary. The current interface is not sound: it takes as input a callback cb which will be later called by another callback. This pattern is non-stanadrd and unecessarily complex. Moreover, cb necessarily lives outside of the mempool. This should be avoided because changes against the mempool must be thread safe.

The new interface @hvanz is proposing returns a promise. The promise captures the fact that the side effects of CheckTx are applied asynchronously. This change to the interface is not breaking because mempool#CheckTx is only used internally.

On the other hand, I am not in favor of the introduction of the CListIterator, modifying the way the reactor accesses the mempool. As indicated in my review, this change is not trivial because the underlying list is a non-standard concurrent list. I recommend to add these changes in a different commit with proper testing on them. Even better, before doing that, I recommend to actually model and verify the clist abstraction.

@@ -130,6 +152,18 @@ func (mem *CListMempool) EnableTxsAvailable() {
mem.txsAvailable = make(chan struct{}, 1)
}

func (mem *CListMempool) SetTxRemovedCallback(cb func(txKey types.TxKey)) {
mem.removeTxOnReactorCb = cb
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a very restrictive interface. Add some defensive programming here, by checking it was not set already. Document what is expected. Visibility would be package level (but this does not exist in golang.)

// Safe for concurrent use by multiple goroutines.
func (mem *CListMempool) TxsWaitChan() <-chan struct{} {
return mem.txs.WaitChan()
func (mem *CListMempool) NewIterator() Iterator {
Copy link
Contributor

Choose a reason for hiding this comment

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

Document this. As above, explain that it is a restricted interface.

mem.txsMap.Store(memTx.tx.Key(), e)
atomic.AddInt64(&mem.txsBytes, int64(len(memTx.tx)))
mem.metrics.TxSizeBytes.Observe(float64(len(memTx.tx)))
func (mem *CListMempool) addTx(entry *Entry) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment this method.

I suggest to pack methods according to their visibility levels, e.g., first public ones then private ones. Mixing things makes understanding the code difficult.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree with sorting the methods by visibility, but this will require to change most of the file, and I don't want to do it in this PR.

lastElement *clist.CElement // last accessed element in the list
nextEntryAvailable chan struct{} // channel to communicate that there is at least one entry available
mtx sync.RWMutex
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I would move this code to CList.

There is no need to for the iterator to be thread safe. Each peer has its own iterator. Hence, the mtx field can be dropped.

Besides that, I do not understand the logic of the nextEntryAvailable field.

}

return iter.lastElement.Value.(*Entry)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I am concernend about this set of changes, regarding how the reactor iterates over the mempool. They should be part of a different commit.

Overall, this is non-trivial code. The underlying list is a non-standard concurrent list (not à la M. Scott). As a consequence, we should be very cautious when using it. At the very least, this new way to iterate should be tested in unit tests. I would even recommend to actually model the clist with Quint, before adding an iterator atop it.

@lasarojc
Copy link
Contributor

Depends on #1169
This PR is intermittently failing some new tests. We moved the tests to a different branch to merge them first into main and will continue work here after that or later.
No other work is blocked by this PR, which is a nice to have.

@thanethomson thanethomson added the wip Work in progress label Jul 31, 2023
hvanz added a commit that referenced this pull request Aug 3, 2023
@hvanz
Copy link
Member Author

hvanz commented Dec 14, 2023

Closing this PR as it is not clear that the proposed solution is correct.

The main change introduced by this PR is an iterator for CListMempool. This is the main modification needed in the Mempool interface to clearly separate the reactor, which should only deal with the gossip protocol, from CListMempool, the actual pool of txs. We should revisit this issue in the context of modularising the Comet codebase (#42).

In the proposed solution, there is an iterator for each peer that reads from CListMempool. This adds to the complexity of the concurrent accesses to CListMempool and its underlying concurrent list clist. Although the intention was not to change the code logic, just to do a refactoring, it is possible that the new iterator may change the way the reactor access transactions. In a future attempt, it is advisable to clearly specify all concurrent accesses to CListMempool. As it was suggested above, a formal model of the clist implementation would also help.

@hvanz hvanz closed this Dec 14, 2023
@hvanz hvanz deleted the hvanz/mempool-interface branch July 11, 2024 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mempool wip Work in progress
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

mempool: Separate reactor from implementation
7 participants