github.com/m3shine/gochain@v2.2.26+incompatible/core/genesis_test.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/json"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"reflect"
    26  	"testing"
    27  
    28  	"github.com/davecgh/go-spew/spew"
    29  
    30  	"github.com/gochain-io/gochain/common"
    31  	"github.com/gochain-io/gochain/consensus/clique"
    32  	"github.com/gochain-io/gochain/core/rawdb"
    33  	"github.com/gochain-io/gochain/core/vm"
    34  	"github.com/gochain-io/gochain/ethdb"
    35  	"github.com/gochain-io/gochain/params"
    36  )
    37  
    38  func TestDefaultGenesisBlockHash(t *testing.T) {
    39  	for _, test := range []struct {
    40  		name     string
    41  		exp, got common.Hash
    42  	}{
    43  		{"mainnet", params.MainnetGenesisHash, DefaultGenesisBlock().ToBlock(nil).Hash()},
    44  		{"testnet", params.TestnetGenesisHash, DefaultTestnetGenesisBlock().ToBlock(nil).Hash()},
    45  	} {
    46  		if test.exp != test.got {
    47  			t.Errorf("wrong %s genesis hash, got %s, want %s", test.name, test.got.Hex(), test.exp.Hex())
    48  		}
    49  	}
    50  }
    51  
    52  func TestSetupGenesis(t *testing.T) {
    53  	ctx := context.Background()
    54  	var (
    55  		customghash = common.HexToHash("0x2ba5deb4ad470a1b170475fe5004f0e0cefffa8e18469e6510937e74db11094a")
    56  		customg     = Genesis{
    57  			Config: &params.ChainConfig{
    58  				HomesteadBlock: big.NewInt(3),
    59  				Clique:         params.DefaultCliqueConfig(),
    60  			},
    61  			Alloc: GenesisAlloc{
    62  				{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
    63  			},
    64  		}
    65  		oldcustomg = customg
    66  	)
    67  	oldcustomg.Config = &params.ChainConfig{
    68  		HomesteadBlock: big.NewInt(2),
    69  		Clique:         params.DefaultCliqueConfig(),
    70  	}
    71  	tests := []struct {
    72  		name       string
    73  		fn         func(common.Database) (*params.ChainConfig, common.Hash, error)
    74  		wantConfig *params.ChainConfig
    75  		wantHash   common.Hash
    76  		wantErr    error
    77  	}{
    78  		{
    79  			name: "genesis without ChainConfig",
    80  			fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) {
    81  				return SetupGenesisBlock(db, new(Genesis))
    82  			},
    83  			wantErr:    errGenesisNoConfig,
    84  			wantConfig: params.AllCliqueProtocolChanges,
    85  		},
    86  		{
    87  			name: "no block in DB, genesis == nil",
    88  			fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) {
    89  				return SetupGenesisBlock(db, nil)
    90  			},
    91  			wantHash:   params.MainnetGenesisHash,
    92  			wantConfig: params.MainnetChainConfig,
    93  		},
    94  		{
    95  			name: "mainnet block in DB, genesis == nil",
    96  			fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) {
    97  				DefaultGenesisBlock().MustCommit(db)
    98  				return SetupGenesisBlock(db, nil)
    99  			},
   100  			wantHash:   params.MainnetGenesisHash,
   101  			wantConfig: params.MainnetChainConfig,
   102  		},
   103  		{
   104  			name: "custom block in DB, genesis == nil",
   105  			fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) {
   106  				customg.MustCommit(db)
   107  				return SetupGenesisBlock(db, nil)
   108  			},
   109  			wantHash:   customghash,
   110  			wantConfig: customg.Config,
   111  		},
   112  		{
   113  			name: "custom block in DB, genesis == testnet",
   114  			fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) {
   115  				customg.MustCommit(db)
   116  				return SetupGenesisBlock(db, DefaultTestnetGenesisBlock())
   117  			},
   118  			wantErr:    &GenesisMismatchError{Stored: customghash, New: params.TestnetGenesisHash},
   119  			wantHash:   params.TestnetGenesisHash,
   120  			wantConfig: params.TestnetChainConfig,
   121  		},
   122  		{
   123  			name: "compatible config in DB",
   124  			fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) {
   125  				oldcustomg.MustCommit(db)
   126  				return SetupGenesisBlock(db, &customg)
   127  			},
   128  			wantHash:   customghash,
   129  			wantConfig: customg.Config,
   130  		},
   131  		{
   132  			name: "incompatible config in DB",
   133  			fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) {
   134  				// Commit the 'old' genesis block with Homestead transition at #2.
   135  				// Advance to block #4, past the homestead transition block of customg.
   136  				genesis := oldcustomg.MustCommit(db)
   137  
   138  				bc, _ := NewBlockChain(ctx, db, nil, oldcustomg.Config, clique.NewFullFaker(), vm.Config{})
   139  				defer bc.Stop()
   140  
   141  				blocks, _ := GenerateChain(ctx, oldcustomg.Config, genesis, clique.NewFaker(), db, 4, nil)
   142  				_, err := bc.InsertChain(ctx, blocks)
   143  				if err != nil {
   144  					return nil, common.Hash{}, err
   145  				}
   146  				bc.CurrentBlock()
   147  				// This should return a compatibility error.
   148  				return SetupGenesisBlock(db, &customg)
   149  			},
   150  			wantHash:   customghash,
   151  			wantConfig: customg.Config,
   152  			wantErr: &params.ConfigCompatError{
   153  				What:         "Homestead fork block",
   154  				StoredConfig: big.NewInt(2),
   155  				NewConfig:    big.NewInt(3),
   156  				RewindTo:     1,
   157  			},
   158  		},
   159  	}
   160  
   161  	for _, test := range tests {
   162  		db := ethdb.NewMemDatabase()
   163  		config, hash, err := test.fn(db)
   164  		// Check the return values.
   165  		if !reflect.DeepEqual(err, test.wantErr) {
   166  			spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
   167  			t.Fatalf("%s:\nhave: %#v\nwant: %#v\n", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
   168  		}
   169  		if !reflect.DeepEqual(config, test.wantConfig) {
   170  			t.Errorf("%s:\nhave: %v\nwant: %v\n", test.name, config, test.wantConfig)
   171  		}
   172  		if hash != test.wantHash {
   173  			t.Errorf("%s:\nhave: %s\nwant: %s\n", test.name, hash.Hex(), test.wantHash.Hex())
   174  		} else if err == nil {
   175  			// Check database content.
   176  			stored := rawdb.ReadBlock(db, test.wantHash, 0)
   177  			if stored.Hash() != test.wantHash {
   178  				t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash)
   179  			}
   180  		}
   181  	}
   182  }
   183  
   184  func TestDefaultGenesisBlock(t *testing.T) {
   185  	for _, test := range []struct {
   186  		name    string
   187  		file    string
   188  		genesis *Genesis
   189  	}{
   190  		{"mainnet", "genesis-main.json", DefaultGenesisBlock()},
   191  		{"testnet", "genesis-test.json", DefaultTestnetGenesisBlock()},
   192  	} {
   193  		exp, err := ioutil.ReadFile(test.file)
   194  		if err != nil {
   195  			t.Fatal(err)
   196  		}
   197  		exp = bytes.TrimSpace(exp)
   198  		got, err := json.MarshalIndent(test.genesis, "", "  ")
   199  		if err != nil {
   200  			t.Fatal(err)
   201  		}
   202  		if !bytes.Equal(exp, got) {
   203  			t.Errorf("mismatched %s genesis, expected:\n%s\ngot:\n%s", test.name, string(exp), string(got))
   204  		}
   205  	}
   206  }
   207  
   208  func TestGenesisAlloc_Total(t *testing.T) {
   209  	for _, test := range []struct {
   210  		name  string
   211  		exp   *big.Int
   212  		alloc GenesisAlloc
   213  	}{
   214  		{
   215  			name:  "mainnet",
   216  			exp:   new(big.Int).Mul(big.NewInt(params.Ether), big.NewInt(1000000000)),
   217  			alloc: DefaultGenesisBlock().Alloc,
   218  		},
   219  		{
   220  			name:  "testnet",
   221  			exp:   new(big.Int).Mul(big.NewInt(params.Ether), big.NewInt(1000000000)),
   222  			alloc: DefaultTestnetGenesisBlock().Alloc,
   223  		},
   224  		{
   225  			name: "custom",
   226  			exp:  big.NewInt(100),
   227  			alloc: GenesisAlloc{
   228  				common.StringToAddress("a"): {Balance: big.NewInt(1)},
   229  				common.StringToAddress("b"): {Balance: big.NewInt(10)},
   230  				common.StringToAddress("c"): {Balance: big.NewInt(19)},
   231  				common.StringToAddress("d"): {Balance: big.NewInt(30)},
   232  				common.StringToAddress("e"): {Balance: big.NewInt(40)},
   233  			},
   234  		},
   235  	} {
   236  		if got := test.alloc.Total(); got.Cmp(test.exp) != 0 {
   237  			t.Errorf("%s: expected %s but got %s", test.name, test.exp, got)
   238  		}
   239  	}
   240  }