// Copyright 2017 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 core import ( "math/big" "reflect" "testing" "github.com/davecgh/go-spew/spew" "github.com/pavelkrolevets/go-ethereum/common" "github.com/pavelkrolevets/go-ethereum/consensus/ethash" "github.com/pavelkrolevets/go-ethereum/core/vm" "github.com/pavelkrolevets/go-ethereum/ethdb" "github.com/pavelkrolevets/go-ethereum/params" "github.com/pavelkrolevets/go-ethereum/core/types" "github.com/pavelkrolevets/go-ethereum/core/state" ) type bproc struct{} func (bproc) ValidateBody(*types.Block) error { return nil } func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error { return nil } func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) { return nil, nil, new(big.Int), nil } func (bproc) ValidateDposState(block *types.Block) error { return nil } func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block { var chain []*types.Block for i, difficulty := range d { header := &types.Header{ Coinbase: common.Address{seed}, Number: big.NewInt(int64(i + 1)), Difficulty: big.NewInt(int64(difficulty)), UncleHash: types.EmptyUncleHash, TxHash: types.EmptyRootHash, ReceiptHash: types.EmptyRootHash, Time: big.NewInt(int64(i) + 1), } if i == 0 { header.ParentHash = genesis.Hash() } else { header.ParentHash = chain[i-1].Hash() } block := types.NewBlockWithHeader(header) chain = append(chain, block) } return chain } func TestSetupGenesis(t *testing.T) { var ( customghash = common.HexToHash("0xa4813c30e66d854572733941743e6736f20c0487d32c6b2fe1233946b036f6f5") customg = Genesis{ Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)}, Alloc: GenesisAlloc{ {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, }, } oldcustomg = customg ) oldcustomg.Config = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(2)} tests := []struct { name string fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error) wantConfig *params.ChainConfig wantHash common.Hash wantErr error }{ { name: "custom block in DB, genesis == nil", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { customg.MustCommit(db) return SetupGenesisBlock(db, nil) }, wantHash: customghash, wantConfig: customg.Config, }, { name: "compatible config in DB", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { oldcustomg.MustCommit(db) return SetupGenesisBlock(db, &customg) }, wantHash: customghash, wantConfig: customg.Config, }, { name: "incompatible config in DB", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { // Commit the 'old' genesis block with Homestead transition at #2. // Advance to block #4, past the homestead transition block of customg. genesis := oldcustomg.MustCommit(db) bc, _ := NewBlockChain(db,nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}) defer bc.Stop() bc.SetValidator(bproc{}) bc.InsertChain(makeBlockChainWithDiff(genesis, []int{2, 3, 4, 5}, 0)) bc.CurrentBlock() // This should return a compatibility error. return SetupGenesisBlock(db, &customg) }, wantHash: customghash, wantConfig: customg.Config, wantErr: ¶ms.ConfigCompatError{ What: "Homestead fork block", StoredConfig: big.NewInt(2), NewConfig: big.NewInt(3), RewindTo: 1, }, }, } for _, test := range tests { db:= ethdb.NewMemDatabase() config, hash, err := test.fn(db) // Check the return values. if !reflect.DeepEqual(err, test.wantErr) { spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true} t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr)) } if !reflect.DeepEqual(config, test.wantConfig) { t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig) } if hash != test.wantHash { t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex()) } else if err == nil { // Check database content. stored := GetBlock(db, test.wantHash, 0) if stored.Hash() != test.wantHash { t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash) } } } }