@@ -51,6 +51,80 @@ func deriveSender(tx *types.Transaction) (common.Address, error) {
51
51
return types .Sender (types.HomesteadSigner {}, tx )
52
52
}
53
53
54
+ // This test simulates a scenario where a new block is imported during a
55
+ // state reset and tests whether the pending state is in sync with the
56
+ // block head event that initiated the resetState().
57
+ func TestStateChangeDuringPoolReset (t * testing.T ) {
58
+ var (
59
+ db , _ = ethdb .NewMemDatabase ()
60
+ key , _ = crypto .GenerateKey ()
61
+ address = crypto .PubkeyToAddress (key .PublicKey )
62
+ mux = new (event.TypeMux )
63
+ statedb , _ = state .New (common.Hash {}, db )
64
+ trigger = false
65
+ )
66
+
67
+ // setup pool with 2 transaction in it
68
+ statedb .SetBalance (address , new (big.Int ).Mul (common .Big1 , common .Ether ))
69
+
70
+ tx0 := transaction (0 , big .NewInt (100000 ), key )
71
+ tx1 := transaction (1 , big .NewInt (100000 ), key )
72
+
73
+ // stateFunc is used multiple times to reset the pending state.
74
+ // when simulate is true it will create a state that indicates
75
+ // that tx0 and tx1 are included in the chain.
76
+ stateFunc := func () (* state.StateDB , error ) {
77
+ // delay "state change" by one. The tx pool fetches the
78
+ // state multiple times and by delaying it a bit we simulate
79
+ // a state change between those fetches.
80
+ stdb := statedb
81
+ if trigger {
82
+ statedb , _ = state .New (common.Hash {}, db )
83
+ // simulate that the new head block included tx0 and tx1
84
+ statedb .SetNonce (address , 2 )
85
+ statedb .SetBalance (address , new (big.Int ).Mul (common .Big1 , common .Ether ))
86
+ trigger = false
87
+ }
88
+ return stdb , nil
89
+ }
90
+
91
+ gasLimitFunc := func () * big.Int { return big .NewInt (1000000000 ) }
92
+
93
+ txpool := NewTxPool (testChainConfig (), mux , stateFunc , gasLimitFunc )
94
+ txpool .resetState ()
95
+
96
+ nonce := txpool .State ().GetNonce (address )
97
+ if nonce != 0 {
98
+ t .Fatalf ("Invalid nonce, want 0, got %d" , nonce )
99
+ }
100
+
101
+ txpool .AddBatch (types.Transactions {tx0 , tx1 })
102
+
103
+ nonce = txpool .State ().GetNonce (address )
104
+ if nonce != 2 {
105
+ t .Fatalf ("Invalid nonce, want 2, got %d" , nonce )
106
+ }
107
+
108
+ // trigger state change in the background
109
+ trigger = true
110
+
111
+ txpool .resetState ()
112
+
113
+ pendingTx , err := txpool .Pending ()
114
+ if err != nil {
115
+ t .Fatalf ("Could not fetch pending transactions: %v" , err )
116
+ }
117
+
118
+ for addr , txs := range pendingTx {
119
+ t .Logf ("%0x: %d\n " , addr , len (txs ))
120
+ }
121
+
122
+ nonce = txpool .State ().GetNonce (address )
123
+ if nonce != 2 {
124
+ t .Fatalf ("Invalid nonce, want 2, got %d" , nonce )
125
+ }
126
+ }
127
+
54
128
func TestInvalidTransactions (t * testing.T ) {
55
129
pool , key := setupTxPool ()
56
130
@@ -97,9 +171,10 @@ func TestTransactionQueue(t *testing.T) {
97
171
from , _ := deriveSender (tx )
98
172
currentState , _ := pool .currentState ()
99
173
currentState .AddBalance (from , big .NewInt (1000 ))
174
+ pool .resetState ()
100
175
pool .enqueueTx (tx .Hash (), tx )
101
176
102
- pool .promoteExecutables ()
177
+ pool .promoteExecutables (currentState )
103
178
if len (pool .pending ) != 1 {
104
179
t .Error ("expected valid txs to be 1 is" , len (pool .pending ))
105
180
}
@@ -108,7 +183,7 @@ func TestTransactionQueue(t *testing.T) {
108
183
from , _ = deriveSender (tx )
109
184
currentState .SetNonce (from , 2 )
110
185
pool .enqueueTx (tx .Hash (), tx )
111
- pool .promoteExecutables ()
186
+ pool .promoteExecutables (currentState )
112
187
if _ , ok := pool .pending [from ].txs .items [tx .Nonce ()]; ok {
113
188
t .Error ("expected transaction to be in tx pool" )
114
189
}
@@ -124,11 +199,13 @@ func TestTransactionQueue(t *testing.T) {
124
199
from , _ = deriveSender (tx1 )
125
200
currentState , _ = pool .currentState ()
126
201
currentState .AddBalance (from , big .NewInt (1000 ))
202
+ pool .resetState ()
203
+
127
204
pool .enqueueTx (tx1 .Hash (), tx1 )
128
205
pool .enqueueTx (tx2 .Hash (), tx2 )
129
206
pool .enqueueTx (tx3 .Hash (), tx3 )
130
207
131
- pool .promoteExecutables ()
208
+ pool .promoteExecutables (currentState )
132
209
133
210
if len (pool .pending ) != 1 {
134
211
t .Error ("expected tx pool to be 1, got" , len (pool .pending ))
@@ -225,7 +302,8 @@ func TestTransactionDoubleNonce(t *testing.T) {
225
302
if err := pool .add (tx2 ); err != nil {
226
303
t .Error ("didn't expect error" , err )
227
304
}
228
- pool .promoteExecutables ()
305
+ state , _ := pool .currentState ()
306
+ pool .promoteExecutables (state )
229
307
if pool .pending [addr ].Len () != 1 {
230
308
t .Error ("expected 1 pending transactions, got" , pool .pending [addr ].Len ())
231
309
}
@@ -236,7 +314,7 @@ func TestTransactionDoubleNonce(t *testing.T) {
236
314
if err := pool .add (tx3 ); err != nil {
237
315
t .Error ("didn't expect error" , err )
238
316
}
239
- pool .promoteExecutables ()
317
+ pool .promoteExecutables (state )
240
318
if pool .pending [addr ].Len () != 1 {
241
319
t .Error ("expected 1 pending transactions, got" , pool .pending [addr ].Len ())
242
320
}
@@ -295,6 +373,7 @@ func TestRemovedTxEvent(t *testing.T) {
295
373
from , _ := deriveSender (tx )
296
374
currentState , _ := pool .currentState ()
297
375
currentState .AddBalance (from , big .NewInt (1000000000000 ))
376
+ pool .resetState ()
298
377
pool .eventMux .Post (RemovedTransactionEvent {types.Transactions {tx }})
299
378
pool .eventMux .Post (ChainHeadEvent {nil })
300
379
if pool .pending [from ].Len () != 1 {
@@ -452,6 +531,7 @@ func TestTransactionQueueAccountLimiting(t *testing.T) {
452
531
453
532
state , _ := pool .currentState ()
454
533
state .AddBalance (account , big .NewInt (1000000 ))
534
+ pool .resetState ()
455
535
456
536
// Keep queuing up transactions and make sure all above a limit are dropped
457
537
for i := uint64 (1 ); i <= maxQueuedPerAccount + 5 ; i ++ {
@@ -564,6 +644,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
564
644
565
645
state , _ := pool .currentState ()
566
646
state .AddBalance (account , big .NewInt (1000000 ))
647
+ pool .resetState ()
567
648
568
649
// Keep queuing up transactions and make sure all above a limit are dropped
569
650
for i := uint64 (0 ); i < maxQueuedPerAccount + 5 ; i ++ {
@@ -733,7 +814,7 @@ func benchmarkPendingDemotion(b *testing.B, size int) {
733
814
// Benchmark the speed of pool validation
734
815
b .ResetTimer ()
735
816
for i := 0 ; i < b .N ; i ++ {
736
- pool .demoteUnexecutables ()
817
+ pool .demoteUnexecutables (state )
737
818
}
738
819
}
739
820
@@ -757,7 +838,7 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
757
838
// Benchmark the speed of pool validation
758
839
b .ResetTimer ()
759
840
for i := 0 ; i < b .N ; i ++ {
760
- pool .promoteExecutables ()
841
+ pool .promoteExecutables (state )
761
842
}
762
843
}
763
844
0 commit comments