Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
3b3071d
removed unused function
pompon0 Apr 8, 2026
3c866a6
snapshot
pompon0 Apr 8, 2026
4764164
updated test
pompon0 Apr 8, 2026
3b992a1
more cleanup
pompon0 Apr 8, 2026
9fd05fc
snapshot
pompon0 Apr 8, 2026
1fd3453
wip
pompon0 Apr 8, 2026
a0ef9c7
WIP
pompon0 Apr 8, 2026
63e6bd3
wip
pompon0 Apr 8, 2026
254426b
wip
pompon0 Apr 8, 2026
44b9288
wip
pompon0 Apr 8, 2026
3061e49
wip
pompon0 Apr 8, 2026
47aa688
wip
pompon0 Apr 8, 2026
aaf3ee9
wip
pompon0 Apr 8, 2026
4e0faa9
addressed a flake
pompon0 Apr 8, 2026
bd8db80
Merge branch 'gprusak-mempool2' into gprusak-mempool3
pompon0 Apr 8, 2026
d2b6a21
wip
pompon0 Apr 8, 2026
4a3a579
snapshot
pompon0 Apr 9, 2026
59b9f59
removed notion of precheck
pompon0 Apr 9, 2026
28a2ff1
simplified errors
pompon0 Apr 9, 2026
fab6e8c
Merge remote-tracking branch 'origin/main' into gprusak-mempool2
pompon0 Apr 9, 2026
ea8519e
Merge branch 'gprusak-mempool2' into gprusak-mempool3
pompon0 Apr 9, 2026
15ed859
compilation fix
pompon0 Apr 9, 2026
ba81b8b
separated reactor
pompon0 Apr 9, 2026
4601391
wip
pompon0 Apr 9, 2026
b30fc91
concurrency fix
pompon0 Apr 9, 2026
05e69c6
non-nil args to buildGigaConfig
pompon0 Apr 9, 2026
0d3b1d0
mempool in GigaRouter
pompon0 Apr 9, 2026
f13a871
-1 in Reap
pompon0 Apr 9, 2026
cdc7047
disabled some components for autobahn mode
pompon0 Apr 10, 2026
a21d315
disabled mempool notifications when WaitForTxs is disabled
pompon0 Apr 10, 2026
0b1ed51
Merge branch 'main' into gprusak-mempool4
pompon0 Apr 10, 2026
b84cfda
Merge remote-tracking branch 'origin/main' into gprusak-mempool3
pompon0 Apr 10, 2026
a86ce40
Merge branch 'gprusak-mempool3' into gprusak-mempool4
pompon0 Apr 10, 2026
062f712
reverted err visibility
pompon0 Apr 10, 2026
9b5b8e6
restored comments
pompon0 Apr 10, 2026
c8e6d17
more comments
pompon0 Apr 10, 2026
708a690
broadcast fix
pompon0 Apr 10, 2026
b94c719
SpawnCritical
pompon0 Apr 10, 2026
029113b
moved ownership of mempool
pompon0 Apr 10, 2026
67ea52a
lint
pompon0 Apr 10, 2026
1e74249
Merge remote-tracking branch 'origin/main' into gprusak-mempool3
pompon0 Apr 10, 2026
f6be363
wip
pompon0 Apr 10, 2026
de584fa
mempool fix
pompon0 Apr 10, 2026
70c75a1
Merge remote-tracking branch 'origin/main' into gprusak-mempool3
pompon0 Apr 10, 2026
f5a18e0
Merge branch 'gprusak-mempool3' into gprusak-mempool4
pompon0 Apr 10, 2026
26e74ea
applied comments
pompon0 Apr 13, 2026
be79fac
keeping a tx mempool lock for Finalize + Commit + Update
pompon0 Apr 13, 2026
baac6b0
applied comments
pompon0 Apr 14, 2026
121b2e4
applied comments
pompon0 Apr 14, 2026
4dbc0d7
Merge remote-tracking branch 'origin/main' into gprusak-mempool4
pompon0 Apr 14, 2026
d217ee0
moved config
pompon0 Apr 14, 2026
5ed9b06
extracted config
pompon0 Apr 14, 2026
6a2cd95
deflake
pompon0 Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 43 additions & 20 deletions sei-tendermint/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strings"
"time"

mempoolcfg "github.com/sei-protocol/sei-chain/sei-tendermint/internal/mempool"
tmos "github.com/sei-protocol/sei-chain/sei-tendermint/libs/os"
"github.com/sei-protocol/sei-chain/sei-tendermint/types"
)
Expand Down Expand Up @@ -857,38 +858,60 @@ type MempoolConfig struct {
DropPriorityReservoirSize int `mapstructure:"drop-priority-reservoir-size"`
}

