Skip to content

Commit d2b00a6

Browse files
committed
updates
1 parent 010626b commit d2b00a6

File tree

16 files changed

+210
-227
lines changed

16 files changed

+210
-227
lines changed

apps/testapp/kv/kvexecutor.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,11 @@ func (k *KVExecutor) GetExecutionInfo(ctx context.Context, height uint64) (execu
430430
return execution.ExecutionInfo{MaxGas: 0}, nil
431431
}
432432

433-
// FilterTxs validates force-included transactions and calculates gas for all transactions.
433+
// FilterTxs validates force-included transactions and applies gas filtering.
434434
// For KVExecutor, only force-included transactions are validated (key=value format).
435435
// Mempool transactions are passed through unchanged.
436-
// KVExecutor doesn't track gas, so GasPerTx is nil.
437-
func (k *KVExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*execution.FilterTxsResult, error) {
436+
// KVExecutor doesn't track gas, so maxGas is ignored.
437+
func (k *KVExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*execution.FilterTxsResult, error) {
438438
validTxs := make([][]byte, 0, len(txs))
439439
validMask := make([]bool, 0, len(txs))
440440

@@ -460,6 +460,6 @@ func (k *KVExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedM
460460
return &execution.FilterTxsResult{
461461
ValidTxs: validTxs,
462462
ForceIncludedMask: validMask,
463-
GasPerTx: nil, // KVExecutor doesn't track gas
463+
RemainingTxs: nil, // KVExecutor doesn't track gas, so no gas-based filtering
464464
}, nil
465465
}

core/execution/dummy.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,13 @@ func (e *DummyExecutor) GetExecutionInfo(ctx context.Context, height uint64) (Ex
109109
return ExecutionInfo{MaxGas: 0}, nil
110110
}
111111

112-
// FilterTxs validates force-included transactions and calculates gas for all transactions.
112+
// FilterTxs validates force-included transactions and applies gas filtering.
113113
// For DummyExecutor, all transactions are considered valid (no parsing/gas checks).
114-
func (e *DummyExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*FilterTxsResult, error) {
114+
func (e *DummyExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*FilterTxsResult, error) {
115115
// DummyExecutor doesn't do any filtering - return all txs as valid
116-
// GasPerTx is nil since DummyExecutor doesn't track gas
117116
return &FilterTxsResult{
118117
ValidTxs: txs,
119118
ForceIncludedMask: forceIncludedMask,
120-
GasPerTx: nil,
119+
RemainingTxs: nil,
121120
}, nil
122121
}

core/execution/execution.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@ import (
77

88
// FilterTxsResult contains the result of filtering transactions.
99
type FilterTxsResult struct {
10-
// ValidTxs contains transactions that passed validation.
10+
// ValidTxs contains transactions that passed validation and fit within gas limit.
1111
// Force-included txs that are invalid are removed.
12-
// Mempool txs are passed through unchanged.
12+
// Mempool txs are passed through unchanged (but may be trimmed for gas).
1313
ValidTxs [][]byte
1414

1515
// ForceIncludedMask indicates which ValidTxs are force-included (true = force-included).
1616
// Same length as ValidTxs.
1717
ForceIncludedMask []bool
1818

19-
// GasPerTx contains the gas for each transaction in ValidTxs.
20-
// For non-gas-based execution layers, this may be nil or all zeros.
21-
GasPerTx []uint64
19+
// RemainingTxs contains valid force-included transactions that didn't fit due to gas limit.
20+
// These should be re-queued for the next block.
21+
// Only force-included txs are returned here (mempool txs are handled by the sequencer).
22+
RemainingTxs [][]byte
2223
}
2324

2425
// ExecutionInfo contains execution layer parameters that may change per block.
@@ -121,27 +122,26 @@ type Executor interface {
121122
// - error: Any errors during retrieval
122123
GetExecutionInfo(ctx context.Context, height uint64) (ExecutionInfo, error)
123124

124-
// FilterTxs validates force-included transactions and calculates gas for all transactions.
125+
// FilterTxs validates force-included transactions and applies gas filtering.
125126
// Only transactions with forceIncludedMask[i]=true are validated for correctness.
126127
// Mempool transactions (forceIncludedMask[i]=false) are passed through unchanged.
127128
//
128129
// The function filters out:
129130
// - Invalid/unparseable force-included transactions (gibberish)
131+
// - Transactions that would exceed the cumulative gas limit (for force-included txs)
130132
//
131-
// Gas limiting is NOT performed by this function. The caller (sequencer) is responsible
132-
// for using the returned GasPerTx values to enforce gas limits.
133-
//
134-
// For non-gas-based execution layers, GasPerTx may be nil or all zeros.
133+
// For non-gas-based execution layers (maxGas=0), return all valid transactions.
135134
//
136135
// Parameters:
137136
// - ctx: Context for timeout/cancellation control
138137
// - txs: All transactions (force-included + mempool)
139138
// - forceIncludedMask: true for each tx that is force-included (needs validation)
139+
// - maxGas: Maximum cumulative gas allowed (0 means no gas limit)
140140
//
141141
// Returns:
142-
// - result: Contains valid txs, updated mask, and gas per tx
142+
// - result: Contains valid txs, updated mask, remaining txs, and gas used
143143
// - err: Any errors during filtering (not validation errors, which result in filtering)
144-
FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*FilterTxsResult, error)
144+
FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*FilterTxsResult, error)
145145
}
146146

147147
// HeightProvider is an optional interface that execution clients can implement

execution/evm/execution.go

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -788,14 +788,15 @@ func (c *EngineClient) GetExecutionInfo(ctx context.Context, height uint64) (exe
788788
return execution.ExecutionInfo{MaxGas: gasLimit}, nil
789789
}
790790

791-
// FilterTxs validates force-included transactions and calculates gas for all transactions.
791+
// FilterTxs validates force-included transactions and applies gas filtering.
792792
// Only transactions with forceIncludedMask[i]=true are validated for correctness.
793793
// Mempool transactions (forceIncludedMask[i]=false) are passed through unchanged.
794-
// Gas limiting is NOT performed by this function - the caller handles that using GasPerTx.
795-
func (c *EngineClient) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*execution.FilterTxsResult, error) {
794+
// Gas limiting is applied to force-included transactions; remaining valid ones are returned in RemainingTxs.
795+
func (c *EngineClient) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*execution.FilterTxsResult, error) {
796796
validTxs := make([][]byte, 0, len(txs))
797797
validMask := make([]bool, 0, len(txs))
798-
gasPerTx := make([]uint64, 0, len(txs))
798+
var remainingTxs [][]byte
799+
var cumulativeGas uint64
799800

800801
for i, tx := range txs {
801802
isForceIncluded := i < len(forceIncludedMask) && forceIncludedMask[i]
@@ -817,32 +818,62 @@ func (c *EngineClient) FilterTxs(ctx context.Context, txs [][]byte, forceInclude
817818
continue
818819
}
819820

821+
txGas := ethTx.Gas()
822+
823+
// Check gas limit for force-included transactions
824+
if maxGas > 0 && cumulativeGas+txGas > maxGas {
825+
// This tx and remaining force-included txs don't fit - add to remaining
826+
remainingTxs = append(remainingTxs, tx)
827+
// Continue to collect remaining valid force-included txs
828+
for j := i + 1; j < len(txs); j++ {
829+
if j < len(forceIncludedMask) && forceIncludedMask[j] {
830+
if len(txs[j]) == 0 {
831+
continue
832+
}
833+
var remainingEthTx types.Transaction
834+
if err := remainingEthTx.UnmarshalBinary(txs[j]); err != nil {
835+
c.logger.Debug().
836+
Int("tx_index", j).
837+
Err(err).
838+
Msg("filtering out invalid force-included transaction in remaining (gibberish)")
839+
continue
840+
}
841+
remainingTxs = append(remainingTxs, txs[j])
842+
} else {
843+
// Add remaining mempool txs to validTxs
844+
validTxs = append(validTxs, txs[j])
845+
validMask = append(validMask, false)
846+
}
847+
}
848+
849+
c.logger.Debug().
850+
Int("valid_txs", len(validTxs)).
851+
Int("remaining_txs", len(remainingTxs)).
852+
Uint64("cumulative_gas", cumulativeGas).
853+
Uint64("max_gas", maxGas).
854+
Msg("force-included transactions exceeded gas limit, splitting batch")
855+
856+
return &execution.FilterTxsResult{
857+
ValidTxs: validTxs,
858+
ForceIncludedMask: validMask,
859+
RemainingTxs: remainingTxs,
860+
}, nil
861+
}
862+
863+
cumulativeGas += txGas
820864
validTxs = append(validTxs, tx)
821865
validMask = append(validMask, true)
822-
gasPerTx = append(gasPerTx, ethTx.Gas())
823866
} else {
824867
// Mempool transactions pass through unchanged
825-
// Still calculate gas for them
826-
var txGas uint64
827-
if len(tx) > 0 {
828-
var ethTx types.Transaction
829-
if err := ethTx.UnmarshalBinary(tx); err == nil {
830-
txGas = ethTx.Gas()
831-
}
832-
// If parsing fails for mempool tx, we still include it with gas=0
833-
// The execution layer will handle it during actual execution
834-
}
835-
836868
validTxs = append(validTxs, tx)
837869
validMask = append(validMask, false)
838-
gasPerTx = append(gasPerTx, txGas)
839870
}
840871
}
841872

842873
return &execution.FilterTxsResult{
843874
ValidTxs: validTxs,
844875
ForceIncludedMask: validMask,
845-
GasPerTx: gasPerTx,
876+
RemainingTxs: nil,
846877
}, nil
847878
}
848879

