@@ -27,7 +27,6 @@ import (
27
27
"path/filepath"
28
28
"sync"
29
29
"testing"
30
- "time"
31
30
32
31
"github.com/ethereum/go-ethereum/common"
33
32
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
@@ -53,33 +52,22 @@ var (
53
52
emptyBlobVHash = kzg4844 .CalcBlobHashV1 (sha256 .New (), & emptyBlobCommit )
54
53
)
55
54
56
- // Chain configuration with Cancun enabled.
57
- //
58
- // TODO(karalabe): replace with params.MainnetChainConfig after Cancun.
59
- var testChainConfig * params.ChainConfig
60
-
61
- func init () {
62
- testChainConfig = new (params.ChainConfig )
63
- * testChainConfig = * params .MainnetChainConfig
64
-
65
- testChainConfig .CancunTime = new (uint64 )
66
- * testChainConfig .CancunTime = uint64 (time .Now ().Unix ())
67
- }
68
-
69
55
// testBlockChain is a mock of the live chain for testing the pool.
70
56
type testBlockChain struct {
71
57
config * params.ChainConfig
72
58
basefee * uint256.Int
73
59
blobfee * uint256.Int
74
60
statedb * state.StateDB
61
+
62
+ blocks map [uint64 ]* types.Block
75
63
}
76
64
77
65
func (bc * testBlockChain ) Config () * params.ChainConfig {
78
66
return bc .config
79
67
}
80
68
81
69
func (bc * testBlockChain ) CurrentBlock () * types.Header {
82
- // Yolo, life is too short to invert mist .CalcBaseFee and misc.CalcBlobFee,
70
+ // Yolo, life is too short to invert misc .CalcBaseFee and misc.CalcBlobFee,
83
71
// just binary search it them.
84
72
85
73
// The base fee at 5714 ETH translates into the 21000 base gas higher than
@@ -142,7 +130,14 @@ func (bc *testBlockChain) CurrentFinalBlock() *types.Header {
142
130
}
143
131
144
132
func (bc * testBlockChain ) GetBlock (hash common.Hash , number uint64 ) * types.Block {
145
- return nil
133
+ // This is very yolo for the tests. If the number is the origin block we use
134
+ // to init the pool, return an empty block with the correct starting header.
135
+ //
136
+ // If it is something else, return some baked in mock data.
137
+ if number == bc .config .LondonBlock .Uint64 ()+ 1 {
138
+ return types .NewBlockWithHeader (bc .CurrentBlock ())
139
+ }
140
+ return bc .blocks [number ]
146
141
}
147
142
148
143
func (bc * testBlockChain ) StateAt (common.Hash ) (* state.StateDB , error ) {
@@ -181,14 +176,14 @@ func makeAddressReserver() txpool.AddressReserver {
181
176
// the blob pool.
182
177
func makeTx (nonce uint64 , gasTipCap uint64 , gasFeeCap uint64 , blobFeeCap uint64 , key * ecdsa.PrivateKey ) * types.Transaction {
183
178
blobtx := makeUnsignedTx (nonce , gasTipCap , gasFeeCap , blobFeeCap )
184
- return types .MustSignNewTx (key , types .LatestSigner (testChainConfig ), blobtx )
179
+ return types .MustSignNewTx (key , types .LatestSigner (params . MainnetChainConfig ), blobtx )
185
180
}
186
181
187
182
// makeUnsignedTx is a utility method to construct a random blob transaction
188
183
// without signing it.
189
184
func makeUnsignedTx (nonce uint64 , gasTipCap uint64 , gasFeeCap uint64 , blobFeeCap uint64 ) * types.BlobTx {
190
185
return & types.BlobTx {
191
- ChainID : uint256 .MustFromBig (testChainConfig .ChainID ),
186
+ ChainID : uint256 .MustFromBig (params . MainnetChainConfig .ChainID ),
192
187
Nonce : nonce ,
193
188
GasTipCap : uint256 .NewInt (gasTipCap ),
194
189
GasFeeCap : uint256 .NewInt (gasFeeCap ),
@@ -229,13 +224,17 @@ func verifyPoolInternals(t *testing.T, pool *BlobPool) {
229
224
for hash := range seen {
230
225
t .Errorf ("indexed transaction hash #%x missing from lookup table" , hash )
231
226
}
232
- // Verify that transactions are sorted per account and contain no nonce gaps
227
+ // Verify that transactions are sorted per account and contain no nonce gaps,
228
+ // and that the first nonce is the next expected one based on the state.
233
229
for addr , txs := range pool .index {
234
230
for i := 1 ; i < len (txs ); i ++ {
235
231
if txs [i ].nonce != txs [i - 1 ].nonce + 1 {
236
232
t .Errorf ("addr %v, tx %d nonce mismatch: have %d, want %d" , addr , i , txs [i ].nonce , txs [i - 1 ].nonce + 1 )
237
233
}
238
234
}
235
+ if txs [0 ].nonce != pool .state .GetNonce (addr ) {
236
+ t .Errorf ("addr %v, first tx nonce mismatch: have %d, want %d" , addr , txs [0 ].nonce , pool .state .GetNonce (addr ))
237
+ }
239
238
}
240
239
// Verify that calculated evacuation thresholds are correct
241
240
for addr , txs := range pool .index {
@@ -331,7 +330,7 @@ func TestOpenDrops(t *testing.T) {
331
330
// Insert a transaction with a bad signature to verify that stale junk after
332
331
// potential hard-forks can get evicted (case 2)
333
332
tx := types .NewTx (& types.BlobTx {
334
- ChainID : uint256 .MustFromBig (testChainConfig .ChainID ),
333
+ ChainID : uint256 .MustFromBig (params . MainnetChainConfig .ChainID ),
335
334
GasTipCap : new (uint256.Int ),
336
335
GasFeeCap : new (uint256.Int ),
337
336
Gas : 0 ,
@@ -560,7 +559,7 @@ func TestOpenDrops(t *testing.T) {
560
559
statedb .Commit (0 , true )
561
560
562
561
chain := & testBlockChain {
563
- config : testChainConfig ,
562
+ config : params . MainnetChainConfig ,
564
563
basefee : uint256 .NewInt (params .InitialBaseFee ),
565
564
blobfee : uint256 .NewInt (params .BlobTxMinBlobGasprice ),
566
565
statedb : statedb ,
@@ -679,7 +678,7 @@ func TestOpenIndex(t *testing.T) {
679
678
statedb .Commit (0 , true )
680
679
681
680
chain := & testBlockChain {
682
- config : testChainConfig ,
681
+ config : params . MainnetChainConfig ,
683
682
basefee : uint256 .NewInt (params .InitialBaseFee ),
684
683
blobfee : uint256 .NewInt (params .BlobTxMinBlobGasprice ),
685
684
statedb : statedb ,
@@ -781,7 +780,7 @@ func TestOpenHeap(t *testing.T) {
781
780
statedb .Commit (0 , true )
782
781
783
782
chain := & testBlockChain {
784
- config : testChainConfig ,
783
+ config : params . MainnetChainConfig ,
785
784
basefee : uint256 .NewInt (1050 ),
786
785
blobfee : uint256 .NewInt (105 ),
787
786
statedb : statedb ,
@@ -861,7 +860,7 @@ func TestOpenCap(t *testing.T) {
861
860
statedb .Commit (0 , true )
862
861
863
862
chain := & testBlockChain {
864
- config : testChainConfig ,
863
+ config : params . MainnetChainConfig ,
865
864
basefee : uint256 .NewInt (1050 ),
866
865
blobfee : uint256 .NewInt (105 ),
867
866
statedb : statedb ,
@@ -908,23 +907,28 @@ func TestOpenCap(t *testing.T) {
908
907
func TestAdd (t * testing.T ) {
909
908
log .SetDefault (log .NewLogger (log .NewTerminalHandlerWithLevel (os .Stderr , log .LevelTrace , true )))
910
909
911
- // seed is a helper tumpe to seed an initial state db and pool
910
+ // seed is a helper tuple to seed an initial state db and pool
912
911
type seed struct {
913
912
balance uint64
914
913
nonce uint64
915
914
txs []* types.BlobTx
916
915
}
917
-
918
916
// addtx is a helper sender/tx tuple to represent a new tx addition
919
917
type addtx struct {
920
918
from string
921
919
tx * types.BlobTx
922
920
err error
923
921
}
922
+ // newhead ius a helper tumple to represent a chain head event
923
+ type newhead struct {
924
+ header * types.Header
925
+ txs []* types.BlobTx
926
+ }
924
927
925
928
tests := []struct {
926
929
seeds map [string ]seed
927
930
adds []addtx
931
+ block []addtx
928
932
}{
929
933
// Transactions from new accounts should be accepted if their initial
930
934
// nonce matches the expected one from the statedb. Higher or lower must
@@ -1250,6 +1254,25 @@ func TestAdd(t *testing.T) {
1250
1254
},
1251
1255
},
1252
1256
},
1257
+ // Tests issue #30518 where a refactor broke internal state invariants,
1258
+ // causing included transactions not to be properly accounted and thus
1259
+ // account states going our of sync with the chain.
1260
+ {
1261
+ seeds : map [string ]seed {
1262
+ "alice" : {
1263
+ balance : 1000000 ,
1264
+ txs : []* types.BlobTx {
1265
+ makeUnsignedTx (0 , 1 , 1 , 1 ),
1266
+ },
1267
+ },
1268
+ },
1269
+ block : []addtx {
1270
+ {
1271
+ from : "alice" ,
1272
+ tx : makeUnsignedTx (0 , 1 , 1 , 1 ),
1273
+ },
1274
+ },
1275
+ },
1253
1276
}
1254
1277
for i , tt := range tests {
1255
1278
// Create a temporary folder for the persistent backend
@@ -1276,7 +1299,7 @@ func TestAdd(t *testing.T) {
1276
1299
1277
1300
// Sign the seed transactions and store them in the data store
1278
1301
for _ , tx := range seed .txs {
1279
- signed := types .MustSignNewTx (keys [acc ], types .LatestSigner (testChainConfig ), tx )
1302
+ signed := types .MustSignNewTx (keys [acc ], types .LatestSigner (params . MainnetChainConfig ), tx )
1280
1303
blob , _ := rlp .EncodeToBytes (signed )
1281
1304
store .Put (blob )
1282
1305
}
@@ -1286,7 +1309,7 @@ func TestAdd(t *testing.T) {
1286
1309
1287
1310
// Create a blob pool out of the pre-seeded dats
1288
1311
chain := & testBlockChain {
1289
- config : testChainConfig ,
1312
+ config : params . MainnetChainConfig ,
1290
1313
basefee : uint256 .NewInt (1050 ),
1291
1314
blobfee : uint256 .NewInt (105 ),
1292
1315
statedb : statedb ,
@@ -1299,14 +1322,40 @@ func TestAdd(t *testing.T) {
1299
1322
1300
1323
// Add each transaction one by one, verifying the pool internals in between
1301
1324
for j , add := range tt .adds {
1302
- signed , _ := types .SignNewTx (keys [add .from ], types .LatestSigner (testChainConfig ), add .tx )
1325
+ signed , _ := types .SignNewTx (keys [add .from ], types .LatestSigner (params . MainnetChainConfig ), add .tx )
1303
1326
if err := pool .add (signed ); ! errors .Is (err , add .err ) {
1304
1327
t .Errorf ("test %d, tx %d: adding transaction error mismatch: have %v, want %v" , i , j , err , add .err )
1305
1328
}
1306
1329
verifyPoolInternals (t , pool )
1307
1330
}
1308
- // Verify the pool internals and close down the test
1309
1331
verifyPoolInternals (t , pool )
1332
+
1333
+ // If the test contains a chain head event, run that and gain verify the internals
1334
+ if tt .block != nil {
1335
+ // Fake a header for the new set of transactions
1336
+ header := & types.Header {
1337
+ Number : big .NewInt (int64 (chain .CurrentBlock ().Number .Uint64 () + 1 )),
1338
+ BaseFee : chain .CurrentBlock ().BaseFee , // invalid, but nothing checks it, yolo
1339
+ }
1340
+ // Inject the fake block into the chain
1341
+ txs := make ([]* types.Transaction , len (tt .block ))
1342
+ for j , inc := range tt .block {
1343
+ txs [j ] = types .MustSignNewTx (keys [inc .from ], types .LatestSigner (params .MainnetChainConfig ), inc .tx )
1344
+ }
1345
+ chain .blocks = map [uint64 ]* types.Block {
1346
+ header .Number .Uint64 (): types .NewBlockWithHeader (header ).WithBody (types.Body {
1347
+ Transactions : txs ,
1348
+ }),
1349
+ }
1350
+ // Apply the nonce updates to the state db
1351
+ for _ , tx := range txs {
1352
+ sender , _ := types .Sender (types .LatestSigner (params .MainnetChainConfig ), tx )
1353
+ chain .statedb .SetNonce (sender , tx .Nonce ()+ 1 )
1354
+ }
1355
+ pool .Reset (chain .CurrentBlock (), header )
1356
+ verifyPoolInternals (t , pool )
1357
+ }
1358
+ // Close down the test
1310
1359
pool .Close ()
1311
1360
}
1312
1361
}
@@ -1325,10 +1374,10 @@ func benchmarkPoolPending(b *testing.B, datacap uint64) {
1325
1374
var (
1326
1375
basefee = uint64 (1050 )
1327
1376
blobfee = uint64 (105 )
1328
- signer = types .LatestSigner (testChainConfig )
1377
+ signer = types .LatestSigner (params . MainnetChainConfig )
1329
1378
statedb , _ = state .New (types .EmptyRootHash , state .NewDatabaseForTesting ())
1330
1379
chain = & testBlockChain {
1331
- config : testChainConfig ,
1380
+ config : params . MainnetChainConfig ,
1332
1381
basefee : uint256 .NewInt (basefee ),
1333
1382
blobfee : uint256 .NewInt (blobfee ),
1334
1383
statedb : statedb ,
0 commit comments