@@ -2287,3 +2287,78 @@ func TestSideImportPrunedBlocks(t *testing.T) {
2287
2287
t .Errorf ("Got error, %v" , err )
2288
2288
}
2289
2289
}
2290
+
2291
+ // TestDeleteCreateRevert tests a weird state transition corner case that we hit
2292
+ // while changing the internals of statedb. The workflow is that a contract is
2293
+ // self destructed, then in a followup transaction (but same block) it's created
2294
+ // again and the transaction reverted.
2295
+ //
2296
+ // The original statedb implementation flushed dirty objects to the tries after
2297
+ // each transaction, so this works ok. The rework accumulated writes in memory
2298
+ // first, but the journal wiped the entire state object on create-revert.
2299
+ func TestDeleteCreateRevert (t * testing.T ) {
2300
+ var (
2301
+ aa = common .HexToAddress ("0x000000000000000000000000000000000000aaaa" )
2302
+ bb = common .HexToAddress ("0x000000000000000000000000000000000000bbbb" )
2303
+ // Generate a canonical chain to act as the main dataset
2304
+ engine = ethash .NewFaker ()
2305
+ db = rawdb .NewMemoryDatabase ()
2306
+
2307
+ // A sender who makes transactions, has some funds
2308
+ key , _ = crypto .HexToECDSA ("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" )
2309
+ address = crypto .PubkeyToAddress (key .PublicKey )
2310
+ funds = big .NewInt (1000000000 )
2311
+ gspec = & Genesis {
2312
+ Config : params .TestChainConfig ,
2313
+ Alloc : GenesisAlloc {
2314
+ address : {Balance : funds },
2315
+ // The address 0xAAAAA selfdestructs if called
2316
+ aa : {
2317
+ // Code needs to just selfdestruct
2318
+ Code : []byte {byte (vm .PC ), 0xFF },
2319
+ Nonce : 1 ,
2320
+ Balance : big .NewInt (0 ),
2321
+ },
2322
+ // The address 0xBBBB send 1 wei to 0xAAAA, then reverts
2323
+ bb : {
2324
+ Code : []byte {
2325
+ byte (vm .PC ), // [0]
2326
+ byte (vm .DUP1 ), // [0,0]
2327
+ byte (vm .DUP1 ), // [0,0,0]
2328
+ byte (vm .DUP1 ), // [0,0,0,0]
2329
+ byte (vm .PUSH1 ), 0x01 , // [0,0,0,0,1] (value)
2330
+ byte (vm .PUSH2 ), 0xaa , 0xaa , // [0,0,0,0,1, 0xaaaa]
2331
+ byte (vm .GAS ),
2332
+ byte (vm .CALL ),
2333
+ byte (vm .REVERT ),
2334
+ },
2335
+ Balance : big .NewInt (1 ),
2336
+ },
2337
+ },
2338
+ }
2339
+ genesis = gspec .MustCommit (db )
2340
+ )
2341
+
2342
+ blocks , _ := GenerateChain (params .TestChainConfig , genesis , engine , db , 1 , func (i int , b * BlockGen ) {
2343
+ b .SetCoinbase (common.Address {1 })
2344
+ // One transaction to AAAA
2345
+ tx , _ := types .SignTx (types .NewTransaction (0 , aa ,
2346
+ big .NewInt (0 ), 50000 , big .NewInt (1 ), nil ), types.HomesteadSigner {}, key )
2347
+ b .AddTx (tx )
2348
+ // One transaction to BBBB
2349
+ tx , _ = types .SignTx (types .NewTransaction (1 , bb ,
2350
+ big .NewInt (0 ), 100000 , big .NewInt (1 ), nil ), types.HomesteadSigner {}, key )
2351
+ b .AddTx (tx )
2352
+ })
2353
+ // Import the canonical chain
2354
+ diskdb := rawdb .NewMemoryDatabase ()
2355
+ gspec .MustCommit (diskdb )
2356
+
2357
+ chain , err := NewBlockChain (diskdb , nil , params .TestChainConfig , engine , vm.Config {}, nil )
2358
+ if err != nil {
2359
+ t .Fatalf ("failed to create tester chain: %v" , err )
2360
+ }
2361
+ if n , err := chain .InsertChain (blocks ); err != nil {
2362
+ t .Fatalf ("block %d: failed to insert into chain: %v" , n , err )
2363
+ }
2364
+ }
0 commit comments