From 7a6d5d0cce16e1a766e6fc89c3aacb7ecf502dcc Mon Sep 17 00:00:00 2001
From: gary rong <garyrong0905@gmail.com>
Date: Mon, 4 Nov 2019 16:41:29 +0800
Subject: [PATCH] cmd/puppeth: integrate istanbul into puppeth (#19926)

* cmd/puppeth: integrate istanbul into puppeth

* cmd/puppeth: address comment

* cmd/puppeth: use hexutil.Big for fork indicator

* cmd/puppeth: finalize istanbul fork

* cmd/puppeth: fix 2200 for parity, rename is to eip1283ReenableTransition

* cmd/puppeth: fix eip1108

* cmd/puppeth: add blake2f for parity

* cmd/puppeth: add aleth istanbul precompiled

* cmd/puppeth: use hexutil.Big

* cmd/puppeth: fix unit tests

* cmd/puppeth: update testdata
---
 cmd/puppeth/genesis.go                   | 229 +++++++++++-------
 cmd/puppeth/genesis_test.go              |   2 +-
 cmd/puppeth/testdata/stureby_aleth.json  | 177 +++++++-------
 cmd/puppeth/testdata/stureby_geth.json   |  33 ++-
 cmd/puppeth/testdata/stureby_parity.json | 289 ++++++++++++-----------
 cmd/puppeth/wizard_genesis.go            |   9 +-
 6 files changed, 414 insertions(+), 325 deletions(-)

diff --git a/cmd/puppeth/genesis.go b/cmd/puppeth/genesis.go
index ae7675cd9..44ad6c4cd 100644
--- a/cmd/puppeth/genesis.go
+++ b/cmd/puppeth/genesis.go
@@ -36,25 +36,27 @@ import (
 type alethGenesisSpec struct {
 	SealEngine string `json:"sealEngine"`
 	Params     struct {
-		AccountStartNonce       math2.HexOrDecimal64   `json:"accountStartNonce"`
-		MaximumExtraDataSize    hexutil.Uint64         `json:"maximumExtraDataSize"`
-		HomesteadForkBlock      hexutil.Uint64         `json:"homesteadForkBlock"`
-		DaoHardforkBlock        math2.HexOrDecimal64   `json:"daoHardforkBlock"`
-		EIP150ForkBlock         hexutil.Uint64         `json:"EIP150ForkBlock"`
-		EIP158ForkBlock         hexutil.Uint64         `json:"EIP158ForkBlock"`
-		ByzantiumForkBlock      hexutil.Uint64         `json:"byzantiumForkBlock"`
-		ConstantinopleForkBlock hexutil.Uint64         `json:"constantinopleForkBlock"`
-		MinGasLimit             hexutil.Uint64         `json:"minGasLimit"`
-		MaxGasLimit             hexutil.Uint64         `json:"maxGasLimit"`
-		TieBreakingGas          bool                   `json:"tieBreakingGas"`
-		GasLimitBoundDivisor    math2.HexOrDecimal64   `json:"gasLimitBoundDivisor"`
-		MinimumDifficulty       *hexutil.Big           `json:"minimumDifficulty"`
-		DifficultyBoundDivisor  *math2.HexOrDecimal256 `json:"difficultyBoundDivisor"`
-		DurationLimit           *math2.HexOrDecimal256 `json:"durationLimit"`
-		BlockReward             *hexutil.Big           `json:"blockReward"`
-		NetworkID               hexutil.Uint64         `json:"networkID"`
-		ChainID                 hexutil.Uint64         `json:"chainID"`
-		AllowFutureBlocks       bool                   `json:"allowFutureBlocks"`
+		AccountStartNonce          math2.HexOrDecimal64   `json:"accountStartNonce"`
+		MaximumExtraDataSize       hexutil.Uint64         `json:"maximumExtraDataSize"`
+		HomesteadForkBlock         *hexutil.Big           `json:"homesteadForkBlock,omitempty"`
+		DaoHardforkBlock           math2.HexOrDecimal64   `json:"daoHardforkBlock"`
+		EIP150ForkBlock            *hexutil.Big           `json:"EIP150ForkBlock,omitempty"`
+		EIP158ForkBlock            *hexutil.Big           `json:"EIP158ForkBlock,omitempty"`
+		ByzantiumForkBlock         *hexutil.Big           `json:"byzantiumForkBlock,omitempty"`
+		ConstantinopleForkBlock    *hexutil.Big           `json:"constantinopleForkBlock,omitempty"`
+		ConstantinopleFixForkBlock *hexutil.Big           `json:"constantinopleFixForkBlock,omitempty"`
+		IstanbulForkBlock          *hexutil.Big           `json:"istanbulForkBlock,omitempty"`
+		MinGasLimit                hexutil.Uint64         `json:"minGasLimit"`
+		MaxGasLimit                hexutil.Uint64         `json:"maxGasLimit"`
+		TieBreakingGas             bool                   `json:"tieBreakingGas"`
+		GasLimitBoundDivisor       math2.HexOrDecimal64   `json:"gasLimitBoundDivisor"`
+		MinimumDifficulty          *hexutil.Big           `json:"minimumDifficulty"`
+		DifficultyBoundDivisor     *math2.HexOrDecimal256 `json:"difficultyBoundDivisor"`
+		DurationLimit              *math2.HexOrDecimal256 `json:"durationLimit"`
+		BlockReward                *hexutil.Big           `json:"blockReward"`
+		NetworkID                  hexutil.Uint64         `json:"networkID"`
+		ChainID                    hexutil.Uint64         `json:"chainID"`
+		AllowFutureBlocks          bool                   `json:"allowFutureBlocks"`
 	} `json:"params"`
 
 	Genesis struct {
@@ -74,7 +76,7 @@ type alethGenesisSpec struct {
 // alethGenesisSpecAccount is the prefunded genesis account and/or precompiled
 // contract definition.
 type alethGenesisSpecAccount struct {
-	Balance     *math2.HexOrDecimal256   `json:"balance"`
+	Balance     *math2.HexOrDecimal256   `json:"balance,omitempty"`
 	Nonce       uint64                   `json:"nonce,omitempty"`
 	Precompiled *alethGenesisSpecBuiltin `json:"precompiled,omitempty"`
 }
@@ -82,7 +84,7 @@ type alethGenesisSpecAccount struct {
 // alethGenesisSpecBuiltin is the precompiled contract definition.
 type alethGenesisSpecBuiltin struct {
 	Name          string                         `json:"name,omitempty"`
-	StartingBlock hexutil.Uint64                 `json:"startingBlock,omitempty"`
+	StartingBlock *hexutil.Big                   `json:"startingBlock,omitempty"`
 	Linear        *alethGenesisSpecLinearPricing `json:"linear,omitempty"`
 }
 
@@ -106,21 +108,33 @@ func newAlethGenesisSpec(network string, genesis *core.Genesis) (*alethGenesisSp
 	spec.Params.AccountStartNonce = 0
 	spec.Params.TieBreakingGas = false
 	spec.Params.AllowFutureBlocks = false
-	spec.Params.DaoHardforkBlock = 0
 
-	spec.Params.HomesteadForkBlock = (hexutil.Uint64)(genesis.Config.HomesteadBlock.Uint64())
-	spec.Params.EIP150ForkBlock = (hexutil.Uint64)(genesis.Config.EIP150Block.Uint64())
-	spec.Params.EIP158ForkBlock = (hexutil.Uint64)(genesis.Config.EIP158Block.Uint64())
+	// Dao hardfork block is a special one. The fork block is listed as 0 in the
+	// config but aleth will sync with ETC clients up until the actual dao hard
+	// fork block.
+	spec.Params.DaoHardforkBlock = 0
 
-	// Byzantium
+	if num := genesis.Config.HomesteadBlock; num != nil {
+		spec.Params.HomesteadForkBlock = (*hexutil.Big)(num)
+	}
+	if num := genesis.Config.EIP150Block; num != nil {
+		spec.Params.EIP150ForkBlock = (*hexutil.Big)(num)
+	}
+	if num := genesis.Config.EIP158Block; num != nil {
+		spec.Params.EIP158ForkBlock = (*hexutil.Big)(num)
+	}
 	if num := genesis.Config.ByzantiumBlock; num != nil {
-		spec.setByzantium(num)
+		spec.Params.ByzantiumForkBlock = (*hexutil.Big)(num)
 	}
-	// Constantinople
 	if num := genesis.Config.ConstantinopleBlock; num != nil {
-		spec.setConstantinople(num)
+		spec.Params.ConstantinopleForkBlock = (*hexutil.Big)(num)
+	}
+	if num := genesis.Config.PetersburgBlock; num != nil {
+		spec.Params.ConstantinopleFixForkBlock = (*hexutil.Big)(num)
+	}
+	if num := genesis.Config.IstanbulBlock; num != nil {
+		spec.Params.IstanbulForkBlock = (*hexutil.Big)(num)
 	}
-
 	spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
 	spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
 	spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
@@ -157,15 +171,32 @@ func newAlethGenesisSpec(network string, genesis *core.Genesis) (*alethGenesisSp
 		Linear: &alethGenesisSpecLinearPricing{Base: 15, Word: 3}})
 	if genesis.Config.ByzantiumBlock != nil {
 		spec.setPrecompile(5, &alethGenesisSpecBuiltin{Name: "modexp",
-			StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64())})
+			StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock)})
 		spec.setPrecompile(6, &alethGenesisSpecBuiltin{Name: "alt_bn128_G1_add",
-			StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()),
+			StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
 			Linear:        &alethGenesisSpecLinearPricing{Base: 500}})
 		spec.setPrecompile(7, &alethGenesisSpecBuiltin{Name: "alt_bn128_G1_mul",
-			StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()),
+			StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
 			Linear:        &alethGenesisSpecLinearPricing{Base: 40000}})
 		spec.setPrecompile(8, &alethGenesisSpecBuiltin{Name: "alt_bn128_pairing_product",
-			StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64())})
+			StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock)})
+	}
+	if genesis.Config.IstanbulBlock != nil {
+		if genesis.Config.ByzantiumBlock == nil {
+			return nil, errors.New("invalid genesis, istanbul fork is enabled while byzantium is not")
+		}
+		spec.setPrecompile(6, &alethGenesisSpecBuiltin{
+			Name:          "alt_bn128_G1_add",
+			StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
+		}) // Aleth hardcoded the gas policy
+		spec.setPrecompile(7, &alethGenesisSpecBuiltin{
+			Name:          "alt_bn128_G1_mul",
+			StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
+		}) // Aleth hardcoded the gas policy
+		spec.setPrecompile(9, &alethGenesisSpecBuiltin{
+			Name:          "blake2_compression",
+			StartingBlock: (*hexutil.Big)(genesis.Config.IstanbulBlock),
+		})
 	}
 	return spec, nil
 }
