@@ -2,6 +2,7 @@ package ethfinalizer
22
33import (
44 "context"
5+ "fmt"
56 "sync"
67 "time"
78
@@ -15,35 +16,40 @@ type Mempool[T any] interface {
1516 Nonce (ctx context.Context ) (uint64 , error )
1617
1718 // Commit persists the signed transaction with its metadata in the store.
18- // The transaction must be persisted with a timestamp of the current time .
19- // If the transaction already exists in the mempool, the timestamp must be updated.
19+ // The transaction must be persisted with timestamps of the first and latest submissions .
20+ // If the transaction already exists in the mempool, the latest timestamp must be updated.
2021 Commit (ctx context.Context , transaction * types.Transaction , metadata T ) error
2122
23+ // SetError sets the error for a previously committed transaction.
24+ SetError (ctx context.Context , transaction common.Hash , err error ) error
25+
2226 // Transactions returns the transactions for the specified hashes which are signed by this specific wallet for this specific chain.
2327 Transactions (ctx context.Context , hashes map [common.Hash ]struct {}) (map [common.Hash ]* Transaction [T ], error )
2428
2529 // PriciestTransactions returns, by nonce, the most expensive transactions signed by this specific wallet for this specific chain, with a minimum nonce and a latest timestamp.
2630 PriciestTransactions (ctx context.Context , fromNonce uint64 , before time.Time ) (map [uint64 ]* Transaction [T ], error )
31+
32+ // Status returns the statuses for the first and latest transactions for a given nonce.
33+ Status (ctx context.Context , nonce uint64 ) (* Status [T ], * Status [T ], error )
2734}
2835
2936type memoryMempool [T any ] struct {
30- transactions map [common.Hash ]* Transaction [T ]
31- priciestTransactions map [uint64 ]* timestampedTransaction [T ]
32- highestNonce * uint64
33- mu sync.RWMutex
37+ transactions map [common.Hash ]* Status [T ]
38+ nonces map [uint64 ]* nonceStatus [T ]
39+ highestNonce * uint64
40+ mu sync.RWMutex
3441}
3542
36- type timestampedTransaction [T any ] struct {
37- * Transaction [T ]
38-
39- timestamp time.Time
43+ type nonceStatus [T any ] struct {
44+ first , latest * Status [T ]
45+ time time.Time
4046}
4147
4248// NewMemoryMempool creates a minimal in-memory Mempool.
4349func NewMemoryMempool [T any ]() Mempool [T ] {
4450 return & memoryMempool [T ]{
45- transactions : map [common.Hash ]* Transaction [T ]{},
46- priciestTransactions : map [uint64 ]* timestampedTransaction [T ]{},
51+ transactions : map [common.Hash ]* Status [T ]{},
52+ nonces : map [uint64 ]* nonceStatus [T ]{},
4753 }
4854}
4955
@@ -62,28 +68,49 @@ func (m *memoryMempool[T]) Commit(ctx context.Context, transaction *types.Transa
6268 m .mu .Lock ()
6369 defer m .mu .Unlock ()
6470
65- transaction_ := Transaction [T ]{
66- Transaction : transaction ,
67- Metadata : metadata ,
68- }
69-
70- m .transactions [transaction .Hash ()] = & transaction_
71+ now := time .Now ()
7172
72- previous := m .priciestTransactions [transaction .Nonce ()]
73- if previous == nil || transaction .GasFeeCapCmp (previous .Transaction .Transaction ) > 0 && transaction .GasTipCapCmp (previous .Transaction .Transaction ) > 0 {
74- m .priciestTransactions [transaction .Nonce ()] = & timestampedTransaction [T ]{
75- Transaction : & transaction_ ,
76- timestamp : time .Now (),
73+ status_ := Status [T ]{
74+ Transaction : & Transaction [T ]{
75+ Transaction : transaction ,
76+ Metadata : metadata ,
77+ },
78+ Time : now ,
79+ }
80+ m .transactions [transaction .Hash ()] = & status_
81+
82+ status := m .nonces [transaction .Nonce ()]
83+ if status == nil {
84+ status = & nonceStatus [T ]{
85+ first : & status_ ,
86+ latest : & status_ ,
87+ time : now ,
7788 }
89+ m .nonces [transaction .Nonce ()] = status
7890
7991 if m .highestNonce == nil || transaction .Nonce () > * m .highestNonce {
8092 m .highestNonce = new (uint64 )
8193 * m .highestNonce = transaction .Nonce ()
8294 }
83- } else if previous .Hash () == transaction .Hash () {
84- previous .timestamp = time .Now ()
8595 }
8696
97+ if transaction .Hash () == status .latest .Transaction .Hash () {
98+ status .time = now
99+ } else if transaction .GasFeeCapCmp (status .latest .Transaction .Transaction ) > 0 && transaction .GasTipCapCmp (status .latest .Transaction .Transaction ) > 0 {
100+ status .latest = & status_
101+ status .time = now
102+ }
103+
104+ return nil
105+ }
106+
107+ func (m * memoryMempool [T ]) SetError (ctx context.Context , transaction common.Hash , err error ) error {
108+ status := m .transactions [transaction ]
109+ if status == nil {
110+ return fmt .Errorf ("unknown transaction %v" , transaction )
111+ }
112+
113+ status .Error = err
87114 return nil
88115}
89116
@@ -93,9 +120,9 @@ func (m *memoryMempool[T]) Transactions(ctx context.Context, hashes map[common.H
93120
94121 transactions := make (map [common.Hash ]* Transaction [T ], len (hashes ))
95122 for hash := range hashes {
96- transaction := m .transactions [hash ]
97- if transaction != nil {
98- transactions [hash ] = transaction
123+ status := m .transactions [hash ]
124+ if status != nil {
125+ transactions [hash ] = status . Transaction
99126 }
100127 }
101128
@@ -113,12 +140,22 @@ func (m *memoryMempool[T]) PriciestTransactions(ctx context.Context, fromNonce u
113140
114141 transactions := make (map [uint64 ]* Transaction [T ], capacity )
115142 for nonce := fromNonce ; ; nonce ++ {
116- transaction := m .priciestTransactions [nonce ]
117- if transaction == nil || ! transaction . timestamp .Before (before ) {
143+ status := m .nonces [nonce ]
144+ if status == nil || ! status . time .Before (before ) {
118145 break
119146 }
120- transactions [nonce ] = transaction .Transaction
147+
148+ transactions [nonce ] = status .latest .Transaction
121149 }
122150
123151 return transactions , nil
124152}
153+
154+ func (m * memoryMempool [T ]) Status (ctx context.Context , nonce uint64 ) (* Status [T ], * Status [T ], error ) {
155+ status := m .nonces [nonce ]
156+ if status == nil {
157+ return nil , nil , nil
158+ }
159+
160+ return status .first , status .latest , nil
161+ }
0 commit comments