func (cfg *MempoolConfig) ToMempoolConfig() *mempoolcfg.Config {
return &mempoolcfg.Config{
Size: cfg.Size,
MaxTxsBytes: cfg.MaxTxsBytes,
CacheSize: cfg.CacheSize,
DuplicateTxsCacheSize: cfg.DuplicateTxsCacheSize,
KeepInvalidTxsInCache: cfg.KeepInvalidTxsInCache,
MaxTxBytes: cfg.MaxTxBytes,
TTLDuration: cfg.TTLDuration,
TTLNumBlocks: cfg.TTLNumBlocks,
TxNotifyThreshold: cfg.TxNotifyThreshold,
PendingSize: cfg.PendingSize,
MaxPendingTxsBytes: cfg.MaxPendingTxsBytes,
RemoveExpiredTxsFromQueue: cfg.RemoveExpiredTxsFromQueue,
DropPriorityThreshold: cfg.DropPriorityThreshold,
DropUtilisationThreshold: cfg.DropUtilisationThreshold,
DropPriorityReservoirSize: cfg.DropPriorityReservoirSize,
}
}

// DefaultMempoolConfig returns a default configuration for the Tendermint mempool.
func DefaultMempoolConfig() *MempoolConfig {
cfg := mempoolcfg.DefaultConfig()
return &MempoolConfig{
Broadcast: true,
// Each signature verification takes .5ms, Size reduced until we implement
// ABCI Recheck
Size: 5000,
MaxTxsBytes: 1024 * 1024 * 1024, // 1GB
CacheSize: 10000,
DuplicateTxsCacheSize: 100000,
MaxTxBytes: 1024 * 1024, // 1MB
TTLDuration: 5 * time.Second, // prevent stale txs from filling mempool
TTLNumBlocks: 10, // remove txs after 10 blocks
TxNotifyThreshold: 0,
Broadcast: true,
Size: cfg.Size,
MaxTxsBytes: cfg.MaxTxsBytes,
CacheSize: cfg.CacheSize,
DuplicateTxsCacheSize: cfg.DuplicateTxsCacheSize,
KeepInvalidTxsInCache: cfg.KeepInvalidTxsInCache,
MaxTxBytes: cfg.MaxTxBytes,
MaxBatchBytes: 0,
TTLDuration: cfg.TTLDuration,
TTLNumBlocks: cfg.TTLNumBlocks,
TxNotifyThreshold: cfg.TxNotifyThreshold,
CheckTxErrorBlacklistEnabled: true,
CheckTxErrorThreshold: 50,
PendingSize: 5000,
MaxPendingTxsBytes: 1024 * 1024 * 1024, // 1GB
PendingTTLDuration: 0 * time.Second,
PendingSize: cfg.PendingSize,
MaxPendingTxsBytes: cfg.MaxPendingTxsBytes,
PendingTTLDuration: 0,
PendingTTLNumBlocks: 0,
RemoveExpiredTxsFromQueue: true,
DropPriorityThreshold: 0.1,
DropUtilisationThreshold: 1.0,
DropPriorityReservoirSize: 10_240,
RemoveExpiredTxsFromQueue: cfg.RemoveExpiredTxsFromQueue,
DropPriorityThreshold: cfg.DropPriorityThreshold,
DropUtilisationThreshold: cfg.DropUtilisationThreshold,
DropPriorityReservoirSize: cfg.DropPriorityReservoirSize,
}
}

// TestMempoolConfig returns a configuration for testing the Tendermint mempool
func TestMempoolConfig() *MempoolConfig {
cfg := DefaultMempoolConfig()
cfg.CacheSize = 1000
cfg.DropUtilisationThreshold = 0.0
testCfg := mempoolcfg.TestConfig()
cfg.CacheSize = testCfg.CacheSize
cfg.DropUtilisationThreshold = testCfg.DropUtilisationThreshold
return cfg
}

Expand Down
55 changes: 32 additions & 23 deletions sei-tendermint/internal/autobahn/producer/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"time"

