diff options
author | Martin Holst Swende <martin@swende.se> | 2019-09-16 16:39:41 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2019-09-16 16:42:14 +0800 |
commit | f49d6e5ec09b740ae88c3a04edbe60b357b81991 (patch) | |
tree | 822ddb1a6ec1a3f495f897c1d86267f186d704e9 | |
parent | 223b950944f494a5b4e0957fd9f92c48b09037ad (diff) | |
download | go-tangerine-f49d6e5ec09b740ae88c3a04edbe60b357b81991.tar go-tangerine-f49d6e5ec09b740ae88c3a04edbe60b357b81991.tar.gz go-tangerine-f49d6e5ec09b740ae88c3a04edbe60b357b81991.tar.bz2 go-tangerine-f49d6e5ec09b740ae88c3a04edbe60b357b81991.tar.lz go-tangerine-f49d6e5ec09b740ae88c3a04edbe60b357b81991.tar.xz go-tangerine-f49d6e5ec09b740ae88c3a04edbe60b357b81991.tar.zst go-tangerine-f49d6e5ec09b740ae88c3a04edbe60b357b81991.zip |
core: add blockchain test too for revert cornercase
-rw-r--r-- | core/blockchain_test.go | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/core/blockchain_test.go b/core/blockchain_test.go index db624c4dc..a0fa50678 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -2287,3 +2287,78 @@ func TestSideImportPrunedBlocks(t *testing.T) { t.Errorf("Got error, %v", err) } } + +// TestDeleteCreateRevert tests a weird state transition corner case that we hit +// while changing the internals of statedb. The workflow is that a contract is +// self destructed, then in a followup transaction (but same block) it's created +// again and the transaction reverted. +// +// The original statedb implementation flushed dirty objects to the tries after +// each transaction, so this works ok. The rework accumulated writes in memory +// first, but the journal wiped the entire state object on create-revert. +func TestDeleteCreateRevert(t *testing.T) { + var ( + aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") + bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") + // Generate a canonical chain to act as the main dataset + engine = ethash.NewFaker() + db = rawdb.NewMemoryDatabase() + + // A sender who makes transactions, has some funds + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + address = crypto.PubkeyToAddress(key.PublicKey) + funds = big.NewInt(1000000000) + gspec = &Genesis{ + Config: params.TestChainConfig, + Alloc: GenesisAlloc{ + address: {Balance: funds}, + // The address 0xAAAAA selfdestructs if called + aa: { + // Code needs to just selfdestruct + Code: []byte{byte(vm.PC), 0xFF}, + Nonce: 1, + Balance: big.NewInt(0), + }, + // The address 0xBBBB send 1 wei to 0xAAAA, then reverts + bb: { + Code: []byte{ + byte(vm.PC), // [0] + byte(vm.DUP1), // [0,0] + byte(vm.DUP1), // [0,0,0] + byte(vm.DUP1), // [0,0,0,0] + byte(vm.PUSH1), 0x01, // [0,0,0,0,1] (value) + byte(vm.PUSH2), 0xaa, 0xaa, // [0,0,0,0,1, 0xaaaa] + byte(vm.GAS), + byte(vm.CALL), + byte(vm.REVERT), + }, + Balance: big.NewInt(1), + }, + }, + } + genesis = gspec.MustCommit(db) + ) + + blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { + b.SetCoinbase(common.Address{1}) + // One transaction to AAAA + tx, _ := types.SignTx(types.NewTransaction(0, aa, + big.NewInt(0), 50000, big.NewInt(1), nil), types.HomesteadSigner{}, key) + b.AddTx(tx) + // One transaction to BBBB + tx, _ = types.SignTx(types.NewTransaction(1, bb, + big.NewInt(0), 100000, big.NewInt(1), nil), types.HomesteadSigner{}, key) + b.AddTx(tx) + }) + // Import the canonical chain + diskdb := rawdb.NewMemoryDatabase() + gspec.MustCommit(diskdb) + + chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) + if err != nil { + t.Fatalf("failed to create tester chain: %v", err) + } + if n, err := chain.InsertChain(blocks); err != nil { + t.Fatalf("block %d: failed to insert into chain: %v", n, err) + } +} |