Skip to content

Commit dca6f94

Browse files
committed
Distinguish the 2 cases for fast-path submission for logging
1 parent 1e2b22e commit dca6f94

2 files changed

Lines changed: 56 additions & 16 deletions

File tree

services/requester/batch_tx_pool.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ const (
5151
// Max number of retries to perform on submission errors, such as
5252
// networking issues etc.
5353
maxSubmissionRetries = 5
54+
55+
// The possible reasons returned by `fastPathAvailable()`
56+
fastPathNoAvailability = "fast-path: conditions not satisfied"
57+
fastPathNoSpacing = "fast-path: not enough spacing elapsed"
58+
fastPathStateNonce = "fast-path: next unindexed nonce"
59+
fastPathInFlightNonce = "fast-path: next unsubmitted nonce"
5460
)
5561

5662
// BatchTxPool is a TxPool implementation that collects and groups transactions
@@ -145,25 +151,37 @@ func (t *txQueue) staleEntry(now time.Time, spacing time.Duration) bool {
145151
return len(t.txs) == 0 && now.Sub(t.lastSubmittedAt) >= (spacing*stalenessFactor)
146152
}
147153

148-
// validNonce compares the transaction nonce with the nonce from the local
149-
// state index and the last submission activity (if any), and returns whether
150-
// the transaction nonce is valid for submission.
151-
func (t *txQueue) validNonce(
154+
// fastPathAvailable checks whether there is a fast-path strategy, based on
155+
// the EOA's last activity and the given transaction nonce. If enough spacing
156+
// has elapsed since the EOA's last activity, for the given current time and
157+
// spacing duration, and the transaction nonce matches the nonce from the
158+
// local staate index or the last submission activity (if any), fast-path is
159+
// available.
160+
//
161+
// Returns the matching fast-path strategy, if any, and a boolean value which
162+
// denotes its availability.
163+
func (t *txQueue) fastPathAvailable(
164+
now time.Time,
165+
spacing time.Duration,
152166
txNonce uint64,
153167
stateNonce uint64,
154-
) bool {
168+
) (string, bool) {
169+
if !t.spacingElapsed(now, spacing) {
170+
return fastPathNoSpacing, false
171+
}
172+
155173
if txNonce == stateNonce {
156-
return true
174+
return fastPathStateNonce, true
157175
}
158176

159177
// a value of 0 for `lastSubmittedNonce` is legit, if this is the EOA's
160178
// first transaction ever, so we use `lastSubmittedAt` to differentiate
161179
// between Go's zero-value.
162180
if txNonce == t.lastSubmittedNonce+1 && !t.lastSubmittedAt.IsZero() {
163-
return true
181+
return fastPathInFlightNonce, true
164182
}
165183

166-
return false
184+
return fastPathNoAvailability, false
167185
}
168186

169187
// pruneTxs drops pooled transactions that can never be submitted from this
@@ -370,7 +388,8 @@ func (t *BatchTxPool) Add(
370388
// has elapsed and the tx nonce is the next expected, we submit right
371389
// away and update the `lastSubmittedAt` & `lastSubmittedNonce` fields,
372390
// for classifying future submissions, that might arrive shortly.
373-
if eoaQueue.spacingElapsed(time.Now(), t.config.TxBatchInterval) && eoaQueue.validNonce(tx.Nonce(), nonce) {
391+
reason, ok := eoaQueue.fastPathAvailable(time.Now(), t.config.TxBatchInterval, tx.Nonce(), nonce)
392+
if ok {
374393
// Bound the submit so a hung call cannot pin `txQueuesMux`
375394
// indefinitely (see `fastPathSubmitTimeout`).
376395
submitCtx, cancel := context.WithTimeout(ctx, fastPathSubmitTimeout)
@@ -387,7 +406,7 @@ func (t *BatchTxPool) Add(
387406
)
388407
return err
389408
}
390-
t.logSubmission(from, []pooledEvmTx{userTx}, flushReasonFastPath, flowTxID)
409+
t.logSubmission(from, []pooledEvmTx{userTx}, reason, flowTxID)
391410

392411
eoaQueue.lastSubmittedAt = time.Now()
393412
eoaQueue.lastSubmittedNonce = tx.Nonce()

services/requester/batch_tx_pool_test.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,31 +63,52 @@ func Test_TxQueue_StaleEntry(t *testing.T) {
6363
})
6464
}
6565

66-
func Test_TxQueue_ValidNonce(t *testing.T) {
66+
func Test_TxQueue_FastPathAvailable(t *testing.T) {
67+
now := time.Now()
68+
spacing := 2 * time.Second
69+
6770
t.Run("matches state nonce", func(t *testing.T) {
6871
q := &txQueue{}
69-
assert.True(t, q.validNonce(5, 5))
72+
reason, available := q.fastPathAvailable(now, spacing, 5, 5)
73+
assert.True(t, available)
74+
assert.Equal(t, fastPathStateNonce, reason)
75+
})
76+
77+
t.Run("matches lastSubmittedNonce+1 when there is prior activity with elapsed spacing", func(t *testing.T) {
78+
q := &txQueue{
79+
lastSubmittedNonce: 5,
80+
lastSubmittedAt: now.Add(-2 * spacing),
81+
}
82+
reason, available := q.fastPathAvailable(now, spacing, 6, 4)
83+
assert.True(t, available)
84+
assert.Equal(t, fastPathInFlightNonce, reason)
7085
})
7186

72-
t.Run("matches lastSubmittedNonce+1 when there is prior activity", func(t *testing.T) {
87+
t.Run("does not match lastSubmittedNonce+1 without elapsed spacing", func(t *testing.T) {
7388
q := &txQueue{
7489
lastSubmittedNonce: 5,
7590
lastSubmittedAt: time.Now(),
7691
}
77-
assert.True(t, q.validNonce(6, 4))
92+
reason, available := q.fastPathAvailable(now, spacing, 6, 4)
93+
assert.False(t, available)
94+
assert.Equal(t, fastPathNoSpacing, reason)
7895
})
7996

8097
t.Run("lastSubmittedNonce+1 without prior activity is rejected", func(t *testing.T) {
8198
q := &txQueue{lastSubmittedNonce: 0}
82-
assert.False(t, q.validNonce(1, 4))
99+
reason, available := q.fastPathAvailable(now, spacing, 1, 4)
100+
assert.False(t, available)
101+
assert.Equal(t, fastPathNoAvailability, reason)
83102
})
84103

85104
t.Run("arbitrary future nonce is rejected", func(t *testing.T) {
86105
q := &txQueue{
87106
lastSubmittedNonce: 5,
88107
lastSubmittedAt: time.Now(),
89108
}
90-
assert.False(t, q.validNonce(9, 5))
109+
reason, available := q.fastPathAvailable(now, spacing, 9, 5)
110+
assert.False(t, available)
111+
assert.Equal(t, fastPathNoSpacing, reason)
91112
})
92113
}
93114

0 commit comments

Comments
 (0)