@@ -22,6 +22,7 @@ import (
22
22
"io"
23
23
"math/big"
24
24
"sync/atomic"
25
+ "time"
25
26
26
27
"github.com/ethereum/go-ethereum/common"
27
28
"github.com/ethereum/go-ethereum/common/hexutil"
36
37
)
37
38
38
39
type Transaction struct {
39
- data txdata
40
+ data txdata // Consensus contents of a transaction
41
+ time time.Time // Time first seen locally (spam avoidance)
42
+
40
43
// caches
41
44
hash atomic.Value
42
45
size atomic.Value
@@ -100,8 +103,10 @@ func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit
100
103
if gasPrice != nil {
101
104
d .Price .Set (gasPrice )
102
105
}
103
-
104
- return & Transaction {data : d }
106
+ return & Transaction {
107
+ data : d ,
108
+ time : time .Now (),
109
+ }
105
110
}
106
111
107
112
// ChainId returns which chain id this transaction was signed for (if at all)
@@ -134,8 +139,8 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
134
139
err := s .Decode (& tx .data )
135
140
if err == nil {
136
141
tx .size .Store (common .StorageSize (rlp .ListSize (size )))
142
+ tx .time = time .Now ()
137
143
}
138
-
139
144
return err
140
145
}
141
146
@@ -153,7 +158,6 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
153
158
if err := dec .UnmarshalJSON (input ); err != nil {
154
159
return err
155
160
}
156
-
157
161
withSignature := dec .V .Sign () != 0 || dec .R .Sign () != 0 || dec .S .Sign () != 0
158
162
if withSignature {
159
163
var V byte
@@ -167,8 +171,10 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
167
171
return ErrInvalidSig
168
172
}
169
173
}
170
-
171
- * tx = Transaction {data : dec }
174
+ * tx = Transaction {
175
+ data : dec ,
176
+ time : time .Now (),
177
+ }
172
178
return nil
173
179
}
174
180
@@ -246,7 +252,10 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
246
252
if err != nil {
247
253
return nil , err
248
254
}
249
- cpy := & Transaction {data : tx .data }
255
+ cpy := & Transaction {
256
+ data : tx .data ,
257
+ time : tx .time ,
258
+ }
250
259
cpy .data .R , cpy .data .S , cpy .data .V = r , s , v
251
260
return cpy , nil
252
261
}
@@ -306,19 +315,27 @@ func (s TxByNonce) Len() int { return len(s) }
306
315
func (s TxByNonce ) Less (i , j int ) bool { return s [i ].data .AccountNonce < s [j ].data .AccountNonce }
307
316
func (s TxByNonce ) Swap (i , j int ) { s [i ], s [j ] = s [j ], s [i ] }
308
317
309
- // TxByPrice implements both the sort and the heap interface, making it useful
318
+ // TxByPriceAndTime implements both the sort and the heap interface, making it useful
310
319
// for all at once sorting as well as individually adding and removing elements.
311
- type TxByPrice Transactions
312
-
313
- func (s TxByPrice ) Len () int { return len (s ) }
314
- func (s TxByPrice ) Less (i , j int ) bool { return s [i ].data .Price .Cmp (s [j ].data .Price ) > 0 }
315
- func (s TxByPrice ) Swap (i , j int ) { s [i ], s [j ] = s [j ], s [i ] }
320
+ type TxByPriceAndTime Transactions
321
+
322
+ func (s TxByPriceAndTime ) Len () int { return len (s ) }
323
+ func (s TxByPriceAndTime ) Less (i , j int ) bool {
324
+ // If the prices are equal, use the time the transaction was first seen for
325
+ // deterministic sorting
326
+ cmp := s [i ].data .Price .Cmp (s [j ].data .Price )
327
+ if cmp == 0 {
328
+ return s [i ].time .Before (s [j ].time )
329
+ }
330
+ return cmp > 0
331
+ }
332
+ func (s TxByPriceAndTime ) Swap (i , j int ) { s [i ], s [j ] = s [j ], s [i ] }
316
333
317
- func (s * TxByPrice ) Push (x interface {}) {
334
+ func (s * TxByPriceAndTime ) Push (x interface {}) {
318
335
* s = append (* s , x .(* Transaction ))
319
336
}
320
337
321
- func (s * TxByPrice ) Pop () interface {} {
338
+ func (s * TxByPriceAndTime ) Pop () interface {} {
322
339
old := * s
323
340
n := len (old )
324
341
x := old [n - 1 ]
@@ -331,7 +348,7 @@ func (s *TxByPrice) Pop() interface{} {
331
348
// entire batches of transactions for non-executable accounts.
332
349
type TransactionsByPriceAndNonce struct {
333
350
txs map [common.Address ]Transactions // Per account nonce-sorted list of transactions
334
- heads TxByPrice // Next transaction for each unique account (price heap)
351
+ heads TxByPriceAndTime // Next transaction for each unique account (price heap)
335
352
signer Signer // Signer for the set of transactions
336
353
}
337
354
@@ -341,8 +358,8 @@ type TransactionsByPriceAndNonce struct {
341
358
// Note, the input map is reowned so the caller should not interact any more with
342
359
// if after providing it to the constructor.
343
360
func NewTransactionsByPriceAndNonce (signer Signer , txs map [common.Address ]Transactions ) * TransactionsByPriceAndNonce {
344
- // Initialize a price based heap with the head transactions
345
- heads := make (TxByPrice , 0 , len (txs ))
361
+ // Initialize a price and received time based heap with the head transactions
362
+ heads := make (TxByPriceAndTime , 0 , len (txs ))
346
363
for from , accTxs := range txs {
347
364
heads = append (heads , accTxs [0 ])
348
365
// Ensure the sender address is from the signer
0 commit comments