mempool: move interface into mempool package#3524
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #3524 +/- ##
===========================================
- Coverage 64.25% 62.96% -1.29%
===========================================
Files 213 217 +4
Lines 17463 18135 +672
===========================================
+ Hits 11221 11419 +198
- Misses 5308 5754 +446
- Partials 934 962 +28
|
liamsi
left a comment
There was a problem hiding this comment.
Left some comments about the interfaces (and some nits about aliases).
I might lack some context. So please bare with me 🙈 I'll continue reading through the code and the changes.
|
I think I went into the rabbit hole 🐇 |
| // Updates to the mempool need to be synchronized with committing a block so | ||
| // apps can reset their transient state on Commit. | ||
| type Mempool interface { | ||
| Lock() |
There was a problem hiding this comment.
++ glad to see this is still here - we need to be able to claim this lock to avoid issues around recheck/commit.
See further: https://github.com/hyperledger/burrow/blob/develop/consensus/tendermint/abci/app.go#L321-L344
Refs #2659 Breaking changes in the mempool package: - Mempool now an interface - old Mempool renamed to CListMempool Breaking changes to state package: - MockMempool moved to mempool/mock package and renamed to Mempool - Mempool interface moved to mempool package
- combine everything into one interface - rename TxInfo.PeerID to TxInfo.SenderID - unexpose MempoolReactor.Mempool
TxsFront should not be a part of the Mempool interface because it leaks implementation details. Instead, we need to come up with general interface for querying the mempool so the MempoolReactor can fetch and broadcast txs to peers.
mempool/mempool.go
Outdated
| // TxsFront returns the first transaction in the ordered list for peer | ||
| // goroutines to call .NextWait() on. | ||
| // FIXME: leaking implementation details! | ||
| TxsFront() *clist.CElement |
There was a problem hiding this comment.
This needs to be fixed
There was a problem hiding this comment.
can't it just return *mempoolTx?
There was a problem hiding this comment.
or is that the same problem?
There was a problem hiding this comment.
No, because later in the broadcastTxRoutine loop we're calling next.WaitNextChan followed by next.Next(). I don't think we want either of these methods in the MempoolTx interface.
What we want is
a simple interface for Reactor to subscribe/get txs from the mempool, so it can broadcast them to peers (order of txs for a single peer must be preserved).
Current design 👍 👍
A bunch of goroutines (broadcastTxRoutine) are blocked on a single channel. Once the channel is closed, they all access concurrent list (clist) and send txs to peers (preserving order). Later, at some point, the channel is recreated.
I like the current implementation, but struggling to find a good abstraction for it (to separate mempool and mempool reactor).
Iterator interface (plus a channel to get notified about txs) 👎
type Iterator interface {
Next() bool
Tx() MempoolTx
}
type Mempool interface {
# creates an iterator starting from Nth item in the list/tree/any ordered structure
Iterator(offset int) Iterator
# Closed once there're txs in the mempool. Reopened after.
TxsWaitChan() <-chan struct{}
}Txs method (plus a channel to get notified about txs) 👎
type Mempool interface {
# returns an array of txs in the mempool
Txs(n, offset int) []MempoolTx
# Closed once there're txs in the mempool. Reopened after.
TxsWaitChan() <-chan struct{}
}A single channel exposed by mempool 👍
type Mempool interface {
TxsChan() <-chan MempoolTx
}exposing a single channel should allow us to remove TxsWaitChan() <-chan struct{} method. But it's gets messy when it comes down to impl details - unbuffered vs buffered channel + we'll need an additional channel for each peer.
There was a problem hiding this comment.
On the second thought, maybe it's okay for MempoolReactor to require the CList implementation for now. It can be a follow-up PR.
mempool/reactor.go
Outdated
| p2p.BaseReactor | ||
| config *cfg.MempoolConfig | ||
| Mempool *Mempool | ||
| mempool Mempool |
There was a problem hiding this comment.
don't understand why it was exposed in the first place
There was a problem hiding this comment.
Not sure the reasoning, but as mentioned above we need the Mempool locker and until you added node.Mempool() (in this PR) node.MempoolReactor().Mempool was the only way to get it...
Come to think of it I think it was the only way to get CheckTx too, which I've always found handy :)
| } | ||
|
|
||
| // txID is the hex encoded hash of the bytes as a types.Tx. | ||
| func txID(tx []byte) string { |
There was a problem hiding this comment.
same here. seems like an implementation detail
|
Tests failed with: seems not related. |
|
This failure was seen before in: #3310 (comment) |
| // cb: A callback from the CheckTx command. | ||
| // It gets called from another goroutine. | ||
| // CONTRACT: Either cb will get called, or err returned. | ||
| func (mem *CListMempool) CheckTx(tx types.Tx, cb func(*abci.Response)) (err error) { |
There was a problem hiding this comment.
remove and force people to always use CheckTxWithInfo?
There was a problem hiding this comment.
Probably a good idea to discuss this in a separate issue.
| Size() int | ||
|
|
||
| // TxsBytes returns the total size of all txs in the mempool. | ||
| TxsBytes() int64 |
There was a problem hiding this comment.
better abstraction for stats?
node/node.go
Outdated
| blockStore *bc.BlockStore // store the blockchain to disk | ||
| bcReactor *bc.BlockchainReactor // for fast-syncing | ||
| mempoolReactor *mempl.Reactor // for gossipping transactions | ||
| mempool *mempl.CListMempool |
There was a problem hiding this comment.
Why is this a pointer while in rpc/core/pipe.go it was changed to not be a pointer?
There was a problem hiding this comment.
Because node's mempool calls InitWAL/CloseWAL, but I don't want to add these methods to Mempool interface
There was a problem hiding this comment.
I created mempoolWithWAL interface
There was a problem hiding this comment.
Made them a part of Mempool interface for now.
- WAL is an implementation details and shouldn't really be a part of the interface.
- But we need a way to init/close associated resources
- And we need a way to configure them (wal path, etc.)
so we should either make node.Mempool a concrete type OR make InitWAL/CloseWAL/ConfigureWAL a part of any mempool interface (or make them more abstract like Start/Stop/Config)
| // the DetachPrev() call, which makes old elements not reachable by | ||
| // peer broadcastTxRoutine() automatically garbage collected. | ||
|
|
||
| // TODO: Better handle abci client errors. (make it automatically handle connection errors) |
There was a problem hiding this comment.
Same: is there an issue tracking this?
There was a problem hiding this comment.
I don't think so. There's #1993, which is one of the bugs
| blockStore: blockStore, | ||
| bcReactor: bcReactor, | ||
| mempoolReactor: mempoolReactor, | ||
| mempool: mempool, |
There was a problem hiding this comment.
cannot use mempool (variable of type *mempool.Mempool) as mempool.Mempool value in struct literal: missing method CheckTx (from typecheck)
consensus/mempool_test.go
Outdated
|
|
||
| "github.com/tendermint/tendermint/abci/example/code" | ||
| abci "github.com/tendermint/tendermint/abci/types" | ||
| mempl "github.com/tendermint/tendermint/mempool" |
There was a problem hiding this comment.
File is not gofmt-ed with -s (from gofmt)
ebuchman
left a comment
There was a problem hiding this comment.
Very nice start. This doesn't change any functionality right, just renames and file re-org?
Would be nice if we could preserve file names if files are changing, and then change the file names in a separate PR. Otherwise it's very difficult to review.
renames and re-org |
## Description Refs tendermint#2659 Breaking changes in the mempool package: [mempool] tendermint#2659 Mempool now an interface old Mempool renamed to CListMempool NewMempool renamed to NewCListMempool Option renamed to CListOption MempoolReactor renamed to Reactor NewMempoolReactor renamed to NewReactor unexpose TxID method TxInfo.PeerID renamed to SenderID unexpose MempoolReactor.Mempool Breaking changes in the state package: [state] tendermint#2659 Mempool interface moved to mempool package MockMempool moved to top-level mock package and renamed to Mempool Non Breaking changes in the node package: [node] tendermint#2659 Add Mempool method, which allows you to access mempool ## Commits * move Mempool interface into mempool package Refs tendermint#2659 Breaking changes in the mempool package: - Mempool now an interface - old Mempool renamed to CListMempool Breaking changes to state package: - MockMempool moved to mempool/mock package and renamed to Mempool - Mempool interface moved to mempool package * assert CListMempool impl Mempool * gofmt code * rename MempoolReactor to Reactor - combine everything into one interface - rename TxInfo.PeerID to TxInfo.SenderID - unexpose MempoolReactor.Mempool * move mempool mock into top-level mock package * add a fixme TxsFront should not be a part of the Mempool interface because it leaks implementation details. Instead, we need to come up with general interface for querying the mempool so the MempoolReactor can fetch and broadcast txs to peers. * change node#Mempool to return interface * save commit = new reactor arch * Revert "save commit = new reactor arch" This reverts commit 1bfceac. * require CListMempool in mempool.Reactor * add two changelog entries * fixes after my own review * quote interfaces, structs and functions * fixes after Ismail's review * make node's mempool an interface * make InitWAL/CloseWAL methods a part of Mempool interface * fix merge conflicts * make node's mempool an interface
Refs #2659
Breaking changes in the mempool package:
Breaking changes in the state package:
Non Breaking changes in the node package:
Wrote tests====
Nighthawks by Edward Hopper