@@ -196,14 +227,6 @@ func (spec *alethGenesisSpec) setAccount(address common.Address, account core.Ge
 
 }
 
-func (spec *alethGenesisSpec) setByzantium(num *big.Int) {
-	spec.Params.ByzantiumForkBlock = hexutil.Uint64(num.Uint64())
-}
-
-func (spec *alethGenesisSpec) setConstantinople(num *big.Int) {
-	spec.Params.ConstantinopleForkBlock = hexutil.Uint64(num.Uint64())
-}
-
 // parityChainSpec is the chain specification format used by Parity.
 type parityChainSpec struct {
 	Name    string `json:"name"`
@@ -223,29 +246,33 @@ type parityChainSpec struct {
 	} `json:"engine"`
 
 	Params struct {
-		AccountStartNonce        hexutil.Uint64       `json:"accountStartNonce"`
-		MaximumExtraDataSize     hexutil.Uint64       `json:"maximumExtraDataSize"`
-		MinGasLimit              hexutil.Uint64       `json:"minGasLimit"`
-		GasLimitBoundDivisor     math2.HexOrDecimal64 `json:"gasLimitBoundDivisor"`
-		NetworkID                hexutil.Uint64       `json:"networkID"`
-		ChainID                  hexutil.Uint64       `json:"chainID"`
-		MaxCodeSize              hexutil.Uint64       `json:"maxCodeSize"`
-		MaxCodeSizeTransition    hexutil.Uint64       `json:"maxCodeSizeTransition"`
-		EIP98Transition          hexutil.Uint64       `json:"eip98Transition"`
-		EIP150Transition         hexutil.Uint64       `json:"eip150Transition"`
-		EIP160Transition         hexutil.Uint64       `json:"eip160Transition"`
-		EIP161abcTransition      hexutil.Uint64       `json:"eip161abcTransition"`
-		EIP161dTransition        hexutil.Uint64       `json:"eip161dTransition"`
-		EIP155Transition         hexutil.Uint64       `json:"eip155Transition"`
-		EIP140Transition         hexutil.Uint64       `json:"eip140Transition"`
-		EIP211Transition         hexutil.Uint64       `json:"eip211Transition"`
-		EIP214Transition         hexutil.Uint64       `json:"eip214Transition"`
-		EIP658Transition         hexutil.Uint64       `json:"eip658Transition"`
-		EIP145Transition         hexutil.Uint64       `json:"eip145Transition"`
-		EIP1014Transition        hexutil.Uint64       `json:"eip1014Transition"`
-		EIP1052Transition        hexutil.Uint64       `json:"eip1052Transition"`
-		EIP1283Transition        hexutil.Uint64       `json:"eip1283Transition"`
-		EIP1283DisableTransition hexutil.Uint64       `json:"eip1283DisableTransition"`
+		AccountStartNonce         hexutil.Uint64       `json:"accountStartNonce"`
+		MaximumExtraDataSize      hexutil.Uint64       `json:"maximumExtraDataSize"`
+		MinGasLimit               hexutil.Uint64       `json:"minGasLimit"`
+		GasLimitBoundDivisor      math2.HexOrDecimal64 `json:"gasLimitBoundDivisor"`
+		NetworkID                 hexutil.Uint64       `json:"networkID"`
+		ChainID                   hexutil.Uint64       `json:"chainID"`
+		MaxCodeSize               hexutil.Uint64       `json:"maxCodeSize"`
+		MaxCodeSizeTransition     hexutil.Uint64       `json:"maxCodeSizeTransition"`
+		EIP98Transition           hexutil.Uint64       `json:"eip98Transition"`
+		EIP150Transition          hexutil.Uint64       `json:"eip150Transition"`
+		EIP160Transition          hexutil.Uint64       `json:"eip160Transition"`
+		EIP161abcTransition       hexutil.Uint64       `json:"eip161abcTransition"`
+		EIP161dTransition         hexutil.Uint64       `json:"eip161dTransition"`
+		EIP155Transition          hexutil.Uint64       `json:"eip155Transition"`
+		EIP140Transition          hexutil.Uint64       `json:"eip140Transition"`
+		EIP211Transition          hexutil.Uint64       `json:"eip211Transition"`
+		EIP214Transition          hexutil.Uint64       `json:"eip214Transition"`
+		EIP658Transition          hexutil.Uint64       `json:"eip658Transition"`
+		EIP145Transition          hexutil.Uint64       `json:"eip145Transition"`
+		EIP1014Transition         hexutil.Uint64       `json:"eip1014Transition"`
+		EIP1052Transition         hexutil.Uint64       `json:"eip1052Transition"`
+		EIP1283Transition         hexutil.Uint64       `json:"eip1283Transition"`
+		EIP1283DisableTransition  hexutil.Uint64       `json:"eip1283DisableTransition"`
+		EIP1283ReenableTransition hexutil.Uint64       `json:"eip1283ReenableTransition"`
+		EIP1344Transition         hexutil.Uint64       `json:"eip1344Transition"`
+		EIP1884Transition         hexutil.Uint64       `json:"eip1884Transition"`
+		EIP2028Transition         hexutil.Uint64       `json:"eip2028Transition"`
 	} `json:"params"`
 
 	Genesis struct {
@@ -278,17 +305,22 @@ type parityChainSpecAccount struct {
 
 // parityChainSpecBuiltin is the precompiled contract definition.
 type parityChainSpecBuiltin struct {
-	Name       string                  `json:"name,omitempty"`
-	ActivateAt math2.HexOrDecimal64    `json:"activate_at,omitempty"`
-	Pricing    *parityChainSpecPricing `json:"pricing,omitempty"`
+	Name              string                  `json:"name"`                         // Each builtin should has it own name
+	Pricing           *parityChainSpecPricing `json:"pricing"`                      // Each builtin should has it own price strategy
+	ActivateAt        *hexutil.Big            `json:"activate_at,omitempty"`        // ActivateAt can't be omitted if empty, default means no fork
+	EIP1108Transition *hexutil.Big            `json:"eip1108_transition,omitempty"` // EIP1108Transition can't be omitted if empty, default means no fork
 }
 
 // parityChainSpecPricing represents the different pricing models that builtin
 // contracts might advertise using.
 type parityChainSpecPricing struct {
-	Linear       *parityChainSpecLinearPricing       `json:"linear,omitempty"`
-	ModExp       *parityChainSpecModExpPricing       `json:"modexp,omitempty"`
-	AltBnPairing *parityChainSpecAltBnPairingPricing `json:"alt_bn128_pairing,omitempty"`
+	Linear              *parityChainSpecLinearPricing              `json:"linear,omitempty"`
+	ModExp              *parityChainSpecModExpPricing              `json:"modexp,omitempty"`
+	AltBnPairing        *parityChainSpecAltBnPairingPricing        `json:"alt_bn128_pairing,omitempty"`
+	AltBnConstOperation *parityChainSpecAltBnConstOperationPricing `json:"alt_bn128_const_operations,omitempty"`
+
+	// Blake2F is the price per round of Blake2 compression
+	Blake2F *parityChainSpecBlakePricing `json:"blake2_f,omitempty"`
 }
 
 type parityChainSpecLinearPricing struct {
@@ -300,9 +332,20 @@ type parityChainSpecModExpPricing struct {
 	Divisor uint64 `json:"divisor"`
 }
 
+type parityChainSpecAltBnConstOperationPricing struct {
+	Price                  uint64 `json:"price"`
+	EIP1108TransitionPrice uint64 `json:"eip1108_transition_price,omitempty"` // Before Istanbul fork, this field is nil
+}
+
 type parityChainSpecAltBnPairingPricing struct {
-	Base uint64 `json:"base"`
-	Pair uint64 `json:"pair"`
+	Base                  uint64 `json:"base"`
+	Pair                  uint64 `json:"pair"`
+	EIP1108TransitionBase uint64 `json:"eip1108_transition_base,omitempty"` // Before Istanbul fork, this field is nil
+	EIP1108TransitionPair uint64 `json:"eip1108_transition_pair,omitempty"` // Before Istanbul fork, this field is nil
+}
+
+type parityChainSpecBlakePricing struct {
+	GasPerRound uint64 `json:"gas_per_round"`
 }
 
 // newParityChainSpec converts a go-ethereum genesis block into a Parity specific
@@ -352,7 +395,10 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
 	if num := genesis.Config.PetersburgBlock; num != nil {
 		spec.setConstantinopleFix(num)
 	}
-
+	// Istanbul
+	if num := genesis.Config.IstanbulBlock; num != nil {
+		spec.setIstanbul(num)
+	}
 	spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
 	spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
 	spec.Params.GasLimitBoundDivisor = (math2.HexOrDecimal64)(params.GasLimitBoundDivisor)
@@ -398,18 +444,34 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
 		Name: "identity", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 15, Word: 3}},
 	})
 	if genesis.Config.ByzantiumBlock != nil {
-		blnum := math2.HexOrDecimal64(genesis.Config.ByzantiumBlock.Uint64())
 		spec.setPrecompile(5, &parityChainSpecBuiltin{
-			Name: "modexp", ActivateAt: blnum, Pricing: &parityChainSpecPricing{ModExp: &parityChainSpecModExpPricing{Divisor: 20}},
+			Name: "modexp", ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock), Pricing: &parityChainSpecPricing{ModExp: &parityChainSpecModExpPricing{Divisor: 20}},
 		})
 		spec.setPrecompile(6, &parityChainSpecBuiltin{
-			Name: "alt_bn128_add", ActivateAt: blnum, Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 500}},
+			Name: "alt_bn128_add", ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock), Pricing: &parityChainSpecPricing{AltBnConstOperation: &parityChainSpecAltBnConstOperationPricing{Price: 500}},
 		})
 		spec.setPrecompile(7, &parityChainSpecBuiltin{
-			Name: "alt_bn128_mul", ActivateAt: blnum, Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 40000}},
+			Name: "alt_bn128_mul", ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock), Pricing: &parityChainSpecPricing{AltBnConstOperation: &parityChainSpecAltBnConstOperationPricing{Price: 40000}},
 		})
 		spec.setPrecompile(8, &parityChainSpecBuiltin{
-			Name: "alt_bn128_pairing", ActivateAt: blnum, Pricing: &parityChainSpecPricing{AltBnPairing: &parityChainSpecAltBnPairingPricing{Base: 100000, Pair: 80000}},
+			Name: "alt_bn128_pairing", ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock), Pricing: &parityChainSpecPricing{AltBnPairing: &parityChainSpecAltBnPairingPricing{Base: 100000, Pair: 80000}},
+		})
+	}
+	if genesis.Config.IstanbulBlock != nil {
+		if genesis.Config.ByzantiumBlock == nil {
+			return nil, errors.New("invalid genesis, istanbul fork is enabled while byzantium is not")
+		}
+		spec.setPrecompile(6, &parityChainSpecBuiltin{
+			Name: "alt_bn128_add", ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock), EIP1108Transition: (*hexutil.Big)(genesis.Config.IstanbulBlock), Pricing: &parityChainSpecPricing{AltBnConstOperation: &parityChainSpecAltBnConstOperationPricing{Price: 500, EIP1108TransitionPrice: 150}},
+		})
+		spec.setPrecompile(7, &parityChainSpecBuiltin{
+			Name: "alt_bn128_mul", ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock), EIP1108Transition: (*hexutil.Big)(genesis.Config.IstanbulBlock), Pricing: &parityChainSpecPricing{AltBnConstOperation: &parityChainSpecAltBnConstOperationPricing{Price: 40000, EIP1108TransitionPrice: 6000}},
+		})
+		spec.setPrecompile(8, &parityChainSpecBuiltin{
+			Name: "alt_bn128_pairing", ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock), EIP1108Transition: (*hexutil.Big)(genesis.Config.IstanbulBlock), Pricing: &parityChainSpecPricing{AltBnPairing: &parityChainSpecAltBnPairingPricing{Base: 100000, Pair: 80000, EIP1108TransitionBase: 45000, EIP1108TransitionPair: 34000}},
+		})
+		spec.setPrecompile(9, &parityChainSpecBuiltin{
+			Name: "blake2_f", ActivateAt: (*hexutil.Big)(genesis.Config.IstanbulBlock), Pricing: &parityChainSpecPricing{Blake2F: &parityChainSpecBlakePricing{GasPerRound: 1}},
 		})
 	}
 	return spec, nil