"github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/consensus"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/pb"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/autobahn/types"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/mempool"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils/scope"
"golang.org/x/time/rate"
Expand All @@ -32,19 +32,18 @@ func (c *Config) maxTxsPerBlock() uint64 {

// State is the block producer state.
type State struct {
cfg *Config
// channel of transactions to build the next block from.
mempool chan *pb.Transaction
cfg *Config
txMempool *mempool.TxMempool
// consensus state to which published blocks will be reported.
consensus *consensus.State
}

// NewState constructs a new block producer state.
// Returns an error if the current node is NOT a producer.
func NewState(cfg *Config, consensus *consensus.State) *State {
func NewState(cfg *Config, txMempool *mempool.TxMempool, consensus *consensus.State) *State {
return &State{
cfg: cfg,
mempool: make(chan *pb.Transaction, cfg.MempoolSize),
txMempool: txMempool,
consensus: consensus,
}
}
Expand All @@ -54,22 +53,37 @@ func NewState(cfg *Config, consensus *consensus.State) *State {
func (s *State) makePayload(ctx context.Context) *types.Payload {
ctx, cancel := context.WithTimeout(ctx, s.cfg.BlockInterval)
defer cancel()
maxTxs := s.cfg.maxTxsPerBlock()
var totalGas uint64
var txs [][]byte
for totalGas < s.cfg.MaxGasPerBlock && uint64(len(txs)) < maxTxs {
tx, err := utils.Recv(ctx, s.mempool)
if err != nil {
break

if s.txMempool.NumTxsNotPending() == 0 {
select {
case <-ctx.Done():
case <-s.txMempool.TxsAvailable():
}
txs = append(txs, tx.Payload)
totalGas += tx.GasUsed
}
return types.PayloadBuilder{

txs, gasEstimated := s.txMempool.PopTxs(mempool.ReapLimits{
MaxTxs: utils.Some(min(types.MaxTxsPerBlock, s.cfg.maxTxsPerBlock())),
MaxBytes: utils.Some(utils.Clamp[int64](types.MaxTxsBytesPerBlock)),
MaxGasWanted: utils.Some(utils.Clamp[int64](s.cfg.MaxGasPerBlock)),
MaxGasEstimated: utils.Some(utils.Clamp[int64](s.cfg.MaxGasPerBlock)),
})
payloadTxs := make([][]byte, 0, len(txs))
Comment thread
wen-coding marked this conversation as resolved.
for _, tx := range txs {
payloadTxs = append(payloadTxs, tx)
}
payload, err := types.PayloadBuilder{
CreatedAt: time.Now(),
TotalGas: totalGas,
Txs: txs,
// TODO: ReapMaxTxsBytesMaxGas does not handle corner cases correctly rn, which actually
// can produce negative total gas. Fixing it right away might be backward incompatible afaict,
// so we leave it as is for now.
Comment thread
pompon0 marked this conversation as resolved.
TotalGas: uint64(gasEstimated), // nolint:gosec
Txs: payloadTxs,
}.Build()
// This should never happen: we construct the payload from correctly sized data.
if err != nil {
panic(fmt.Errorf("PayloadBuilder{}.Build(): %w", err))
}
return payload
}

// nextPayload constructs the payload for the next block.
Expand All @@ -86,11 +100,6 @@ func (s *State) nextPayload(ctx context.Context) (*types.Payload, error) {
}
}

// PushToMempool pushes the transaction to the mempool.
func (s *State) PushToMempool(ctx context.Context, tx *pb.Transaction) error {
return utils.Send(ctx, s.mempool, tx)
}

// Run runs the background tasks of the producer state.
func (s *State) Run(ctx context.Context) error {
return scope.Run(ctx, func(ctx context.Context, scope scope.Scope) error {
Expand Down
40 changes: 38 additions & 2 deletions sei-tendermint/internal/autobahn/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,30 @@ func (h *BlockHeader) Verify(c *Committee) error {
return nil
}

const standardTxBytes uint64 = 1024

// Maximum number of transactions in a block.
const MaxTxsPerBlock uint64 = 2000

// Maximum total size of all the transactions.
// It can be split arbitrarily across transactions (1 large, 2000 small ones, etc.)
// up to MaxTxsPerBlock limit.
const MaxTxsBytesPerBlock = MaxTxsPerBlock * standardTxBytes

// Upper bound on the block proto encoding.
var MaxBlockProtoSize = func() uint64 {
// Payload.Txs represents the variable part of the Block size.
// Proto size is maximized if we distribute data evenly across transactions.
tx := make([]byte, standardTxBytes)
txs := make([][]byte, MaxTxsPerBlock)
for i := range txs {
txs[i] = tx
}
// Crude estimate of all other fields.
const otherFields = 100 * 1024
return otherFields + uint64(protoutils.Size(&pb.Block{Payload: &pb.Payload{Txs: txs}}))
}()

// Block .
type Block struct {
utils.ReadOnly
Expand Down Expand Up @@ -149,7 +173,19 @@ type Payload struct {
}

// Build builds the Payload.
func (b PayloadBuilder) Build() *Payload { return &Payload{p: b} }
func (b PayloadBuilder) Build() (*Payload, error) {
if uint64(len(b.Txs)) > MaxTxsPerBlock {
return nil, fmt.Errorf("too many transactions")
}
total := uint64(0)
for _, tx := range b.Txs {
total += uint64(len(tx))
}
if total > MaxTxsBytesPerBlock {
return nil, fmt.Errorf("total txs bytes too large")
}
return &Payload{p: b}, nil
}

// ToBuilder converts the Payload to a PayloadBuilder.
func (p *Payload) ToBuilder() PayloadBuilder { return p.p }
Expand Down Expand Up @@ -245,7 +281,7 @@ var PayloadConv = protoutils.Conv[*Payload, *pb.Payload]{
Coinbase: p.Coinbase,
Basefee: *p.Basefee,
Txs: p.Txs,
}.Build(), nil
}.Build()
},
}

Expand Down
4 changes: 2 additions & 2 deletions sei-tendermint/internal/autobahn/types/testonly.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ func GenBlockHeader(rng utils.Rng) *BlockHeader {

// GenPayload generates a random Payload.
func GenPayload(rng utils.Rng) *Payload {
return PayloadBuilder{
return utils.OrPanic1(PayloadBuilder{
CreatedAt: utils.GenTimestamp(rng),
TotalGas: rng.Uint64(),
EdgeCount: rng.Int63(),
Coinbase: utils.GenBytes(rng, 10),
Basefee: rng.Int63(),
Txs: utils.GenSlice(rng, func(rng utils.Rng) []byte { return utils.GenBytes(rng, 10) }),
}.Build()
}.Build())
}

// GenBlock generates a random Block.
Expand Down
2 changes: 1 addition & 1 deletion sei-tendermint/internal/blocksync/reactor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func makeReactor(
state, err := sm.MakeGenesisState(genDoc)
require.NoError(t, err)
require.NoError(t, stateStore.Save(state))
mp := mempool.NewTxMempool(config.TestMempoolConfig(), app, mempool.NopMetrics(), mempool.NopTxConstraintsFetcher)
mp := mempool.NewTxMempool(mempool.TestConfig(), app, mempool.NopMetrics(), mempool.NopTxConstraintsFetcher)
eventbus := eventbus.NewDefault()
require.NoError(t, eventbus.Start(ctx))

Expand Down
2 changes: 1 addition & 1 deletion sei-tendermint/internal/consensus/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ func newStateWithConfigAndBlockStore(
// Make Mempool

mempool := mempool.NewTxMempool(
thisConfig.Mempool,
thisConfig.Mempool.ToMempoolConfig(),
proxyAppConnMem,
mempool.NopMetrics(),
mempool.NopTxConstraintsFetcher,
Expand Down
3 changes: 2 additions & 1 deletion sei-tendermint/internal/consensus/mempool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
sm "github.com/sei-protocol/sei-chain/sei-tendermint/internal/state"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/store"
"github.com/sei-protocol/sei-chain/sei-tendermint/internal/test/factory"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/utils"
"github.com/sei-protocol/sei-chain/sei-tendermint/types"
)

Expand Down Expand Up @@ -247,7 +248,7 @@ func TestMempoolRmBadTx(t *testing.T) {

// check for the tx
for {
txs := cs.txMempool.ReapMaxBytesMaxGas(int64(len(txBytes)), -1, -1)
txs := cs.txMempool.ReapMaxBytesMaxGas(int64(len(txBytes)), utils.Max[int64](), utils.Max[int64]())
if len(txs) == 0 {
emptyMempoolCh <- struct{}{}
return
Expand Down
2 changes: 1 addition & 1 deletion sei-tendermint/internal/consensus/reactor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ func TestReactorWithEvidence(t *testing.T) {
proxyAppConnCon := app

mempool := mempool.NewTxMempool(
thisConfig.Mempool,
thisConfig.Mempool.ToMempoolConfig(),
proxyAppConnMem,
mempool.NopMetrics(),
mempool.NopTxConstraintsFetcher,
Expand Down
2 changes: 1 addition & 1 deletion sei-tendermint/internal/consensus/replay.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func NewHandshaker(
}

func newReplayTxMempool(appClient abci.Application) *mempool.TxMempool {
return mempool.NewTxMempool(config.DefaultMempoolConfig(), appClient, mempool.NopMetrics(), mempool.NopTxConstraintsFetcher)
return mempool.NewTxMempool(config.DefaultMempoolConfig().ToMempoolConfig(), appClient, mempool.NopMetrics(), mempool.NopTxConstraintsFetcher)
}

// NBlocks returns the number of blocks applied to the state.
Expand Down
Loading
Loading