github.com/theQRL/go-zond@v0.1.1/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  	"encoding/json"
    21  	"math/big"
    22  	"reflect"
    23  	"testing"
    24  
    25  	"github.com/davecgh/go-spew/spew"
    26  	"github.com/theQRL/go-zond/common"
    27  	"github.com/theQRL/go-zond/consensus/ethash"
    28  	"github.com/theQRL/go-zond/core/rawdb"
    29  	"github.com/theQRL/go-zond/core/vm"
    30  	"github.com/theQRL/go-zond/params"
    31  	"github.com/theQRL/go-zond/trie"
    32  	"github.com/theQRL/go-zond/trie/triedb/pathdb"
    33  	"github.com/theQRL/go-zond/zonddb"
    34  )
    35  
    36  func TestInvalidCliqueConfig(t *testing.T) {
    37  	block := DefaultGoerliGenesisBlock()
    38  	block.ExtraData = []byte{}
    39  	db := rawdb.NewMemoryDatabase()
    40  	if _, err := block.Commit(db, trie.NewDatabase(db, nil)); err == nil {
    41  		t.Fatal("Expected error on invalid clique config")
    42  	}
    43  }
    44  
    45  func TestSetupGenesis(t *testing.T) {
    46  	testSetupGenesis(t, rawdb.HashScheme)
    47  	testSetupGenesis(t, rawdb.PathScheme)
    48  }
    49  
    50  func testSetupGenesis(t *testing.T, scheme string) {
    51  	var (
    52  		customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50")
    53  		customg     = Genesis{
    54  			Config: &params.ChainConfig{HomesteadBlock: big.NewInt(3)},
    55  			Alloc: GenesisAlloc{
    56  				{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
    57  			},
    58  		}
    59  		oldcustomg = customg
    60  	)
    61  	oldcustomg.Config = &params.ChainConfig{HomesteadBlock: big.NewInt(2)}
    62  
    63  	tests := []struct {
    64  		name       string
    65  		fn         func(zonddb.Database) (*params.ChainConfig, common.Hash, error)
    66  		wantConfig *params.ChainConfig
    67  		wantHash   common.Hash
    68  		wantErr    error
    69  	}{
    70  		{
    71  			name: "genesis without ChainConfig",
    72  			fn: func(db zonddb.Database) (*params.ChainConfig, common.Hash, error) {
    73  				return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), new(Genesis))
    74  			},
    75  			wantErr:    errGenesisNoConfig,
    76  			wantConfig: params.AllEthashProtocolChanges,
    77  		},
    78  		{
    79  			name: "no block in DB, genesis == nil",
    80  			fn: func(db zonddb.Database) (*params.ChainConfig, common.Hash, error) {
    81  				return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil)
    82  			},
    83  			wantHash:   params.MainnetGenesisHash,
    84  			wantConfig: params.MainnetChainConfig,
    85  		},
    86  		{
    87  			name: "mainnet block in DB, genesis == nil",
    88  			fn: func(db zonddb.Database) (*params.ChainConfig, common.Hash, error) {
    89  				DefaultGenesisBlock().MustCommit(db, trie.NewDatabase(db, newDbConfig(scheme)))
    90  				return SetupGenesisBlock(db, trie.NewDatabase(db, newDbConfig(scheme)), nil)
    91  			},
    92  			wantHash:   params.MainnetGenesisHash,
    93  			wantConfig: params.MainnetChainConfig,
    94  		},
    95  		{
    96  			name: "custom block in DB, genesis == nil",
    97  			fn: func(db zonddb.Database) (*params.ChainConfig, common.Hash, error) {
    98  				tdb := trie.NewDatabase(db, newDbConfig(scheme))
    99  				customg.Commit(db, tdb)
   100  				return SetupGenesisBlock(db, tdb, nil)
   101  			},
   102  			wantHash:   customghash,
   103  			wantConfig: customg.Config,
   104  		},
   105  		{
   106  			name: "custom block in DB, genesis == goerli",
   107  			fn: func(db zonddb.Database) (*params.ChainConfig, common.Hash, error) {
   108  				tdb := trie.NewDatabase(db, newDbConfig(scheme))
   109  				customg.Commit(db, tdb)
   110  				return SetupGenesisBlock(db, tdb, DefaultGoerliGenesisBlock())
   111  			},
   112  			wantErr:    &GenesisMismatchError{Stored: customghash, New: params.GoerliGenesisHash},
   113  			wantHash:   params.GoerliGenesisHash,
   114  			wantConfig: params.GoerliChainConfig,
   115  		},
   116  		{
   117  			name: "compatible config in DB",
   118  			fn: func(db zonddb.Database) (*params.ChainConfig, common.Hash, error) {
   119  				tdb := trie.NewDatabase(db, newDbConfig(scheme))
   120  				oldcustomg.Commit(db, tdb)
   121  				return SetupGenesisBlock(db, tdb, &customg)
   122  			},
   123  			wantHash:   customghash,
   124  			wantConfig: customg.Config,
   125  		},
   126  		{
   127  			name: "incompatible config in DB",
   128  			fn: func(db zonddb.Database) (*params.ChainConfig, common.Hash, error) {
   129  				// Commit the 'old' genesis block with Homestead transition at #2.
   130  				// Advance to block #4, past the homestead transition block of customg.
   131  				tdb := trie.NewDatabase(db, newDbConfig(scheme))
   132  				oldcustomg.Commit(db, tdb)
   133  
   134  				bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil)
   135  				defer bc.Stop()
   136  
   137  				_, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil)
   138  				bc.InsertChain(blocks)
   139  
   140  				// This should return a compatibility error.
   141  				return SetupGenesisBlock(db, tdb, &customg)
   142  			},
   143  			wantHash:   customghash,
   144  			wantConfig: customg.Config,
   145  			wantErr: &params.ConfigCompatError{
   146  				What:          "Homestead fork block",
   147  				StoredBlock:   big.NewInt(2),
   148  				NewBlock:      big.NewInt(3),
   149  				RewindToBlock: 1,
   150  			},
   151  		},
   152  	}
   153  
   154  	for _, test := range tests {
   155  		db := rawdb.NewMemoryDatabase()
   156  		config, hash, err := test.fn(db)
   157  		// Check the return values.
   158  		if !reflect.DeepEqual(err, test.wantErr) {
   159  			spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
   160  			t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
   161  		}
   162  		if !reflect.DeepEqual(config, test.wantConfig) {
   163  			t.Errorf("%s:\nreturned %v\nwant     %v", test.name, config, test.wantConfig)
   164  		}
   165  		if hash != test.wantHash {
   166  			t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex())
   167  		} else if err == nil {
   168  			// Check database content.
   169  			stored := rawdb.ReadBlock(db, test.wantHash, 0)
   170  			if stored.Hash() != test.wantHash {
   171  				t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash)
   172  			}
   173  		}
   174  	}
   175  }
   176  
   177  // TestGenesisHashes checks the congruity of default genesis data to
   178  // corresponding hardcoded genesis hash values.
   179  func TestGenesisHashes(t *testing.T) {
   180  	for i, c := range []struct {
   181  		genesis *Genesis
   182  		want    common.Hash
   183  	}{
   184  		{DefaultGenesisBlock(), params.MainnetGenesisHash},
   185  		{DefaultGoerliGenesisBlock(), params.GoerliGenesisHash},
   186  		{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
   187  		{DefaultBetaNetGenesisBlock(), params.BetaNetGenesisHash},
   188  	} {
   189  		// Test via MustCommit
   190  		db := rawdb.NewMemoryDatabase()
   191  		if have := c.genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults)).Hash(); have != c.want {
   192  			t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
   193  		}
   194  		// Test via ToBlock
   195  		if have := c.genesis.ToBlock().Hash(); have != c.want {
   196  			t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
   197  		}
   198  	}
   199  }
   200  
   201  func TestGenesis_Commit(t *testing.T) {
   202  	genesis := &Genesis{
   203  		BaseFee: big.NewInt(params.InitialBaseFee),
   204  		Config:  params.TestChainConfig,
   205  		// difficulty is nil
   206  	}
   207  
   208  	db := rawdb.NewMemoryDatabase()
   209  	genesisBlock := genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
   210  
   211  	if genesis.Difficulty != nil {
   212  		t.Fatalf("assumption wrong")
   213  	}
   214  
   215  	// This value should have been set as default in the ToBlock method.
   216  	if genesisBlock.Difficulty().Cmp(params.GenesisDifficulty) != 0 {
   217  		t.Errorf("assumption wrong: want: %d, got: %v", params.GenesisDifficulty, genesisBlock.Difficulty())
   218  	}
   219  
   220  	// Expect the stored total difficulty to be the difficulty of the genesis block.
   221  	stored := rawdb.ReadTd(db, genesisBlock.Hash(), genesisBlock.NumberU64())
   222  
   223  	if stored.Cmp(genesisBlock.Difficulty()) != 0 {
   224  		t.Errorf("inequal difficulty; stored: %v, genesisBlock: %v", stored, genesisBlock.Difficulty())
   225  	}
   226  }
   227  
   228  func TestReadWriteGenesisAlloc(t *testing.T) {
   229  	var (
   230  		db    = rawdb.NewMemoryDatabase()
   231  		alloc = &GenesisAlloc{
   232  			{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
   233  			{2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
   234  		}
   235  		hash, _ = alloc.deriveHash()
   236  	)
   237  	blob, _ := json.Marshal(alloc)
   238  	rawdb.WriteGenesisStateSpec(db, hash, blob)
   239  
   240  	var reload GenesisAlloc
   241  	err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash))
   242  	if err != nil {
   243  		t.Fatalf("Failed to load genesis state %v", err)
   244  	}
   245  	if len(reload) != len(*alloc) {
   246  		t.Fatal("Unexpected genesis allocation")
   247  	}
   248  	for addr, account := range reload {
   249  		want, ok := (*alloc)[addr]
   250  		if !ok {
   251  			t.Fatal("Account is not found")
   252  		}
   253  		if !reflect.DeepEqual(want, account) {
   254  			t.Fatal("Unexpected account")
   255  		}
   256  	}
   257  }
   258  
   259  func newDbConfig(scheme string) *trie.Config {
   260  	if scheme == rawdb.HashScheme {
   261  		return trie.HashDefaults
   262  	}
   263  	return &trie.Config{PathDB: pathdb.Defaults}
   264  }