mempool: v1 implementation (#6466)

This commit is contained in:
Aleksandr Bezobchuk
2021-06-01 11:17:45 -04:00
committed by GitHub
parent 4e06dfef8c
commit 1e4bc04cd6
42 changed files with 3323 additions and 736 deletions

View File

@@ -28,7 +28,7 @@ import (
"github.com/tendermint/tendermint/libs/service"
"github.com/tendermint/tendermint/libs/strings"
"github.com/tendermint/tendermint/light"
mempl "github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/p2p/pex"
"github.com/tendermint/tendermint/privval"
@@ -70,8 +70,8 @@ type Node struct {
stateStore sm.Store
blockStore *store.BlockStore // store the blockchain to disk
bcReactor service.Service // for fast-syncing
mempoolReactor *mempl.Reactor // for gossipping transactions
mempool mempl.Mempool
mempoolReactor service.Service // for gossipping transactions
mempool mempool.Mempool
stateSync bool // whether the node should state sync on startup
stateSyncReactor *statesync.Reactor // for hosting and restoring state sync snapshots
stateSyncProvider statesync.StateProvider // provides state data for bootstrapping a node
@@ -253,9 +253,12 @@ func NewNode(config *cfg.Config,
return nil, fmt.Errorf("failed to create router: %w", err)
}
mpReactorShim, mpReactor, mempool := createMempoolReactor(
mpReactorShim, mpReactor, mp, err := createMempoolReactor(
config, proxyApp, state, memplMetrics, peerManager, router, logger,
)
if err != nil {
return nil, err
}
evReactorShim, evReactor, evPool, err := createEvidenceReactor(
config, dbProvider, stateDB, blockStore, peerManager, router, logger,
@@ -269,13 +272,13 @@ func NewNode(config *cfg.Config,
stateStore,
logger.With("module", "state"),
proxyApp.Consensus(),
mempool,
mp,
evPool,
sm.BlockExecutorWithMetrics(smMetrics),
)
csReactorShim, csReactor, csState := createConsensusReactor(
config, state, blockExec, blockStore, mempool, evPool,
config, state, blockExec, blockStore, mp, evPool,
privValidator, csMetrics, stateSync || fastSync, eventBus,
peerManager, router, consensusLogger,
)
@@ -426,7 +429,7 @@ func NewNode(config *cfg.Config,
blockStore: blockStore,
bcReactor: bcReactor,
mempoolReactor: mpReactor,
mempool: mempool,
mempool: mp,
consensusState: csState,
consensusReactor: csReactor,
stateSyncReactor: stateSyncReactor,
@@ -993,12 +996,12 @@ func (n *Node) ConsensusReactor() *cs.Reactor {
}
// MempoolReactor returns the Node's mempool reactor.
func (n *Node) MempoolReactor() *mempl.Reactor {
func (n *Node) MempoolReactor() service.Service {
return n.mempoolReactor
}
// Mempool returns the Node's mempool.
func (n *Node) Mempool() mempl.Mempool {
func (n *Node) Mempool() mempool.Mempool {
return n.mempool
}
@@ -1149,19 +1152,19 @@ func DefaultGenesisDocProviderFunc(config *cfg.Config) GenesisDocProvider {
type Provider func(*cfg.Config, log.Logger) (*Node, error)
// MetricsProvider returns a consensus, p2p and mempool Metrics.
type MetricsProvider func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempl.Metrics, *sm.Metrics)
type MetricsProvider func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempool.Metrics, *sm.Metrics)
// DefaultMetricsProvider returns Metrics build using Prometheus client library
// if Prometheus is enabled. Otherwise, it returns no-op Metrics.
func DefaultMetricsProvider(config *cfg.InstrumentationConfig) MetricsProvider {
return func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempl.Metrics, *sm.Metrics) {
return func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempool.Metrics, *sm.Metrics) {
if config.Prometheus {
return cs.PrometheusMetrics(config.Namespace, "chain_id", chainID),
p2p.PrometheusMetrics(config.Namespace, "chain_id", chainID),
mempl.PrometheusMetrics(config.Namespace, "chain_id", chainID),
mempool.PrometheusMetrics(config.Namespace, "chain_id", chainID),
sm.PrometheusMetrics(config.Namespace, "chain_id", chainID)
}
return cs.NopMetrics(), p2p.NopMetrics(), mempl.NopMetrics(), sm.NopMetrics()
return cs.NopMetrics(), p2p.NopMetrics(), mempool.NopMetrics(), sm.NopMetrics()
}
}

View File

@@ -24,7 +24,8 @@ import (
"github.com/tendermint/tendermint/evidence"
"github.com/tendermint/tendermint/libs/log"
tmrand "github.com/tendermint/tendermint/libs/rand"
mempl "github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/mempool"
mempoolv0 "github.com/tendermint/tendermint/mempool/v0"
"github.com/tendermint/tendermint/p2p"
p2pmock "github.com/tendermint/tendermint/p2p/mock"
"github.com/tendermint/tendermint/privval"
@@ -226,16 +227,15 @@ func TestCreateProposalBlock(t *testing.T) {
state.ConsensusParams.Evidence.MaxBytes = maxEvidenceBytes
proposerAddr, _ := state.Validators.GetByIndex(0)
// Make Mempool
mempool := mempl.NewCListMempool(
mp := mempoolv0.NewCListMempool(
config.Mempool,
proxyApp.Mempool(),
state.LastBlockHeight,
mempl.WithMetrics(mempl.NopMetrics()),
mempl.WithPreCheck(sm.TxPreCheck(state)),
mempl.WithPostCheck(sm.TxPostCheck(state)),
mempoolv0.WithMetrics(mempool.NopMetrics()),
mempoolv0.WithPreCheck(sm.TxPreCheck(state)),
mempoolv0.WithPostCheck(sm.TxPostCheck(state)),
)
mempool.SetLogger(logger)
mp.SetLogger(logger)
// Make EvidencePool
evidenceDB := dbm.NewMemDB()
@@ -262,7 +262,7 @@ func TestCreateProposalBlock(t *testing.T) {
txLength := 100
for i := 0; i <= maxBytes/txLength; i++ {
tx := tmrand.Bytes(txLength)
err := mempool.CheckTx(tx, nil, mempl.TxInfo{})
err := mp.CheckTx(tx, nil, mempool.TxInfo{})
assert.NoError(t, err)
}
@@ -270,7 +270,7 @@ func TestCreateProposalBlock(t *testing.T) {
stateStore,
logger,
proxyApp.Consensus(),
mempool,
mp,
evidencePool,
)
@@ -317,27 +317,27 @@ func TestMaxTxsProposalBlockSize(t *testing.T) {
proposerAddr, _ := state.Validators.GetByIndex(0)
// Make Mempool
mempool := mempl.NewCListMempool(
mp := mempoolv0.NewCListMempool(
config.Mempool,
proxyApp.Mempool(),
state.LastBlockHeight,
mempl.WithMetrics(mempl.NopMetrics()),
mempl.WithPreCheck(sm.TxPreCheck(state)),
mempl.WithPostCheck(sm.TxPostCheck(state)),
mempoolv0.WithMetrics(mempool.NopMetrics()),
mempoolv0.WithPreCheck(sm.TxPreCheck(state)),
mempoolv0.WithPostCheck(sm.TxPostCheck(state)),
)
mempool.SetLogger(logger)
mp.SetLogger(logger)
// fill the mempool with one txs just below the maximum size
txLength := int(types.MaxDataBytesNoEvidence(maxBytes, 1))
tx := tmrand.Bytes(txLength - 4) // to account for the varint
err = mempool.CheckTx(tx, nil, mempl.TxInfo{})
err = mp.CheckTx(tx, nil, mempool.TxInfo{})
assert.NoError(t, err)
blockExec := sm.NewBlockExecutor(
stateStore,
logger,
proxyApp.Consensus(),
mempool,
mp,
sm.EmptyEvidencePool{},
)
@@ -375,26 +375,26 @@ func TestMaxProposalBlockSize(t *testing.T) {
proposerAddr, _ := state.Validators.GetByIndex(0)
// Make Mempool
mempool := mempl.NewCListMempool(
mp := mempoolv0.NewCListMempool(
config.Mempool,
proxyApp.Mempool(),
state.LastBlockHeight,
mempl.WithMetrics(mempl.NopMetrics()),
mempl.WithPreCheck(sm.TxPreCheck(state)),
mempl.WithPostCheck(sm.TxPostCheck(state)),
mempoolv0.WithMetrics(mempool.NopMetrics()),
mempoolv0.WithPreCheck(sm.TxPreCheck(state)),
mempoolv0.WithPostCheck(sm.TxPostCheck(state)),
)
mempool.SetLogger(logger)
mp.SetLogger(logger)
// fill the mempool with one txs just below the maximum size
txLength := int(types.MaxDataBytesNoEvidence(maxBytes, types.MaxVotesCount))
tx := tmrand.Bytes(txLength - 6) // to account for the varint
err = mempool.CheckTx(tx, nil, mempl.TxInfo{})
err = mp.CheckTx(tx, nil, mempool.TxInfo{})
assert.NoError(t, err)
// now produce more txs than what a normal block can hold with 10 smaller txs
// At the end of the test, only the single big tx should be added
for i := 0; i < 10; i++ {
tx := tmrand.Bytes(10)
err = mempool.CheckTx(tx, nil, mempl.TxInfo{})
err = mp.CheckTx(tx, nil, mempool.TxInfo{})
assert.NoError(t, err)
}
@@ -402,7 +402,7 @@ func TestMaxProposalBlockSize(t *testing.T) {
stateStore,
logger,
proxyApp.Consensus(),
mempool,
mp,
sm.EmptyEvidencePool{},
)

View File

@@ -22,8 +22,10 @@ import (
"github.com/tendermint/tendermint/evidence"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/libs/service"
tmStrings "github.com/tendermint/tendermint/libs/strings"
mempl "github.com/tendermint/tendermint/mempool"
tmstrings "github.com/tendermint/tendermint/libs/strings"
"github.com/tendermint/tendermint/mempool"
mempoolv0 "github.com/tendermint/tendermint/mempool/v0"
mempoolv1 "github.com/tendermint/tendermint/mempool/v1"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/p2p/pex"
protop2p "github.com/tendermint/tendermint/proto/tendermint/p2p"
@@ -192,25 +194,14 @@ func createMempoolReactor(
config *cfg.Config,
proxyApp proxy.AppConns,
state sm.State,
memplMetrics *mempl.Metrics,
memplMetrics *mempool.Metrics,
peerManager *p2p.PeerManager,
router *p2p.Router,
logger log.Logger,
) (*p2p.ReactorShim, *mempl.Reactor, *mempl.CListMempool) {
) (*p2p.ReactorShim, service.Service, mempool.Mempool, error) {
logger = logger.With("module", "mempool")
mempool := mempl.NewCListMempool(
config.Mempool,
proxyApp.Mempool(),
state.LastBlockHeight,
mempl.WithMetrics(memplMetrics),
mempl.WithPreCheck(sm.TxPreCheck(state)),
mempl.WithPostCheck(sm.TxPostCheck(state)),
)
mempool.SetLogger(logger)
channelShims := mempl.GetChannelShims(config.Mempool)
logger = logger.With("module", "mempool", "version", config.Mempool.Version)
channelShims := mempoolv0.GetChannelShims(config.Mempool)
reactorShim := p2p.NewReactorShim(logger, "MempoolShim", channelShims)
var (
@@ -226,20 +217,63 @@ func createMempoolReactor(
peerUpdates = reactorShim.PeerUpdates
}
reactor := mempl.NewReactor(
logger,
config.Mempool,
peerManager,
mempool,
channels[mempl.MempoolChannel],
peerUpdates,
)
switch config.Mempool.Version {
case cfg.MempoolV0:
mp := mempoolv0.NewCListMempool(
config.Mempool,
proxyApp.Mempool(),
state.LastBlockHeight,
mempoolv0.WithMetrics(memplMetrics),
mempoolv0.WithPreCheck(sm.TxPreCheck(state)),
mempoolv0.WithPostCheck(sm.TxPostCheck(state)),
)
if config.Consensus.WaitForTxs() {
mempool.EnableTxsAvailable()
mp.SetLogger(logger)
reactor := mempoolv0.NewReactor(
logger,
config.Mempool,
peerManager,
mp,
channels[mempool.MempoolChannel],
peerUpdates,
)
if config.Consensus.WaitForTxs() {
mp.EnableTxsAvailable()
}
return reactorShim, reactor, mp, nil
case cfg.MempoolV1:
mp := mempoolv1.NewTxMempool(
logger,
config.Mempool,
proxyApp.Mempool(),
state.LastBlockHeight,
mempoolv1.WithMetrics(memplMetrics),
mempoolv1.WithPreCheck(sm.TxPreCheck(state)),
mempoolv1.WithPostCheck(sm.TxPostCheck(state)),
)
reactor := mempoolv1.NewReactor(
logger,
config.Mempool,
peerManager,
mp,
channels[mempool.MempoolChannel],
peerUpdates,
)
if config.Consensus.WaitForTxs() {
mp.EnableTxsAvailable()
}
return reactorShim, reactor, mp, nil
default:
return nil, nil, nil, fmt.Errorf("unknown mempool version: %s", config.Mempool.Version)
}
return reactorShim, reactor, mempool
}
func createEvidenceReactor(
@@ -344,7 +378,7 @@ func createConsensusReactor(
state sm.State,
blockExec *sm.BlockExecutor,
blockStore sm.BlockStore,
mempool *mempl.CListMempool,
mp mempool.Mempool,
evidencePool *evidence.Pool,
privValidator types.PrivValidator,
csMetrics *cs.Metrics,
@@ -360,7 +394,7 @@ func createConsensusReactor(
state.Copy(),
blockExec,
blockStore,
mempool,
mp,
evidencePool,
cs.StateMetrics(csMetrics),
)
@@ -408,7 +442,7 @@ func createTransport(logger log.Logger, config *cfg.Config) *p2p.MConnTransport
logger, p2p.MConnConfig(config.P2P), []*p2p.ChannelDescriptor{},
p2p.MConnTransportOptions{
MaxAcceptedConnections: uint32(config.P2P.MaxNumInboundPeers +
len(tmStrings.SplitAndTrimEmpty(config.P2P.UnconditionalPeerIDs, ",", " ")),
len(tmstrings.SplitAndTrimEmpty(config.P2P.UnconditionalPeerIDs, ",", " ")),
),
},
)
@@ -445,7 +479,7 @@ func createPeerManager(
}
privatePeerIDs := make(map[p2p.NodeID]struct{})
for _, id := range tmStrings.SplitAndTrimEmpty(config.P2P.PrivatePeerIDs, ",", " ") {
for _, id := range tmstrings.SplitAndTrimEmpty(config.P2P.PrivatePeerIDs, ",", " ") {
privatePeerIDs[p2p.NodeID(id)] = struct{}{}
}
@@ -461,7 +495,7 @@ func createPeerManager(
}
peers := []p2p.NodeAddress{}
for _, p := range tmStrings.SplitAndTrimEmpty(config.P2P.PersistentPeers, ",", " ") {
for _, p := range tmstrings.SplitAndTrimEmpty(config.P2P.PersistentPeers, ",", " ") {
address, err := p2p.ParseNodeAddress(p)
if err != nil {
return nil, fmt.Errorf("invalid peer address %q: %w", p, err)
@@ -471,7 +505,7 @@ func createPeerManager(
options.PersistentPeers = append(options.PersistentPeers, address.NodeID)
}
for _, p := range tmStrings.SplitAndTrimEmpty(config.P2P.BootstrapPeers, ",", " ") {
for _, p := range tmstrings.SplitAndTrimEmpty(config.P2P.BootstrapPeers, ",", " ") {
address, err := p2p.ParseNodeAddress(p)
if err != nil {
return nil, fmt.Errorf("invalid peer address %q: %w", p, err)
@@ -638,7 +672,7 @@ func createPEXReactorAndAddToSwitch(addrBook pex.AddrBook, config *cfg.Config,
sw *p2p.Switch, logger log.Logger) *pex.Reactor {
reactorConfig := &pex.ReactorConfig{
Seeds: tmStrings.SplitAndTrimEmpty(config.P2P.Seeds, ",", " "),
Seeds: tmstrings.SplitAndTrimEmpty(config.P2P.Seeds, ",", " "),
SeedMode: config.Mode == cfg.ModeSeed,
// See consensus/reactor.go: blocksToContributeToBecomeGoodPeer 10000
// blocks assuming 10s blocks ~ 28 hours.
@@ -711,7 +745,7 @@ func makeNodeInfo(
byte(cs.DataChannel),
byte(cs.VoteChannel),
byte(cs.VoteSetBitsChannel),
byte(mempl.MempoolChannel),
byte(mempool.MempoolChannel),
byte(evidence.EvidenceChannel),
byte(statesync.SnapshotChannel),
byte(statesync.ChunkChannel),