aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2019-09-16 16:39:41 +0800
committerPéter Szilágyi <peterke@gmail.com>2019-09-16 16:42:14 +0800
commitf49d6e5ec09b740ae88c3a04edbe60b357b81991 (patch)
tree822ddb1a6ec1a3f495f897c1d86267f186d704e9
parent223b950944f494a5b4e0957fd9f92c48b09037ad (diff)
downloadgo-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.go75
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)
+ }
+}