1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

go-ethereumを読む(2) geth init編

Posted at

go-ethereumを読む(1) 準備編の続きで、
今回はローカルでgethを起動するために必要なGemesisブロックの生成辺りを解説します。
ローカルで動かすときはPOAで動かした方が処理が早いのでPOAの説明がメインです。
v1.8.15ベースに解説します

puppeth

gethを起動するときにdevフラグを付けない場合、gensis.jsonを作成する必要があります。
genesis.json作成についてはこの記事が詳しいです

geth init

gethをdevフラグをつけて起動する場合 geth init は必要ありません。
その場合下記の状態で起動されます。

  • POAになる
  • アカウントを作成・アンロックする
  • GasPriceが1になる

geth init実行時に処理されるコードを追っていきます。

makeFullNode > makeConfigNode > SetEthConfig

// cmd/utils/flags.go
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
	// 省略
	// Override any default configs for hard coded networks.
	switch {
	// 省略
	case ctx.GlobalBool(DeveloperFlag.Name):
		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
			cfg.NetworkId = 1337
		}
		// Create new developer account or reuse existing one
		var (
			developer accounts.Account
			err       error
		)
		if accs := ks.Accounts(); len(accs) > 0 {
			developer = ks.Accounts()[0]
		} else {
			developer, err = ks.NewAccount("")
			if err != nil {
				Fatalf("Failed to create developer account: %v", err)
			}
		}
		if err := ks.Unlock(developer, ""); err != nil {
			Fatalf("Failed to unlock developer account: %v", err)
		}
		log.Info("Using developer account", "address", developer.Address)

		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
			cfg.MinerGasPrice = big.NewInt(1)
		}
	}
	// 省略
}

// core/genesis.go
func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
	// POAになる(Clique)
	// Override the default period to the user requested one
	config := *params.AllCliqueProtocolChanges
	config.Clique.Period = period

	// Assemble and return the genesis with the precompiles and faucet pre-funded
	return &Genesis{
		Config:     &config,
		ExtraData:  append(append(make([]byte, 32), faucet[:]...), make([]byte, 65)...),
		GasLimit:   6283185,
		Difficulty: big.NewInt(1),
		Alloc: map[common.Address]GenesisAccount{
			common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
			common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
			common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
			common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
			common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
			common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
			common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
			common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
			faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
		},
	}
}

// 下のURLが詳しいので、ほとんど、ここを読めば事足りる
// https://arvanaghi.com/blog/explaining-the-genesis-block-in-ethereum/
type Genesis struct {
	Config     *params.ChainConfig `json:"config"` // ブロックチェーンの設定
	Nonce      uint64              `json:"nonce"`
	Timestamp  uint64              `json:"timestamp"`
	ExtraData  []byte              `json:"extraData"`
	GasLimit   uint64              `json:"gasLimit"   gencodec:"required"`
	Difficulty *big.Int            `json:"difficulty" gencodec:"required"`
	Mixhash    common.Hash         `json:"mixHash"`
	Coinbase   common.Address      `json:"coinbase"`
	Alloc      GenesisAlloc        `json:"alloc"      gencodec:"required"`

	// These fields are used for consensus tests. Please don't use them
	// in actual genesis blocks.
	Number     uint64      `json:"number"`
	GasUsed    uint64      `json:"gasUsed"`
	ParentHash common.Hash `json:"parentHash"`
}

// GenesisAlloc specifies the initial state that is part of the genesis block.
type GenesisAlloc map[common.Address]GenesisAccount

type ChainConfig struct {
	// blockchainの識別ID geth起動時に networkidとはべつもの
	// EIP155に定義されているのとは被らないようにする https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
	ChainId *big.Int `json:"chainId"`
	HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // 0に設定しておけばHomesteadになる main netも0らしい

	DAOForkBlock   *big.Int `json:"daoForkBlock,omitempty"`   // 指定の必要なし。TheDAO事件のHard Forkしたblock番号
	DAOForkSupport bool     `json:"daoForkSupport,omitempty"` // 指定の必要なし。TheDAO事件のHard Forkに賛成か反対かを指定

	// EIP150で Gas priceの変更があったのでそのための項目  (https://github.com/ethereum/EIPs/issues/150)
	// storage readのGas priceが他と比べて安すぎてトランザクション拒否攻撃やトランザクションspamを防ぐため?
	EIP150Block *big.Int    `json:"eip150Block,omitempty"` // 0を指定しておけばOK
	EIP150Hash  common.Hash `json:"eip150Hash,omitempty"`  // 指定の必要なし。 main netで --syncmode=fastで使用する  --syncmode=fastがデフォルト

	EIP155Block *big.Int `json:"eip155Block,omitempty"` // 0を指定しておけばOK EIP155 Hard Fork 別環境のtransactionが使えてしまう問題があって、TransactionHashにChainIdを付けるようになった
	EIP158Block *big.Int `json:"eip158Block,omitempty"` // 0を指定しておけばOK EIP158 Hard Fork 空のアカウントを無視して容量を削減するようにした

	ByzantiumBlock      *big.Int `json:"byzantiumBlock,omitempty"`      // 指定の必要なし。 Byzantiumに切り替えたブロック
	ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // 指定の必要なし。 Constantinopleに切り替えたブロック

	Ethash *EthashConfig `json:"ethash,omitempty"` // 指定の必要なし。 Ethashの設定 今のところ無し
	Clique *CliqueConfig `json:"clique,omitempty"` // POAにするときに必要
}

type CliqueConfig struct {
	Period uint64 `json:"period"` // ブロックの生成時間のインターバル
	// Epoch 投票(vote)のリセット間隔 checkpointはcheckpointIntervalだと思うけど、プログラムが怪しい?
	// 投票はblockのheaderのNonceを使って正しい署名者かをチェックする?
	// checkpointInterval毎のblockでsnapshotをdbに書き出す
	// それまでは、lruにインメモリで持っている
	Epoch  uint64 `json:"epoch"`				
}

// params/config.go
var (
	// 省略
	// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
	// and accepted by the Ethereum core developers into the Ethash consensus.
	//
	// This configuration is intentionally not using keyed fields to force anyone
	// adding flags to the config to also have to set these fields.
	AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}

	// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
	// and accepted by the Ethereum core developers into the Clique consensus.
	//
	// This configuration is intentionally not using keyed fields to force anyone
	// adding flags to the config to also have to set these fields.
	AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
	// 省略
)
$ geth --datadir testnet init genesis.json

普通の場合のサンプル

{
  "config": {
    "chainId": 33,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "clique": {
      "period": 33,
      "epoch": 30000
    }
  },
  "difficulty": "0x400000",
  "gasLimit": "0x8000000",
  "alloc": {}
  }
}

POA(clique)にする場合のサンプル

{
  "config": {
    "chainId": 33,
    "homesteadBlock": 1,
    "eip150Block": 2,
    "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "eip155Block": 3,
    "eip158Block": 3,
    "byzantiumBlock": 4,
    "clique": {
      "period": 15,
      "epoch": 30000
    }
  },
  "nonce": "0x0",
  "timestamp": "0x5afe4952",
  "extraData": "0x00000000000000000000000000000000000000000000000000000000000000004528fc478bb156f0e79988a1f5fca25bfa43039c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "gasLimit": "0x47b760",
  "difficulty": "0x1",
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "alloc": {
    "0000000000000000000000000000000000000000": {
      "balance": "0x1"
    },
  },
  "number": "0x0",
  "gasUsed": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?