diff --git a/statediff/builder_test.go b/statediff/builder_test.go index 39361e2ab..efc7300d5 100644 --- a/statediff/builder_test.go +++ b/statediff/builder_test.go @@ -34,14 +34,12 @@ import ( // TODO: add test that filters on address var ( contractLeafKey []byte - emptyAccountDiffEventualMap = make([]statediff.AccountDiff, 0) - emptyAccountDiffIncrementalMap = make([]statediff.AccountDiff, 0) + emptyAccountMap = make([]statediff.AccountDiff, 0) block0, block1, block2, block3 *types.Block builder statediff.Builder miningReward = int64(2000000000000000000) minerAddress = common.HexToAddress("0x0") minerLeafKey = testhelpers.AddressToLeafKey(minerAddress) - nullHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") balanceChange10000 = int64(10000) balanceChange1000 = int64(1000) @@ -279,7 +277,7 @@ type arguments struct { blockHash common.Hash } -func TestBuilder1(t *testing.T) { +func TestBuilder(t *testing.T) { blockHashes, blockMap, chain := testhelpers.MakeChain(3, testhelpers.Genesis) contractLeafKey = testhelpers.AddressToLeafKey(testhelpers.ContractAddr) defer chain.Stop() @@ -308,16 +306,16 @@ func TestBuilder1(t *testing.T) { &statediff.StateDiff{ BlockNumber: block0.Number(), BlockHash: block0.Hash(), - CreatedAccounts: emptyAccountDiffEventualMap, - DeletedAccounts: emptyAccountDiffEventualMap, - UpdatedAccounts: emptyAccountDiffIncrementalMap, + CreatedAccounts: emptyAccountMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, }, }, { "testBlock0", //10000 transferred from testBankAddress to account1Addr arguments{ - oldStateRoot: nullHash, + oldStateRoot: testhelpers.NullHash, newStateRoot: block0.Root(), blockNumber: block0.Number(), blockHash: block0.Hash(), @@ -334,8 +332,8 @@ func TestBuilder1(t *testing.T) { Storage: []statediff.StorageDiff{}, }, }, - DeletedAccounts: emptyAccountDiffEventualMap, - UpdatedAccounts: emptyAccountDiffIncrementalMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, }, }, { @@ -366,7 +364,7 @@ func TestBuilder1(t *testing.T) { Storage: []statediff.StorageDiff{}, }, }, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{ { Path: []byte{'\x00'}, @@ -415,7 +413,7 @@ func TestBuilder1(t *testing.T) { Storage: []statediff.StorageDiff{}, }, }, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{ { Path: []byte{'\x00'}, @@ -455,7 +453,7 @@ func TestBuilder1(t *testing.T) { BlockNumber: block3.Number(), BlockHash: block3.Hash(), CreatedAccounts: []statediff.AccountDiff{}, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{ { Path: []byte{'\x00'}, @@ -497,9 +495,6 @@ func TestBuilder1(t *testing.T) { } for _, test := range tests { - if test.name != "testBlock0" { - continue - } arguments := test.startingArguments diff, err := builder.BuildStateDiff(arguments.oldStateRoot, arguments.newStateRoot, arguments.blockNumber, arguments.blockHash) if err != nil { @@ -551,16 +546,16 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { &statediff.StateDiff{ BlockNumber: block0.Number(), BlockHash: block0.Hash(), - CreatedAccounts: emptyAccountDiffEventualMap, - DeletedAccounts: emptyAccountDiffEventualMap, - UpdatedAccounts: emptyAccountDiffIncrementalMap, + CreatedAccounts: emptyAccountMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, }, }, { "testBlock0", //10000 transferred from testBankAddress to account1Addr arguments{ - oldStateRoot: nullHash, + oldStateRoot: testhelpers.NullHash, newStateRoot: block0.Root(), blockNumber: block0.Number(), blockHash: block0.Hash(), @@ -577,8 +572,8 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { Storage: []statediff.StorageDiff{}, }, }, - DeletedAccounts: emptyAccountDiffEventualMap, - UpdatedAccounts: emptyAccountDiffIncrementalMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, }, }, { @@ -615,7 +610,7 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { Storage: []statediff.StorageDiff{}, }, }, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{ { Path: []byte{'\x00'}, @@ -664,7 +659,7 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { Storage: []statediff.StorageDiff{}, }, }, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{ { Path: []byte{}, @@ -710,7 +705,7 @@ func TestBuilderWithIntermediateNodes(t *testing.T) { BlockNumber: block3.Number(), BlockHash: block3.Hash(), CreatedAccounts: []statediff.AccountDiff{}, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{ { Path: []byte{}, @@ -815,16 +810,16 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { &statediff.StateDiff{ BlockNumber: block0.Number(), BlockHash: block0.Hash(), - CreatedAccounts: emptyAccountDiffEventualMap, - DeletedAccounts: emptyAccountDiffEventualMap, - UpdatedAccounts: emptyAccountDiffIncrementalMap, + CreatedAccounts: emptyAccountMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, }, }, { "testBlock0", //10000 transferred from testBankAddress to account1Addr arguments{ - oldStateRoot: nullHash, + oldStateRoot: testhelpers.NullHash, newStateRoot: block0.Root(), blockNumber: block0.Number(), blockHash: block0.Hash(), @@ -832,9 +827,9 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { &statediff.StateDiff{ BlockNumber: block0.Number(), BlockHash: block0.Hash(), - CreatedAccounts: emptyAccountDiffEventualMap, - DeletedAccounts: emptyAccountDiffEventualMap, - UpdatedAccounts: emptyAccountDiffIncrementalMap, + CreatedAccounts: emptyAccountMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, }, }, { @@ -858,7 +853,7 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { Storage: []statediff.StorageDiff{}, }, }, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{}, }, }, @@ -891,7 +886,7 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { }, }, }, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{ { Path: []byte{'\x0e'}, @@ -917,7 +912,7 @@ func TestBuilderWithWatchedAddressList(t *testing.T) { BlockNumber: block3.Number(), BlockHash: block3.Hash(), CreatedAccounts: []statediff.AccountDiff{}, - DeletedAccounts: emptyAccountDiffEventualMap, + DeletedAccounts: emptyAccountMap, UpdatedAccounts: []statediff.AccountDiff{ { Path: []byte{'\x06'}, diff --git a/statediff/test_data/builder_test.go b/statediff/test_data/builder_test.go new file mode 100644 index 000000000..0d664c6e4 --- /dev/null +++ b/statediff/test_data/builder_test.go @@ -0,0 +1,203 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package statediff_test + +import ( + "bytes" + "io/ioutil" + "math/big" + "os" + "sort" + "testing" + + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/statediff" + "github.com/ethereum/go-ethereum/statediff/testhelpers" +) + +var ( + builder statediff.Builder + emptyAccountMap = make([]statediff.AccountDiff, 0) +) + +type arguments struct { + oldStateRoot common.Hash + newStateRoot common.Hash + blockNumber *big.Int + blockHash common.Hash +} + +func loadBlockFromRLPFile(filename string) (*types.Block, []byte, error) { + f, err := os.Open(filename) + if err != nil { + return nil, nil, err + } + defer f.Close() + blockRLP, err := ioutil.ReadAll(f) + if err != nil { + return nil, nil, err + } + block := new(types.Block) + return block, blockRLP, rlp.DecodeBytes(blockRLP, block) +} + +func TestBuilderOnMainnetBlocks(t *testing.T) { + db := rawdb.NewMemoryDatabase() + gen := core.DefaultGenesisBlock().MustCommit(db) + genBy, err := rlp.EncodeToBytes(gen) + if err != nil { + t.Error(err) + } + block0, block0RLP, err := loadBlockFromRLPFile("./block0_rlp") + if err != nil { + t.Error(err) + } + if !bytes.Equal(genBy, block0RLP) { + t.Error("mainnet genesis blocks do not match") + } + + block1, _, err := loadBlockFromRLPFile("./block1_rlp") + if err != nil { + t.Error(err) + } + block2, _, err := loadBlockFromRLPFile("./block2_rlp") + if err != nil { + t.Error(err) + } + block3, _, err := loadBlockFromRLPFile("./block3_rlp") + if err != nil { + t.Error(err) + } + + chain, _ := core.NewBlockChain(db, nil, params.MainnetChainConfig, ethash.NewFaker(), vm.Config{}, nil) + _, err = chain.InsertChain([]*types.Block{block1, block2, block3}) + if err != nil { + t.Error(err) + } + config := statediff.Config{ + IntermediateNodes: true, + } + builder = statediff.NewBuilder(chain, config) + + var tests = []struct { + name string + startingArguments arguments + expected *statediff.StateDiff + }{ + { + "testBlock0", + //10000 transferred from testBankAddress to account1Addr + arguments{ + oldStateRoot: testhelpers.NullHash, + newStateRoot: block0.Root(), + blockNumber: block0.Number(), + blockHash: block0.Hash(), + }, + &statediff.StateDiff{ + BlockNumber: block0.Number(), + BlockHash: block0.Hash(), + CreatedAccounts: emptyAccountMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, + }, + }, + { + "testBlock1", + //10000 transferred from testBankAddress to account1Addr + arguments{ + oldStateRoot: block0.Root(), + newStateRoot: block1.Root(), + blockNumber: block1.Number(), + blockHash: block1.Hash(), + }, + &statediff.StateDiff{ + BlockNumber: block1.Number(), + BlockHash: block1.Hash(), + CreatedAccounts: emptyAccountMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, + }, + }, + { + "testBlock2", + // 1000 transferred from testBankAddress to account1Addr + // 1000 transferred from account1Addr to account2Addr + // account1addr creates a new contract + arguments{ + oldStateRoot: block1.Root(), + newStateRoot: block2.Root(), + blockNumber: block2.Number(), + blockHash: block2.Hash(), + }, + &statediff.StateDiff{ + BlockNumber: block2.Number(), + BlockHash: block2.Hash(), + CreatedAccounts: emptyAccountMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, + }, + }, + { + "testBlock3", + //the contract's storage is changed + //and the block is mined by account 2 + arguments{ + oldStateRoot: block2.Root(), + newStateRoot: block3.Root(), + blockNumber: block3.Number(), + blockHash: block3.Hash(), + }, + &statediff.StateDiff{ + BlockNumber: block3.Number(), + BlockHash: block3.Hash(), + CreatedAccounts: emptyAccountMap, + DeletedAccounts: emptyAccountMap, + UpdatedAccounts: emptyAccountMap, + }, + }, + } + + for _, test := range tests { + arguments := test.startingArguments + diff, err := builder.BuildStateDiff(arguments.oldStateRoot, arguments.newStateRoot, arguments.blockNumber, arguments.blockHash) + if err != nil { + t.Error(err) + } + receivedStateDiffRlp, err := rlp.EncodeToBytes(diff) + if err != nil { + t.Error(err) + } + expectedStateDiffRlp, err := rlp.EncodeToBytes(test.expected) + if err != nil { + t.Error(err) + } + sort.Slice(receivedStateDiffRlp, func(i, j int) bool { return receivedStateDiffRlp[i] < receivedStateDiffRlp[j] }) + sort.Slice(expectedStateDiffRlp, func(i, j int) bool { return expectedStateDiffRlp[i] < expectedStateDiffRlp[j] }) + if !bytes.Equal(receivedStateDiffRlp, expectedStateDiffRlp) { + t.Logf("Test failed: %s", test.name) + t.Errorf("actual state diff: %+v\nexpected state diff: %+v", diff, test.expected) + } + } +} diff --git a/statediff/testhelpers/test_data.go b/statediff/testhelpers/test_data.go index c095928e2..800dd7855 100644 --- a/statediff/testhelpers/test_data.go +++ b/statediff/testhelpers/test_data.go @@ -47,6 +47,7 @@ var ( StoragePath = common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").Bytes() StorageKey = common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001").Bytes() StorageValue = common.Hex2Bytes("0x03") + NullHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") Testdb = rawdb.NewMemoryDatabase() TestBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")