diff --git a/core/bench_test.go b/core/bench_test.go index c6029499a8..3f97888d33 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -162,7 +162,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { // Generate a chain of b.N blocks using the supplied block // generator function. - genesis := WriteGenesisBlockForTesting(db, GenesisAccount{benchRootAddr, benchRootFunds}) + genesis := WriteGenesisBlockForTesting(db, GenesisAccount{Address: benchRootAddr, Balance: benchRootFunds}) chain, _ := GenerateChain(genesis, db, b.N, gen) // Time the insertion of the new chain. diff --git a/core/blockchain_test.go b/core/blockchain_test.go index a26fe4a1b9..8e639a36a4 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -732,7 +732,7 @@ func TestFastVsFullChains(t *testing.T) { }) // Import the chain as an archive node for the comparison baseline archiveDb, _ := ethdb.NewMemDatabase() - WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds}) + WriteGenesisBlockForTesting(archiveDb, GenesisAccount{Address: address, Balance: funds}) archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux)) @@ -741,7 +741,7 @@ func TestFastVsFullChains(t *testing.T) { } // Fast import the chain as a non-archive node to test fastDb, _ := ethdb.NewMemDatabase() - WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds}) + WriteGenesisBlockForTesting(fastDb, GenesisAccount{Address: address, Balance: funds}) fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux)) headers := make([]*types.Header, len(blocks)) @@ -816,7 +816,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { } // Import the chain as an archive node and ensure all pointers are updated archiveDb, _ := ethdb.NewMemDatabase() - WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds}) + WriteGenesisBlockForTesting(archiveDb, GenesisAccount{Address: address, Balance: funds}) archive, _ := NewBlockChain(archiveDb, testChainConfig(), FakePow{}, new(event.TypeMux)) @@ -829,7 +829,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { // Import the chain as a non-archive node and ensure all pointers are updated fastDb, _ := ethdb.NewMemDatabase() - WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds}) + WriteGenesisBlockForTesting(fastDb, GenesisAccount{Address: address, Balance: funds}) fast, _ := NewBlockChain(fastDb, testChainConfig(), FakePow{}, new(event.TypeMux)) headers := make([]*types.Header, len(blocks)) @@ -848,7 +848,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { // Import the chain as a light node and ensure all pointers are updated lightDb, _ := ethdb.NewMemDatabase() - WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds}) + WriteGenesisBlockForTesting(lightDb, GenesisAccount{Address: address, Balance: funds}) light, _ := NewBlockChain(lightDb, testChainConfig(), FakePow{}, new(event.TypeMux)) if n, err := light.InsertHeaderChain(headers, 1); err != nil { @@ -874,9 +874,9 @@ func TestChainTxReorgs(t *testing.T) { db, _ = ethdb.NewMemDatabase() ) genesis := WriteGenesisBlockForTesting(db, - GenesisAccount{addr1, big.NewInt(1000000)}, - GenesisAccount{addr2, big.NewInt(1000000)}, - GenesisAccount{addr3, big.NewInt(1000000)}, + GenesisAccount{Address: addr1, Balance: big.NewInt(1000000)}, + GenesisAccount{Address: addr2, Balance: big.NewInt(1000000)}, + GenesisAccount{Address: addr3, Balance: big.NewInt(1000000)}, ) // Create two transactions shared between the chains: // - postponed: transaction included at a later block in the forked chain @@ -983,7 +983,7 @@ func TestLogReorgs(t *testing.T) { code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") ) genesis := WriteGenesisBlockForTesting(db, - GenesisAccount{addr1, big.NewInt(10000000000000)}, + GenesisAccount{Address: addr1, Balance: big.NewInt(10000000000000)}, ) evmux := &event.TypeMux{} @@ -1019,7 +1019,7 @@ func TestReorgSideEvent(t *testing.T) { db, _ = ethdb.NewMemDatabase() key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr1 = crypto.PubkeyToAddress(key1.PublicKey) - genesis = WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(10000000000000)}) + genesis = WriteGenesisBlockForTesting(db, GenesisAccount{Address: addr1, Balance: big.NewInt(10000000000000)}) ) evmux := &event.TypeMux{} diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index 32c3efe8da..5074a60d92 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -42,7 +42,7 @@ func ExampleGenerateChain() { ) // Ensure that key1 has some funds in the genesis block. - genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(1000000)}) + genesis := WriteGenesisBlockForTesting(db, GenesisAccount{Address: addr1, Balance: big.NewInt(1000000)}) // This call generates a chain of 5 blocks. The function runs for // each block and adds different features to gen based on the diff --git a/core/database_util_test.go b/core/database_util_test.go index 6c19f78c84..6ce34eded7 100644 --- a/core/database_util_test.go +++ b/core/database_util_test.go @@ -560,7 +560,7 @@ func TestMipmapChain(t *testing.T) { ) defer db.Close() - genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr, big.NewInt(1000000)}) + genesis := WriteGenesisBlockForTesting(db, GenesisAccount{Address: addr, Balance: big.NewInt(1000000)}) chain, receipts := GenerateChain(genesis, db, 1010, func(i int, gen *BlockGen) { var receipts types.Receipts switch i { diff --git a/core/genesis.go b/core/genesis.go index 637b633206..0d4efc80cf 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -143,6 +143,8 @@ func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big type GenesisAccount struct { Address common.Address Balance *big.Int + Code []byte // runtime code + Storage map[common.Hash]common.Hash } func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount) *types.Block { @@ -151,7 +153,21 @@ func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount) if i != 0 { accountJson += "," } - accountJson += fmt.Sprintf(`"0x%x":{"balance":"0x%x"}`, account.Address, account.Balance.Bytes()) + if len(account.Storage) == 0 { + accountJson += fmt.Sprintf(`"0x%x":{"balance":"0x%x","code":"%x"}`, account.Address, account.Balance.Bytes(), account.Code) + } else { + accountJson += fmt.Sprintf(`"0x%x":{"balance":"0x%x","code":"%x", "storage": {`, account.Address, account.Balance.Bytes(), account.Code) + prefixComma := false + for key, value := range account.Storage { + if prefixComma { + accountJson += fmt.Sprintf(`,"%x": "%x"`, key, value) + } else { + accountJson += fmt.Sprintf(`"%x": "%x"`, key, value) + } + prefixComma = true + } + accountJson += "}}" + } } accountJson += "}" diff --git a/core/genesis_test.go b/core/genesis_test.go new file mode 100644 index 0000000000..53a6bbce91 --- /dev/null +++ b/core/genesis_test.go @@ -0,0 +1,90 @@ +package core + +import ( + "bytes" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/ethdb" +) + +// Test if genesis block is deployed with correct state. +func TestWriteGenesisBlockForTesting(t *testing.T) { + type Expected struct { + code []byte + balance *big.Int + storage map[common.Hash]common.Hash + } + + stor := map[common.Hash]common.Hash{ + common.HexToHash("0x00"): common.HexToHash("0x01"), + common.HexToHash("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"): common.HexToHash("abcdef"), + } + + tests := []struct { + account GenesisAccount + expected Expected + }{ + { + account: GenesisAccount{ + Address: common.HexToAddress("0x0000000000000000000000000000000000000001"), + Balance: big.NewInt(11111), + }, + expected: Expected{ + balance: big.NewInt(11111), + }, + }, + { + account: GenesisAccount{ + Address: common.HexToAddress("0x0000000000000000000000000000000000000002"), + Balance: big.NewInt(22222), + Code: common.FromHex("60606040526008565b00"), // contract Storage { uint a; mapping(address => uint) map; } + Storage: stor, + }, + expected: Expected{ + code: common.FromHex("60606040526008565b00"), + balance: big.NewInt(22222), + storage: stor, + }, + }, + } + + db, err := ethdb.NewMemDatabase() + if err != nil { + t.Fatal(err) + } + + var accounts []GenesisAccount + for _, test := range tests { + accounts = append(accounts, test.account) + } + block := WriteGenesisBlockForTesting(db, accounts...) + + s, err := state.New(block.Root(), db) + if err != nil { + t.Fatal(err) + } + + for i, test := range tests { + if test.expected.balance != nil { + balance := s.GetBalance(test.account.Address) + if test.expected.balance.Cmp(balance) != 0 { + t.Errorf("invalid balance for test %d: want %d, got %d", i, test.expected.balance, balance) + } + } + if len(test.expected.code) > 0 { + code := s.GetCode(test.account.Address) + if !bytes.Equal(test.expected.code, code) { + t.Errorf("invalid code stored for test %d: want %x, got %x", i, test.expected.code, code) + } + } + for k, v := range test.expected.storage { + val := s.GetState(test.account.Address, k) + if v != val { + t.Errorf("invalid storage for test %d: want %x, got %x", i, v, val) + } + } + } +}