execution/grpc/client.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,16 @@ func (c *Client) GetExecutionInfo(ctx context.Context, height uint64) (execution
132132
}, nil
133133
}
134134

135-
// FilterTxs validates force-included transactions and calculates gas for all transactions.
135+
// FilterTxs validates force-included transactions and applies gas filtering.
136136
//
137137
// This method sends transactions to the remote execution service for validation.
138138
// Only force-included transactions are validated; mempool transactions pass through unchanged.
139-
func (c *Client) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*execution.FilterTxsResult, error) {
139+
// Gas limiting is applied to force-included transactions.
140+
func (c *Client) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*execution.FilterTxsResult, error) {
140141
req := connect.NewRequest(&pb.FilterTxsRequest{
141142
Txs: txs,
142143
ForceIncludedMask: forceIncludedMask,
144+
MaxGas: maxGas,
143145
})
144146

145147
resp, err := c.client.FilterTxs(ctx, req)
@@ -150,6 +152,6 @@ func (c *Client) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask
150152
return &execution.FilterTxsResult{
151153
ValidTxs: resp.Msg.ValidTxs,
152154
ForceIncludedMask: resp.Msg.ForceIncludedMask,
153-
GasPerTx: resp.Msg.GasPerTx,
155+
RemainingTxs: resp.Msg.RemainingTxs,
154156
}, nil
155157
}