@@ -451,6 +513,15 @@ func (spec *parityChainSpec) setConstantinopleFix(num *big.Int) {
 	spec.Params.EIP1283DisableTransition = hexutil.Uint64(num.Uint64())
 }
 
+func (spec *parityChainSpec) setIstanbul(num *big.Int) {
+	// spec.Params.EIP152Transition = hexutil.Uint64(num.Uint64())
+	// spec.Params.EIP1108Transition = hexutil.Uint64(num.Uint64())
+	spec.Params.EIP1344Transition = hexutil.Uint64(num.Uint64())
+	spec.Params.EIP1884Transition = hexutil.Uint64(num.Uint64())
+	spec.Params.EIP2028Transition = hexutil.Uint64(num.Uint64())
+	spec.Params.EIP1283ReenableTransition = hexutil.Uint64(num.Uint64())
+}
+
 // pyEthereumGenesisSpec represents the genesis specification format used by the
 // Python Ethereum implementation.
 type pyEthereumGenesisSpec struct {
diff --git a/cmd/puppeth/genesis_test.go b/cmd/puppeth/genesis_test.go
index f128da24f..1fd1b35c4 100644
--- a/cmd/puppeth/genesis_test.go
+++ b/cmd/puppeth/genesis_test.go
@@ -76,7 +76,7 @@ func TestParitySturebyConverter(t *testing.T) {
 	if err := json.Unmarshal(blob, &genesis); err != nil {
 		t.Fatalf("failed parsing genesis: %v", err)
 	}
-	spec, err := newParityChainSpec("Stureby", &genesis, []string{})
+	spec, err := newParityChainSpec("stureby", &genesis, []string{})
 	if err != nil {
 		t.Fatalf("failed creating chainspec: %v", err)
 	}
diff --git a/cmd/puppeth/testdata/stureby_aleth.json b/cmd/puppeth/testdata/stureby_aleth.json
index 1ef1d8ae1..d18ba3854 100644
--- a/cmd/puppeth/testdata/stureby_aleth.json
+++ b/cmd/puppeth/testdata/stureby_aleth.json
@@ -1,112 +1,113 @@
 {
-  "sealEngine":"Ethash",
-  "params":{
-    "accountStartNonce":"0x00",
-    "maximumExtraDataSize":"0x20",
-    "homesteadForkBlock":"0x2710",
-    "daoHardforkBlock":"0x00",
-    "EIP150ForkBlock":"0x3a98",
-    "EIP158ForkBlock":"0x59d8",
-    "byzantiumForkBlock":"0x7530",
-    "constantinopleForkBlock":"0x9c40",
-    "minGasLimit":"0x1388",
-    "maxGasLimit":"0x7fffffffffffffff",
-    "tieBreakingGas":false,
-    "gasLimitBoundDivisor":"0x0400",
-    "minimumDifficulty":"0x20000",
-    "difficultyBoundDivisor":"0x0800",
-    "durationLimit":"0x0d",
-    "blockReward":"0x4563918244F40000",
-    "networkID":"0x4cb2e",
-    "chainID":"0x4cb2e",
-    "allowFutureBlocks":false
+  "sealEngine": "Ethash",
+  "params": {
+    "accountStartNonce": "0x0",
+    "maximumExtraDataSize": "0x20",
+    "homesteadForkBlock": "0x2710",
+    "daoHardforkBlock": "0x0",
+    "EIP150ForkBlock": "0x3a98",
+    "EIP158ForkBlock": "0x59d8",
+    "byzantiumForkBlock": "0x7530",
+    "constantinopleForkBlock": "0x9c40",
+    "constantinopleFixForkBlock": "0x9c40",
+    "istanbulForkBlock": "0xc350",
+    "minGasLimit": "0x1388",
+    "maxGasLimit": "0x7fffffffffffffff",
+    "tieBreakingGas": false,
+    "gasLimitBoundDivisor": "0x400",
+    "minimumDifficulty": "0x20000",
+    "difficultyBoundDivisor": "0x800",
+    "durationLimit": "0xd",
+    "blockReward": "0x4563918244f40000",
+    "networkID": "0x4cb2e",
+    "chainID": "0x4cb2e",
+    "allowFutureBlocks": false
   },
-  "genesis":{
-    "nonce":"0x0000000000000000",
-    "difficulty":"0x20000",
-    "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
-    "author":"0x0000000000000000000000000000000000000000",
-    "timestamp":"0x59a4e76d",
-    "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
-    "extraData":"0x0000000000000000000000000000000000000000000000000000000b4dc0ffee",
-    "gasLimit":"0x47b760"
+  "genesis": {
+    "nonce": "0x0000000000000000",
+    "difficulty": "0x20000",
+    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+    "author": "0x0000000000000000000000000000000000000000",
+    "timestamp": "0x59a4e76d",
+    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+    "extraData": "0x0000000000000000000000000000000000000000000000000000000b4dc0ffee",
+    "gasLimit": "0x47b760"
   },
-  "accounts":{
-    "0000000000000000000000000000000000000001":{
-      "balance":"1",
-      "precompiled":{
-        "name":"ecrecover",
-        "linear":{
-          "base":3000,
-          "word":0
+  "accounts": {
+    "0000000000000000000000000000000000000001": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "ecrecover",
+        "linear": {
+          "base": 3000,
+          "word": 0
         }
       }
     },
-    "0000000000000000000000000000000000000002":{
-      "balance":"1",
-      "precompiled":{
-        "name":"sha256",
-        "linear":{
-          "base":60,
-          "word":12
+    "0000000000000000000000000000000000000002": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "sha256",
+        "linear": {
+          "base": 60,
+          "word": 12
         }
       }
     },
-    "0000000000000000000000000000000000000003":{
-      "balance":"1",
-      "precompiled":{
-        "name":"ripemd160",
-        "linear":{
-          "base":600,
-          "word":120
+    "0000000000000000000000000000000000000003": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "ripemd160",
+        "linear": {
+          "base": 600,
+          "word": 120
         }
       }
     },
-    "0000000000000000000000000000000000000004":{
-      "balance":"1",
-      "precompiled":{
-        "name":"identity",
-        "linear":{
-          "base":15,
-          "word":3
+    "0000000000000000000000000000000000000004": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "identity",
+        "linear": {
+          "base": 15,
+          "word": 3
         }
       }
     },
-    "0000000000000000000000000000000000000005":{
-      "balance":"1",
-      "precompiled":{
-        "name":"modexp",
-        "startingBlock":"0x7530"
+    "0000000000000000000000000000000000000005": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "modexp",
+        "startingBlock": "0x7530"
       }
     },
-    "0000000000000000000000000000000000000006":{
-      "balance":"1",
-      "precompiled":{
-        "name":"alt_bn128_G1_add",
-        "startingBlock":"0x7530",
-        "linear":{
-          "base":500,
-          "word":0
-        }
+    "0000000000000000000000000000000000000006": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "alt_bn128_G1_add",
+        "startingBlock": "0x7530"
       }
     },
-    "0000000000000000000000000000000000000007":{
-      "balance":"1",
-      "precompiled":{
-        "name":"alt_bn128_G1_mul",
-        "startingBlock":"0x7530",
-        "linear":{
-          "base":40000,
-          "word":0
-        }
+    "0000000000000000000000000000000000000007": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "alt_bn128_G1_mul",
+        "startingBlock": "0x7530"
+      }
+    },
+    "0000000000000000000000000000000000000008": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "alt_bn128_pairing_product",
+        "startingBlock": "0x7530"
       }
     },
-    "0000000000000000000000000000000000000008":{
-      "balance":"1",
-      "precompiled":{
-        "name":"alt_bn128_pairing_product",
-        "startingBlock":"0x7530"
+    "0000000000000000000000000000000000000009": {
+      "balance": "0x1",
+      "precompiled": {
+        "name": "blake2_compression",
+        "startingBlock": "0xc350"
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/cmd/puppeth/testdata/stureby_geth.json b/cmd/puppeth/testdata/stureby_geth.json
index c8c3b3c95..79f03469a 100644
--- a/cmd/puppeth/testdata/stureby_geth.json
+++ b/cmd/puppeth/testdata/stureby_geth.json
@@ -1,6 +1,5 @@
 {
   "config": {
-    "ethash":{},
     "chainId": 314158,
     "homesteadBlock": 10000,
     "eip150Block": 15000,
@@ -8,11 +7,13 @@
     "eip155Block": 23000,
     "eip158Block": 23000,
     "byzantiumBlock": 30000,
-    "constantinopleBlock": 40000
+    "constantinopleBlock": 40000,
+    "petersburgBlock": 40000,
+    "istanbulBlock": 50000,
+    "ethash": {}
   },
   "nonce": "0x0",
   "timestamp": "0x59a4e76d",
-  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
   "extraData": "0x0000000000000000000000000000000000000000000000000000000b4dc0ffee",
   "gasLimit": "0x47b760",
   "difficulty": "0x20000",
@@ -20,28 +21,34 @@
   "coinbase": "0x0000000000000000000000000000000000000000",
   "alloc": {
     "0000000000000000000000000000000000000001": {
-      "balance": "0x01"
+      "balance": "0x1"
     },
     "0000000000000000000000000000000000000002": {
-      "balance": "0x01"
+      "balance": "0x1"
     },
     "0000000000000000000000000000000000000003": {
-      "balance": "0x01"
+      "balance": "0x1"
     },
     "0000000000000000000000000000000000000004": {
-      "balance": "0x01"
+      "balance": "0x1"
     },
     "0000000000000000000000000000000000000005": {
-      "balance": "0x01"
+      "balance": "0x1"
     },
     "0000000000000000000000000000000000000006": {
-      "balance": "0x01"
+      "balance": "0x1"
     },
     "0000000000000000000000000000000000000007": {
-      "balance": "0x01"
+      "balance": "0x1"
     },
     "0000000000000000000000000000000000000008": {
-      "balance": "0x01"
+      "balance": "0x1"
+    },
+    "0000000000000000000000000000000000000009": {
+      "balance": "0x1"
     }
-  }
-}
+  },
+  "number": "0x0",
+  "gasUsed": "0x0",
+  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
+}
\ No newline at end of file
diff --git a/cmd/puppeth/testdata/stureby_parity.json b/cmd/puppeth/testdata/stureby_parity.json
index f3fa8386a..fb84b39e2 100644
--- a/cmd/puppeth/testdata/stureby_parity.json
+++ b/cmd/puppeth/testdata/stureby_parity.json
@@ -1,181 +1,186 @@
 {
-  "name":"Stureby",
-  "dataDir":"stureby",
-  "engine":{
-    "Ethash":{
-      "params":{
-        "minimumDifficulty":"0x20000",
-        "difficultyBoundDivisor":"0x800",
-        "durationLimit":"0xd",
-        "blockReward":{
-          "0x0":"0x4563918244f40000",
-          "0x7530":"0x29a2241af62c0000",
-          "0x9c40":"0x1bc16d674ec80000"
+  "name": "stureby",
+  "dataDir": "stureby",
+  "engine": {
+    "Ethash": {
+      "params": {
+        "minimumDifficulty": "0x20000",
+        "difficultyBoundDivisor": "0x800",
+        "durationLimit": "0xd",
+        "blockReward": {
+          "0x0": "0x4563918244f40000",
+          "0x7530": "0x29a2241af62c0000",
+          "0x9c40": "0x1bc16d674ec80000"
         },
-        "homesteadTransition":"0x2710",
-        "eip100bTransition":"0x7530",
-        "difficultyBombDelays":{
-          "0x7530":"0x2dc6c0",
-          "0x9c40":"0x1e8480"
-        }
+        "difficultyBombDelays": {
+          "0x7530": "0x2dc6c0",
+          "0x9c40": "0x1e8480"
+        },
+        "homesteadTransition": "0x2710",
+        "eip100bTransition": "0x7530"
       }
     }
   },
-  "params":{
-    "accountStartNonce":"0x0",
-    "maximumExtraDataSize":"0x20",
-    "gasLimitBoundDivisor":"0x400",
-    "minGasLimit":"0x1388",
-    "networkID":"0x4cb2e",
-    "chainID":"0x4cb2e",
-    "maxCodeSize":"0x6000",
-    "maxCodeSizeTransition":"0x0",
+  "params": {
+    "accountStartNonce": "0x0",
+    "maximumExtraDataSize": "0x20",
+    "minGasLimit": "0x1388",
+    "gasLimitBoundDivisor": "0x400",
+    "networkID": "0x4cb2e",
+    "chainID": "0x4cb2e",
+    "maxCodeSize": "0x6000",
+    "maxCodeSizeTransition": "0x0",
     "eip98Transition": "0x7fffffffffffffff",
-    "eip150Transition":"0x3a98",
-    "eip160Transition":"0x59d8",
-    "eip161abcTransition":"0x59d8",
-    "eip161dTransition":"0x59d8",
-    "eip155Transition":"0x59d8",
-    "eip140Transition":"0x7530",
-    "eip211Transition":"0x7530",
-    "eip214Transition":"0x7530",
-    "eip658Transition":"0x7530",
-    "eip145Transition":"0x9c40",
-    "eip1014Transition":"0x9c40",
-    "eip1052Transition":"0x9c40",
-    "eip1283Transition":"0x9c40"
+    "eip150Transition": "0x3a98",
+    "eip160Transition": "0x59d8",
+    "eip161abcTransition": "0x59d8",
+    "eip161dTransition": "0x59d8",
+    "eip155Transition": "0x59d8",
+    "eip140Transition": "0x7530",
+    "eip211Transition": "0x7530",
+    "eip214Transition": "0x7530",
+    "eip658Transition": "0x7530",
+    "eip145Transition": "0x9c40",
+    "eip1014Transition": "0x9c40",
+    "eip1052Transition": "0x9c40",
+    "eip1283Transition": "0x9c40",
+    "eip1283DisableTransition": "0x9c40",
+    "eip1283ReenableTransition": "0xc350",
+    "eip1344Transition": "0xc350",
+    "eip1884Transition": "0xc350",
+    "eip2028Transition": "0xc350"
   },
-  "genesis":{
-    "seal":{
-      "ethereum":{
-        "nonce":"0x0000000000000000",
-        "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000"
+  "genesis": {
+    "seal": {
+      "ethereum": {
+        "nonce": "0x0000000000000000",
+        "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
       }
     },
-    "difficulty":"0x20000",
-    "author":"0x0000000000000000000000000000000000000000",
-    "timestamp":"0x59a4e76d",
-    "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
-    "extraData":"0x0000000000000000000000000000000000000000000000000000000b4dc0ffee",
-    "gasLimit":"0x47b760"
+    "difficulty": "0x20000",
+    "author": "0x0000000000000000000000000000000000000000",
+    "timestamp": "0x59a4e76d",
+    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+    "extraData": "0x0000000000000000000000000000000000000000000000000000000b4dc0ffee",
+    "gasLimit": "0x47b760"
   },
-  "nodes":[
-    "enode://dfa7aca3f5b635fbfe7d0b20575f25e40d9e27b4bfbb3cf74364a42023ad9f25c1a4383bcc8cced86ee511a7d03415345a4df05be37f1dff040e4c780699f1c0@168.61.153.255:31303",
-    "enode://ef441b20dd70aeabf0eac35c3b8a2854e5ce04db0e30be9152ea9fd129359dcbb3f803993303ff5781c755dfd7223f3fe43505f583cccb740949407677412ba9@40.74.91.252:31303",
-    "enode://953b5ea1c8987cf46008232a0160324fd00d41320ecf00e23af86ec8f5396b19eb57ddab37c78141be56f62e9077de4f4dfa0747fa768ed8c8531bbfb1046237@40.70.214.166:31303",
-    "enode://276e613dd4b277a66591e565711e6c8bb107f0905248a9f8f8228c1a87992e156e5114bb9937c02824a9d9d25f76340442cf86e2028bf5293cae19904fb2b98e@35.178.251.52:30303",
-    "enode://064c820d41e52ed7d426ac64b60506c2998235bedc7e67cb497c6faf7bb4fc54fe56fc82d0add3180b747c0c4f40a1108a6f84d7d0629ed606d504528e61cc57@3.8.5.3:30303",
-    "enode://90069fdabcc5e684fa5d59430bebbb12755d9362dfe5006a1485b13d71a78a3812d36e74dd7d88e50b51add01e097ea80f16263aeaa4f0230db6c79e2a97e7ca@217.29.191.142:30303",
-    "enode://0aac74b7fd28726275e466acb5e03bc88a95927e9951eb66b5efb239b2f798ada0690853b2f2823fe4efa408f0f3d4dd258430bc952a5ff70677b8625b3e3b14@40.115.33.57:40404",
-    "enode://0b96415a10f835106d83e090a0528eed5e7887e5c802a6d084e9f1993a9d0fc713781e6e4101f6365e9b91259712f291acc0a9e6e667e22023050d602c36fbe2@40.115.33.57:40414"
-  ],
-  "accounts":{
-    "0000000000000000000000000000000000000001":{
-      "balance":"1",
-      "nonce":"0",
-      "builtin":{
-        "name":"ecrecover",
-        "pricing":{
-          "linear":{
-            "base":3000,
-            "word":0
+  "nodes": [],
+  "accounts": {
+    "0000000000000000000000000000000000000001": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "ecrecover",
+        "pricing": {
+          "linear": {
+            "base": 3000,
+            "word": 0
           }
         }
       }
     },
-    "0000000000000000000000000000000000000002":{
-      "balance":"1",
-      "nonce":"0",
-      "builtin":{
-        "name":"sha256",
-        "pricing":{
-          "linear":{
-            "base":60,
-            "word":12
+    "0000000000000000000000000000000000000002": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "sha256",
+        "pricing": {
+          "linear": {
+            "base": 60,
+            "word": 12
           }
         }
       }
     },
-    "0000000000000000000000000000000000000003":{
-      "balance":"1",
-      "nonce":"0",
-      "builtin":{
-        "name":"ripemd160",
-        "pricing":{
-          "linear":{
-            "base":600,
-            "word":120
+    "0000000000000000000000000000000000000003": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "ripemd160",
+        "pricing": {
+          "linear": {
+            "base": 600,
+            "word": 120
           }
         }
       }
     },
-    "0000000000000000000000000000000000000004":{
-      "balance":"1",
-      "nonce":"0",
-      "builtin":{
-        "name":"identity",
-        "pricing":{
-          "linear":{
-            "base":15,
-            "word":3
+    "0000000000000000000000000000000000000004": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "identity",
+        "pricing": {
+          "linear": {
+            "base": 15,
+            "word": 3
           }
         }
       }
     },
-    "0000000000000000000000000000000000000005":{
-      "balance":"1",
-      "nonce":"0",
-      "builtin":{
-        "name":"modexp",
-        "activate_at":"0x7530",
-        "pricing":{
-          "modexp":{
-            "divisor":20
+    "0000000000000000000000000000000000000005": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "modexp",
+        "pricing": {
+          "modexp": {
+            "divisor": 20
           }
-        }
+        },
+        "activate_at": "0x7530"
       }
     },
-    "0000000000000000000000000000000000000006":{
-      "balance":"1",
-      "nonce":"0",
-      "builtin":{
-        "name":"alt_bn128_add",
-        "activate_at":"0x7530",
-        "pricing":{
-          "linear":{
-            "base":500,
-            "word":0
+    "0000000000000000000000000000000000000006": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "alt_bn128_add",
+        "pricing": {
+          "alt_bn128_const_operations": {
+            "price": 500,
+            "eip1108_transition_price": 150
           }
-        }
+        },
+        "activate_at": "0x7530",
+        "eip1108_transition": "0xc350"
       }
     },
-    "0000000000000000000000000000000000000007":{
-      "balance":"1",
-      "nonce":"0",
-      "builtin":{
-        "name":"alt_bn128_mul",
-        "activate_at":"0x7530",
-        "pricing":{
-          "linear":{
-            "base":40000,
-            "word":0
+    "0000000000000000000000000000000000000007": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "alt_bn128_mul",
+        "pricing": {
+          "alt_bn128_const_operations": {
+            "price": 40000,
+            "eip1108_transition_price": 6000
           }
-        }
+        },
+        "activate_at": "0x7530",
+        "eip1108_transition": "0xc350"
       }
     },
-    "0000000000000000000000000000000000000008":{
-      "balance":"1",
-      "nonce":"0",
-      "builtin":{
-        "name":"alt_bn128_pairing",
-        "activate_at":"0x7530",
-        "pricing":{
-          "alt_bn128_pairing":{
-            "base":100000,
-            "pair":80000
+    "0000000000000000000000000000000000000008": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "alt_bn128_pairing",
+        "pricing": {
+          "alt_bn128_pairing": {
+            "base": 100000,
+            "pair": 80000,
+            "eip1108_transition_base": 45000,
+            "eip1108_transition_pair": 34000
           }
-        }
+        },
+        "activate_at": "0x7530",
+        "eip1108_transition": "0xc350"
+      }
+    },
+    "0000000000000000000000000000000000000009": {
+      "balance": "0x1",
+      "builtin": {
+        "name": "blake2_f",
+        "pricing": {
+          "blake2_f": {
+            "gas_per_round": 1
+          }
+        },
+        "activate_at": "0xc350"
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/cmd/puppeth/wizard_genesis.go b/cmd/puppeth/wizard_genesis.go
index 499f320f6..ab3e2247b 100644
--- a/cmd/puppeth/wizard_genesis.go
+++ b/cmd/puppeth/wizard_genesis.go
@@ -51,6 +51,7 @@ func (w *wizard) makeGenesis() {
 			ByzantiumBlock:      big.NewInt(0),
 			ConstantinopleBlock: big.NewInt(0),
 			PetersburgBlock:     big.NewInt(0),
+			IstanbulBlock:       big.NewInt(0),
 		},
 	}
 	// Figure out which consensus engine to choose
@@ -230,6 +231,10 @@ func (w *wizard) manageGenesis() {
 		fmt.Printf("Which block should Petersburg come into effect? (default = %v)\n", w.conf.Genesis.Config.PetersburgBlock)
 		w.conf.Genesis.Config.PetersburgBlock = w.readDefaultBigInt(w.conf.Genesis.Config.PetersburgBlock)
 
+		fmt.Println()
+		fmt.Printf("Which block should Istanbul come into effect? (default = %v)\n", w.conf.Genesis.Config.IstanbulBlock)
+		w.conf.Genesis.Config.IstanbulBlock = w.readDefaultBigInt(w.conf.Genesis.Config.IstanbulBlock)
+
 		out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", "  ")
 		fmt.Printf("Chain configuration updated:\n\n%s\n", out)
 
@@ -268,7 +273,7 @@ func (w *wizard) manageGenesis() {
 		} else {
 			saveGenesis(folder, w.network, "parity", spec)
 		}
-		// Export the genesis spec used by Harmony (formerly EthereumJ
+		// Export the genesis spec used by Harmony (formerly EthereumJ)
 		saveGenesis(folder, w.network, "harmony", w.conf.Genesis)
 
 	case "3":
@@ -291,7 +296,7 @@ func (w *wizard) manageGenesis() {
 func saveGenesis(folder, network, client string, spec interface{}) {
 	path := filepath.Join(folder, fmt.Sprintf("%s-%s.json", network, client))
 
-	out, _ := json.Marshal(spec)
+	out, _ := json.MarshalIndent(spec, "", "  ")
 	if err := ioutil.WriteFile(path, out, 0644); err != nil {
 		log.Error("Failed to save genesis file", "client", client, "err", err)
 		return
-- 
GitLab