github.com/tacshi/go-ethereum@v0.0.0-20230616113857-84a434e20921/cmd/geth/genesis_test.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU 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  // go-ethereum 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 General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"path/filepath"
    23  	"strconv"
    24  	"testing"
    25  )
    26  
    27  var customGenesisTests = []struct {
    28  	genesis string
    29  	query   string
    30  	result  string
    31  }{
    32  	// Genesis file with an empty chain configuration (ensure missing fields work)
    33  	{
    34  		genesis: `{
    35  			"alloc"      : {},
    36  			"coinbase"   : "0x0000000000000000000000000000000000000000",
    37  			"difficulty" : "0x20000",
    38  			"extraData"  : "",
    39  			"gasLimit"   : "0x2fefd8",
    40  			"nonce"      : "0x0000000000001338",
    41  			"mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
    42  			"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
    43  			"timestamp"  : "0x00",
    44  			"config"     : {}
    45  		}`,
    46  		query:  "eth.getBlock(0).nonce",
    47  		result: "0x0000000000001338",
    48  	},
    49  	// Genesis file with specific chain configurations
    50  	{
    51  		genesis: `{
    52  			"alloc"      : {},
    53  			"coinbase"   : "0x0000000000000000000000000000000000000000",
    54  			"difficulty" : "0x20000",
    55  			"extraData"  : "",
    56  			"gasLimit"   : "0x2fefd8",
    57  			"nonce"      : "0x0000000000001339",
    58  			"mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
    59  			"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
    60  			"timestamp"  : "0x00",
    61  			"config"     : {
    62  				"homesteadBlock" : 42,
    63  				"daoForkBlock"   : 141,
    64  				"daoForkSupport" : true
    65  			}
    66  		}`,
    67  		query:  "eth.getBlock(0).nonce",
    68  		result: "0x0000000000001339",
    69  	},
    70  }
    71  
    72  // Tests that initializing Geth with a custom genesis block and chain definitions
    73  // work properly.
    74  func TestCustomGenesis(t *testing.T) {
    75  	t.Parallel()
    76  	for i, tt := range customGenesisTests {
    77  		// Create a temporary data directory to use and inspect later
    78  		datadir := t.TempDir()
    79  
    80  		// Initialize the data directory with the custom genesis block
    81  		json := filepath.Join(datadir, "genesis.json")
    82  		if err := os.WriteFile(json, []byte(tt.genesis), 0600); err != nil {
    83  			t.Fatalf("test %d: failed to write genesis file: %v", i, err)
    84  		}
    85  		runGeth(t, "--datadir", datadir, "init", json).WaitExit()
    86  
    87  		// Query the custom genesis block
    88  		geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--cache", "16",
    89  			"--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0",
    90  			"--nodiscover", "--nat", "none", "--ipcdisable",
    91  			"--exec", tt.query, "console")
    92  		geth.ExpectRegexp(tt.result)
    93  		geth.ExpectExit()
    94  	}
    95  }
    96  
    97  // TestCustomBackend that the backend selection and detection (leveldb vs pebble) works properly.
    98  func TestCustomBackend(t *testing.T) {
    99  	t.Parallel()
   100  	// Test pebble, but only on 64-bit platforms
   101  	if strconv.IntSize != 64 {
   102  		t.Skip("Custom backends are only available on 64-bit platform")
   103  	}
   104  	genesis := `{
   105  		"alloc"      : {},
   106  		"coinbase"   : "0x0000000000000000000000000000000000000000",
   107  			"difficulty" : "0x20000",
   108  			"extraData"  : "",
   109  			"gasLimit"   : "0x2fefd8",
   110  			"nonce"      : "0x0000000000001338",
   111  			"mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
   112  			"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
   113  			"timestamp"  : "0x00",
   114  			"config"     : {}
   115  	}`
   116  	type backendTest struct {
   117  		initArgs   []string
   118  		initExpect string
   119  		execArgs   []string
   120  		execExpect string
   121  	}
   122  	testfunc := func(t *testing.T, tt backendTest) error {
   123  		// Create a temporary data directory to use and inspect later
   124  		datadir := t.TempDir()
   125  
   126  		// Initialize the data directory with the custom genesis block
   127  		json := filepath.Join(datadir, "genesis.json")
   128  		if err := os.WriteFile(json, []byte(genesis), 0600); err != nil {
   129  			return fmt.Errorf("failed to write genesis file: %v", err)
   130  		}
   131  		{ // Init
   132  			args := append(tt.initArgs, "--datadir", datadir, "init", json)
   133  			geth := runGeth(t, args...)
   134  			geth.ExpectRegexp(tt.initExpect)
   135  			geth.ExpectExit()
   136  		}
   137  		{ // Exec + query
   138  			args := append(tt.execArgs, "--networkid", "1337", "--syncmode=full", "--cache", "16",
   139  				"--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0",
   140  				"--nodiscover", "--nat", "none", "--ipcdisable",
   141  				"--exec", "eth.getBlock(0).nonce", "console")
   142  			geth := runGeth(t, args...)
   143  			geth.ExpectRegexp(tt.execExpect)
   144  			geth.ExpectExit()
   145  		}
   146  		return nil
   147  	}
   148  	for i, tt := range []backendTest{
   149  		{ // When not specified, it should default to leveldb
   150  			execArgs:   []string{"--db.engine", "leveldb"},
   151  			execExpect: "0x0000000000001338",
   152  		},
   153  		{ // Explicit leveldb
   154  			initArgs:   []string{"--db.engine", "leveldb"},
   155  			execArgs:   []string{"--db.engine", "leveldb"},
   156  			execExpect: "0x0000000000001338",
   157  		},
   158  		{ // Explicit leveldb first, then autodiscover
   159  			initArgs:   []string{"--db.engine", "leveldb"},
   160  			execExpect: "0x0000000000001338",
   161  		},
   162  		{ // Explicit pebble
   163  			initArgs:   []string{"--db.engine", "pebble"},
   164  			execArgs:   []string{"--db.engine", "pebble"},
   165  			execExpect: "0x0000000000001338",
   166  		},
   167  		{ // Explicit pebble, then auto-discover
   168  			initArgs:   []string{"--db.engine", "pebble"},
   169  			execExpect: "0x0000000000001338",
   170  		},
   171  		{ // Can't start pebble on top of leveldb
   172  			initArgs:   []string{"--db.engine", "leveldb"},
   173  			execArgs:   []string{"--db.engine", "pebble"},
   174  			execExpect: `Fatal: Failed to register the Ethereum service: db.engine choice was pebble but found pre-existing leveldb database in specified data directory`,
   175  		},
   176  		{ // Can't start leveldb on top of pebble
   177  			initArgs:   []string{"--db.engine", "pebble"},
   178  			execArgs:   []string{"--db.engine", "leveldb"},
   179  			execExpect: `Fatal: Failed to register the Ethereum service: db.engine choice was leveldb but found pre-existing pebble database in specified data directory`,
   180  		},
   181  		{ // Reject invalid backend choice
   182  			initArgs:   []string{"--db.engine", "mssql"},
   183  			initExpect: `Fatal: Invalid choice for db.engine 'mssql', allowed 'leveldb' or 'pebble'`,
   184  			// Since the init fails, this will return the (default) mainnet genesis
   185  			// block nonce
   186  			execExpect: `0x0000000000000042`,
   187  		},
   188  	} {
   189  		if err := testfunc(t, tt); err != nil {
   190  			t.Fatalf("test %d-leveldb: %v", i, err)
   191  		}
   192  	}
   193  }