execution/grpc/client_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type mockExecutor struct {
1616
executeTxsFunc func(ctx context.Context, txs [][]byte, blockHeight uint64, timestamp time.Time, prevStateRoot []byte) ([]byte, error)
1717
setFinalFunc func(ctx context.Context, blockHeight uint64) error
1818
getExecutionInfoFunc func(ctx context.Context, height uint64) (execution.ExecutionInfo, error)
19-
filterTxsFunc func(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*execution.FilterTxsResult, error)
19+
filterTxsFunc func(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*execution.FilterTxsResult, error)
2020
}
2121

2222
func (m *mockExecutor) InitChain(ctx context.Context, genesisTime time.Time, initialHeight uint64, chainID string) ([]byte, error) {
@@ -54,15 +54,15 @@ func (m *mockExecutor) GetExecutionInfo(ctx context.Context, height uint64) (exe
5454
return execution.ExecutionInfo{MaxGas: 0}, nil
5555
}
5656

57-
func (m *mockExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*execution.FilterTxsResult, error) {
57+
func (m *mockExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*execution.FilterTxsResult, error) {
5858
if m.filterTxsFunc != nil {
59-
return m.filterTxsFunc(ctx, txs, forceIncludedMask)
59+
return m.filterTxsFunc(ctx, txs, forceIncludedMask, maxGas)
6060
}
61-
// Default: return all txs as valid, no gas info
61+
// Default: return all txs as valid, no remaining
6262
return &execution.FilterTxsResult{
6363
ValidTxs: txs,
6464
ForceIncludedMask: forceIncludedMask,
65-
GasPerTx: nil,
65+
RemainingTxs: nil,
6666
}, nil
6767
}
6868

execution/grpc/server.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,20 +156,20 @@ func (s *Server) GetExecutionInfo(
156156

157157
// FilterTxs handles the FilterTxs RPC request.
158158
//
159-
// It validates force-included transactions and calculates gas for all transactions.
159+
// It validates force-included transactions and applies gas filtering.
160160
// Only transactions with forceIncludedMask[i]=true are validated.
161161
func (s *Server) FilterTxs(
162162
ctx context.Context,
163163
req *connect.Request[pb.FilterTxsRequest],
164164
) (*connect.Response[pb.FilterTxsResponse], error) {
165-
result, err := s.executor.FilterTxs(ctx, req.Msg.Txs, req.Msg.ForceIncludedMask)
165+
result, err := s.executor.FilterTxs(ctx, req.Msg.Txs, req.Msg.ForceIncludedMask, req.Msg.MaxGas)
166166
if err != nil {
167167
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("failed to filter transactions: %w", err))
168168
}
169169

170170
return connect.NewResponse(&pb.FilterTxsResponse{
171171
ValidTxs: result.ValidTxs,
172172
ForceIncludedMask: result.ForceIncludedMask,
173-
GasPerTx: result.GasPerTx,
173+
RemainingTxs: result.RemainingTxs,
174174
}), nil
175175
}

pkg/sequencers/based/sequencer.go

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -156,44 +156,25 @@ func (s *BasedSequencer) GetNextBatch(ctx context.Context, req coresequencer.Get
156156
maxGas = info.MaxGas
157157
}
158158

159-
// Filter transactions - validates force-included txs and returns gas per tx
160-
filterResult, err := s.executor.FilterTxs(ctx, batchTxs, forceIncludedMask)
159+
// Filter transactions - validates force-included txs and applies gas filtering
160+
filterResult, err := s.executor.FilterTxs(ctx, batchTxs, forceIncludedMask, maxGas)
161161
if err != nil {
162162
s.logger.Warn().Err(err).Msg("failed to filter transactions, proceeding with unfiltered")
163163
filterResult = &execution.FilterTxsResult{
164164
ValidTxs: batchTxs,
165165
ForceIncludedMask: forceIncludedMask,
166-
GasPerTx: nil,
166+
RemainingTxs: nil,
167167
}
168168
}
169169

170-
// Apply gas limits using the returned GasPerTx
171-
var filteredTxs [][]byte
172-
var remainingGasFilteredTxs [][]byte
173-
var cumulativeGas uint64
174-
175-
for i, tx := range filterResult.ValidTxs {
176-
txGas := uint64(0)
177-
if filterResult.GasPerTx != nil && i < len(filterResult.GasPerTx) {
178-
txGas = filterResult.GasPerTx[i]
179-
}
180-
181-
// Check if this tx fits within gas limit
182-
if maxGas > 0 && cumulativeGas+txGas > maxGas {
183-
// This tx and remaining txs don't fit - save for next block
184-
remainingGasFilteredTxs = append(remainingGasFilteredTxs, filterResult.ValidTxs[i:]...)
185-
break
186-
}
187-
188-
cumulativeGas += txGas
189-
filteredTxs = append(filteredTxs, tx)
190-
}
170+
// FilterTxs returns valid txs that fit within gas, and remaining txs that didn't fit
171+
filteredTxs := filterResult.ValidTxs
172+
remainingGasFilteredTxs := filterResult.RemainingTxs
191173

192174
s.logger.Debug().
193175
Int("input_txs", len(batchTxs)).
194176
Int("filtered_txs", len(filteredTxs)).
195177
Int("remaining_for_next_block", len(remainingGasFilteredTxs)).
196-
Uint64("gas_used", cumulativeGas).
197178
Uint64("max_gas", maxGas).
198179
Msg("filtered DA transactions")
199180

pkg/sequencers/based/sequencer_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
type mockExecutor struct {
2727
maxGas uint64
2828
getInfoErr error
29-
filterFunc func(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*execution.FilterTxsResult, error)
29+
filterFunc func(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*execution.FilterTxsResult, error)
3030
}
3131

3232
func (m *mockExecutor) InitChain(ctx context.Context, genesisTime time.Time, initialHeight uint64, chainID string) ([]byte, error) {
@@ -49,15 +49,15 @@ func (m *mockExecutor) GetExecutionInfo(ctx context.Context, height uint64) (exe
4949
return execution.ExecutionInfo{MaxGas: m.maxGas}, m.getInfoErr
5050
}
5151

52-
func (m *mockExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool) (*execution.FilterTxsResult, error) {
52+
func (m *mockExecutor) FilterTxs(ctx context.Context, txs [][]byte, forceIncludedMask []bool, maxGas uint64) (*execution.FilterTxsResult, error) {
5353
if m.filterFunc != nil {
54-
return m.filterFunc(ctx, txs, forceIncludedMask)
54+
return m.filterFunc(ctx, txs, forceIncludedMask, maxGas)
5555
}
56-
// Default: return all txs as valid, no gas info
56+
// Default: return all txs as valid, no remaining
5757
return &execution.FilterTxsResult{
5858
ValidTxs: txs,
5959
ForceIncludedMask: forceIncludedMask,
60-
GasPerTx: nil,
60+
RemainingTxs: nil,
6161
}, nil
6262
}
6363

0 commit comments

Comments
 (0)