aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/puppeth
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2018-11-25 06:22:25 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-12-03 18:34:41 +0800
commit8698fbabf6c7811e8eec6e84512510e9c9a4eb45 (patch)
treebfd4570f18e332e2d51a140aa331ab9507bd2983 /cmd/puppeth
parenta3fd415c0f983cae35c329d97e0b6707561daef6 (diff)
downloaddexon-8698fbabf6c7811e8eec6e84512510e9c9a4eb45.tar.gz
dexon-8698fbabf6c7811e8eec6e84512510e9c9a4eb45.tar.zst
dexon-8698fbabf6c7811e8eec6e84512510e9c9a4eb45.zip
cmd/puppeth: implement chainspec converters
Diffstat (limited to 'cmd/puppeth')
-rw-r--r--cmd/puppeth/genesis.go386
-rw-r--r--cmd/puppeth/module_dashboard.go2
-rw-r--r--cmd/puppeth/puppeth.go32
-rw-r--r--cmd/puppeth/puppeth_test.go91
-rw-r--r--cmd/puppeth/testdata/stureby_aleth.json112
-rw-r--r--cmd/puppeth/testdata/stureby_geth.json47
-rw-r--r--cmd/puppeth/testdata/stureby_parity.json181
-rw-r--r--cmd/puppeth/wizard.go22
-rw-r--r--cmd/puppeth/wizard_genesis.go67
9 files changed, 779 insertions, 161 deletions
diff --git a/cmd/puppeth/genesis.go b/cmd/puppeth/genesis.go
index 5f39a889d..83212a126 100644
--- a/cmd/puppeth/genesis.go
+++ b/cmd/puppeth/genesis.go
@@ -20,35 +20,41 @@ import (
"encoding/binary"
"errors"
"math"
+ "math/big"
+ "strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+ math2 "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/params"
)
-// cppEthereumGenesisSpec represents the genesis specification format used by the
+// alethGenesisSpec represents the genesis specification format used by the
// C++ Ethereum implementation.
-type cppEthereumGenesisSpec struct {
+type alethGenesisSpec struct {
SealEngine string `json:"sealEngine"`
Params struct {
- AccountStartNonce hexutil.Uint64 `json:"accountStartNonce"`
- HomesteadForkBlock hexutil.Uint64 `json:"homesteadForkBlock"`
- EIP150ForkBlock hexutil.Uint64 `json:"EIP150ForkBlock"`
- EIP158ForkBlock hexutil.Uint64 `json:"EIP158ForkBlock"`
- ByzantiumForkBlock hexutil.Uint64 `json:"byzantiumForkBlock"`
- ConstantinopleForkBlock hexutil.Uint64 `json:"constantinopleForkBlock"`
- NetworkID hexutil.Uint64 `json:"networkID"`
- ChainID hexutil.Uint64 `json:"chainID"`
- MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
- MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
- MaxGasLimit hexutil.Uint64 `json:"maxGasLimit"`
- GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"`
- MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
- DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
- DurationLimit *hexutil.Big `json:"durationLimit"`
- BlockReward *hexutil.Big `json:"blockReward"`
+ 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""`
} `json:"params"`
Genesis struct {
@@ -62,57 +68,68 @@ type cppEthereumGenesisSpec struct {
GasLimit hexutil.Uint64 `json:"gasLimit"`
} `json:"genesis"`
- Accounts map[common.Address]*cppEthereumGenesisSpecAccount `json:"accounts"`
+ Accounts map[common.UnprefixedAddress]*alethGenesisSpecAccount `json:"accounts"`
}
-// cppEthereumGenesisSpecAccount is the prefunded genesis account and/or precompiled
+// alethGenesisSpecAccount is the prefunded genesis account and/or precompiled
// contract definition.
-type cppEthereumGenesisSpecAccount struct {
- Balance *hexutil.Big `json:"balance"`
- Nonce uint64 `json:"nonce,omitempty"`
- Precompiled *cppEthereumGenesisSpecBuiltin `json:"precompiled,omitempty"`
+type alethGenesisSpecAccount struct {
+ Balance *math2.HexOrDecimal256 `json:"balance"`
+ Nonce uint64 `json:"nonce,omitempty"`
+ Precompiled *alethGenesisSpecBuiltin `json:"precompiled,omitempty"`
}
-// cppEthereumGenesisSpecBuiltin is the precompiled contract definition.
-type cppEthereumGenesisSpecBuiltin struct {
- Name string `json:"name,omitempty"`
- StartingBlock hexutil.Uint64 `json:"startingBlock,omitempty"`
- Linear *cppEthereumGenesisSpecLinearPricing `json:"linear,omitempty"`
+// alethGenesisSpecBuiltin is the precompiled contract definition.
+type alethGenesisSpecBuiltin struct {
+ Name string `json:"name,omitempty"`
+ StartingBlock hexutil.Uint64 `json:"startingBlock,omitempty"`
+ Linear *alethGenesisSpecLinearPricing `json:"linear,omitempty"`
}
-type cppEthereumGenesisSpecLinearPricing struct {
+type alethGenesisSpecLinearPricing struct {
Base uint64 `json:"base"`
Word uint64 `json:"word"`
}
-// newCppEthereumGenesisSpec converts a go-ethereum genesis block into a Parity specific
+// newAlethGenesisSpec converts a go-ethereum genesis block into a Aleth-specific
// chain specification format.
-func newCppEthereumGenesisSpec(network string, genesis *core.Genesis) (*cppEthereumGenesisSpec, error) {
- // Only ethash is currently supported between go-ethereum and cpp-ethereum
+func newAlethGenesisSpec(network string, genesis *core.Genesis) (*alethGenesisSpec, error) {
+ // Only ethash is currently supported between go-ethereum and aleth
if genesis.Config.Ethash == nil {
return nil, errors.New("unsupported consensus engine")
}
- // Reconstruct the chain spec in Parity's format
- spec := &cppEthereumGenesisSpec{
+ // Reconstruct the chain spec in Aleth format
+ spec := &alethGenesisSpec{
SealEngine: "Ethash",
}
+ // Some defaults
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())
- spec.Params.ByzantiumForkBlock = (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64())
- spec.Params.ConstantinopleForkBlock = (hexutil.Uint64)(math.MaxUint64)
+
+ // Byzantium
+ if num := genesis.Config.ByzantiumBlock; num != nil {
+ spec.setByzantium(num)
+ }
+ // Constantinople
+ if num := genesis.Config.ConstantinopleBlock; num != nil {
+ spec.setConstantinople(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)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
- spec.Params.MaxGasLimit = (hexutil.Uint64)(math.MaxUint64)
+ spec.Params.MaxGasLimit = (hexutil.Uint64)(math.MaxInt64)
spec.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
- spec.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
- spec.Params.GasLimitBoundDivisor = (hexutil.Uint64)(params.GasLimitBoundDivisor)
- spec.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
+ spec.Params.DifficultyBoundDivisor = (*math2.HexOrDecimal256)(params.DifficultyBoundDivisor)
+ spec.Params.GasLimitBoundDivisor = (math2.HexOrDecimal64)(params.GasLimitBoundDivisor)
+ spec.Params.DurationLimit = (*math2.HexOrDecimal256)(params.DurationLimit)
spec.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
spec.Genesis.Nonce = (hexutil.Bytes)(make([]byte, 8))
@@ -126,77 +143,104 @@ func newCppEthereumGenesisSpec(network string, genesis *core.Genesis) (*cppEther
spec.Genesis.ExtraData = (hexutil.Bytes)(genesis.ExtraData)
spec.Genesis.GasLimit = (hexutil.Uint64)(genesis.GasLimit)
- spec.Accounts = make(map[common.Address]*cppEthereumGenesisSpecAccount)
for address, account := range genesis.Alloc {
- spec.Accounts[address] = &cppEthereumGenesisSpecAccount{
- Balance: (*hexutil.Big)(account.Balance),
- Nonce: account.Nonce,
- }
+ spec.setAccount(address, account)
}
- spec.Accounts[common.BytesToAddress([]byte{1})].Precompiled = &cppEthereumGenesisSpecBuiltin{
- Name: "ecrecover", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 3000},
- }
- spec.Accounts[common.BytesToAddress([]byte{2})].Precompiled = &cppEthereumGenesisSpecBuiltin{
- Name: "sha256", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 60, Word: 12},
+
+ spec.setPrecompile(1, &alethGenesisSpecBuiltin{Name: "ecrecover",
+ Linear: &alethGenesisSpecLinearPricing{Base: 3000}})
+ spec.setPrecompile(2, &alethGenesisSpecBuiltin{Name: "sha256",
+ Linear: &alethGenesisSpecLinearPricing{Base: 60, Word: 12}})
+ spec.setPrecompile(3, &alethGenesisSpecBuiltin{Name: "ripemd160",
+ Linear: &alethGenesisSpecLinearPricing{Base: 600, Word: 120}})
+ spec.setPrecompile(4, &alethGenesisSpecBuiltin{Name: "identity",
+ Linear: &alethGenesisSpecLinearPricing{Base: 15, Word: 3}})
+ if genesis.Config.ByzantiumBlock != nil {
+ spec.setPrecompile(5, &alethGenesisSpecBuiltin{Name: "modexp",
+ StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64())})
+ spec.setPrecompile(6, &alethGenesisSpecBuiltin{Name: "alt_bn128_G1_add",
+ StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()),
+ Linear: &alethGenesisSpecLinearPricing{Base: 500}})
+ spec.setPrecompile(7, &alethGenesisSpecBuiltin{Name: "alt_bn128_G1_mul",
+ StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()),
+ Linear: &alethGenesisSpecLinearPricing{Base: 40000}})
+ spec.setPrecompile(8, &alethGenesisSpecBuiltin{Name: "alt_bn128_pairing_product",
+ StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64())})
}
- spec.Accounts[common.BytesToAddress([]byte{3})].Precompiled = &cppEthereumGenesisSpecBuiltin{
- Name: "ripemd160", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 600, Word: 120},
+ return spec, nil
+}
+
+func (spec *alethGenesisSpec) setPrecompile(address byte, data *alethGenesisSpecBuiltin) {
+ if spec.Accounts == nil {
+ spec.Accounts = make(map[common.UnprefixedAddress]*alethGenesisSpecAccount)
}
- spec.Accounts[common.BytesToAddress([]byte{4})].Precompiled = &cppEthereumGenesisSpecBuiltin{
- Name: "identity", Linear: &cppEthereumGenesisSpecLinearPricing{Base: 15, Word: 3},
+ spec.Accounts[common.UnprefixedAddress(common.BytesToAddress([]byte{address}))].Precompiled = data
+}
+
+func (spec *alethGenesisSpec) setAccount(address common.Address, account core.GenesisAccount) {
+ if spec.Accounts == nil {
+ spec.Accounts = make(map[common.UnprefixedAddress]*alethGenesisSpecAccount)
}
- if genesis.Config.ByzantiumBlock != nil {
- spec.Accounts[common.BytesToAddress([]byte{5})].Precompiled = &cppEthereumGenesisSpecBuiltin{
- Name: "modexp", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()),
- }
- spec.Accounts[common.BytesToAddress([]byte{6})].Precompiled = &cppEthereumGenesisSpecBuiltin{
- Name: "alt_bn128_G1_add", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()), Linear: &cppEthereumGenesisSpecLinearPricing{Base: 500},
- }
- spec.Accounts[common.BytesToAddress([]byte{7})].Precompiled = &cppEthereumGenesisSpecBuiltin{
- Name: "alt_bn128_G1_mul", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()), Linear: &cppEthereumGenesisSpecLinearPricing{Base: 40000},
- }
- spec.Accounts[common.BytesToAddress([]byte{8})].Precompiled = &cppEthereumGenesisSpecBuiltin{
- Name: "alt_bn128_pairing_product", StartingBlock: (hexutil.Uint64)(genesis.Config.ByzantiumBlock.Uint64()),
- }
+
+ a, exist := spec.Accounts[common.UnprefixedAddress(address)]
+ if !exist {
+ a = &alethGenesisSpecAccount{}
+ spec.Accounts[common.UnprefixedAddress(address)] = a
}
- return spec, nil
+ a.Balance = (*math2.HexOrDecimal256)(account.Balance)
+ a.Nonce = account.Nonce
+
+}
+
+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"`
- Engine struct {
+ Name string `json:"name"`
+ Datadir string `json:"dataDir"`
+ Engine struct {
Ethash struct {
Params struct {
- MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
- DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
- DurationLimit *hexutil.Big `json:"durationLimit"`
- BlockReward *hexutil.Big `json:"blockReward"`
- HomesteadTransition uint64 `json:"homesteadTransition"`
- EIP150Transition uint64 `json:"eip150Transition"`
- EIP160Transition uint64 `json:"eip160Transition"`
- EIP161abcTransition uint64 `json:"eip161abcTransition"`
- EIP161dTransition uint64 `json:"eip161dTransition"`
- EIP649Reward *hexutil.Big `json:"eip649Reward"`
- EIP100bTransition uint64 `json:"eip100bTransition"`
- EIP649Transition uint64 `json:"eip649Transition"`
+ MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
+ DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
+ DurationLimit *hexutil.Big `json:"durationLimit"`
+ BlockReward map[string]string `json:"blockReward"`
+ DifficultyBombDelays map[string]string `json:"difficultyBombDelays"`
+ HomesteadTransition hexutil.Uint64 `json:"homesteadTransition"`
+ EIP100bTransition hexutil.Uint64 `json:"eip100bTransition"`
} `json:"params"`
} `json:"Ethash"`
} `json:"engine"`
Params struct {
- MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
- MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
- GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"`
- NetworkID hexutil.Uint64 `json:"networkID"`
- MaxCodeSize uint64 `json:"maxCodeSize"`
- EIP155Transition uint64 `json:"eip155Transition"`
- EIP98Transition uint64 `json:"eip98Transition"`
- EIP86Transition uint64 `json:"eip86Transition"`
- EIP140Transition uint64 `json:"eip140Transition"`
- EIP211Transition uint64 `json:"eip211Transition"`
- EIP214Transition uint64 `json:"eip214Transition"`
- EIP658Transition uint64 `json:"eip658Transition"`
+ 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"`
} `json:"params"`
Genesis struct {
@@ -215,22 +259,22 @@ type parityChainSpec struct {
GasLimit hexutil.Uint64 `json:"gasLimit"`
} `json:"genesis"`
- Nodes []string `json:"nodes"`
- Accounts map[common.Address]*parityChainSpecAccount `json:"accounts"`
+ Nodes []string `json:"nodes"`
+ Accounts map[common.UnprefixedAddress]*parityChainSpecAccount `json:"accounts"`
}
// parityChainSpecAccount is the prefunded genesis account and/or precompiled
// contract definition.
type parityChainSpecAccount struct {
- Balance *hexutil.Big `json:"balance"`
- Nonce uint64 `json:"nonce,omitempty"`
+ Balance math2.HexOrDecimal256 `json:"balance"`
+ Nonce math2.HexOrDecimal64 `json:"nonce,omitempty"`
Builtin *parityChainSpecBuiltin `json:"builtin,omitempty"`
}
// parityChainSpecBuiltin is the precompiled contract definition.
type parityChainSpecBuiltin struct {
Name string `json:"name,omitempty"`
- ActivateAt uint64 `json:"activate_at,omitempty"`
+ ActivateAt math2.HexOrDecimal64 `json:"activate_at,omitempty"`
Pricing *parityChainSpecPricing `json:"pricing,omitempty"`
}
@@ -265,34 +309,51 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
}
// Reconstruct the chain spec in Parity's format
spec := &parityChainSpec{
- Name: network,
- Nodes: bootnodes,
+ Name: network,
+ Nodes: bootnodes,
+ Datadir: strings.ToLower(network),
}
+ spec.Engine.Ethash.Params.BlockReward = make(map[string]string)
+ spec.Engine.Ethash.Params.DifficultyBombDelays = make(map[string]string)
+ // Frontier
spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
spec.Engine.Ethash.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
- spec.Engine.Ethash.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
- spec.Engine.Ethash.Params.HomesteadTransition = genesis.Config.HomesteadBlock.Uint64()
- spec.Engine.Ethash.Params.EIP150Transition = genesis.Config.EIP150Block.Uint64()
- spec.Engine.Ethash.Params.EIP160Transition = genesis.Config.EIP155Block.Uint64()
- spec.Engine.Ethash.Params.EIP161abcTransition = genesis.Config.EIP158Block.Uint64()
- spec.Engine.Ethash.Params.EIP161dTransition = genesis.Config.EIP158Block.Uint64()
- spec.Engine.Ethash.Params.EIP649Reward = (*hexutil.Big)(ethash.ByzantiumBlockReward)
- spec.Engine.Ethash.Params.EIP100bTransition = genesis.Config.ByzantiumBlock.Uint64()
- spec.Engine.Ethash.Params.EIP649Transition = genesis.Config.ByzantiumBlock.Uint64()
+ spec.Engine.Ethash.Params.BlockReward["0x0"] = hexutil.EncodeBig(ethash.FrontierBlockReward)
+
+ // Homestead
+ spec.Engine.Ethash.Params.HomesteadTransition = hexutil.Uint64(genesis.Config.HomesteadBlock.Uint64())
+
+ // Tangerine Whistle : 150
+ // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-608.md
+ spec.Params.EIP150Transition = hexutil.Uint64(genesis.Config.EIP150Block.Uint64())
+
+ // Spurious Dragon: 155, 160, 161, 170
+ // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-607.md
+ spec.Params.EIP155Transition = hexutil.Uint64(genesis.Config.EIP155Block.Uint64())
+ spec.Params.EIP160Transition = hexutil.Uint64(genesis.Config.EIP155Block.Uint64())
+ spec.Params.EIP161abcTransition = hexutil.Uint64(genesis.Config.EIP158Block.Uint64())
+ spec.Params.EIP161dTransition = hexutil.Uint64(genesis.Config.EIP158Block.Uint64())
+ // Byzantium
+ if num := genesis.Config.ByzantiumBlock; num != nil {
+ spec.setByzantium(num)
+ }
+ // Constantinople
+ if num := genesis.Config.ConstantinopleBlock; num != nil {
+ spec.setConstantinople(num)
+ }
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
- spec.Params.GasLimitBoundDivisor = (hexutil.Uint64)(params.GasLimitBoundDivisor)
+ spec.Params.GasLimitBoundDivisor = (math2.HexOrDecimal64)(params.GasLimitBoundDivisor)
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
+ spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
spec.Params.MaxCodeSize = params.MaxCodeSize
- spec.Params.EIP155Transition = genesis.Config.EIP155Block.Uint64()
- spec.Params.EIP98Transition = math.MaxUint64
- spec.Params.EIP86Transition = math.MaxUint64
- spec.Params.EIP140Transition = genesis.Config.ByzantiumBlock.Uint64()
- spec.Params.EIP211Transition = genesis.Config.ByzantiumBlock.Uint64()
- spec.Params.EIP214Transition = genesis.Config.ByzantiumBlock.Uint64()
- spec.Params.EIP658Transition = genesis.Config.ByzantiumBlock.Uint64()
+ // geth has it set from zero
+ spec.Params.MaxCodeSizeTransition = 0
+
+ // Disable this one
+ spec.Params.EIP98Transition = math.MaxInt64
spec.Genesis.Seal.Ethereum.Nonce = (hexutil.Bytes)(make([]byte, 8))
binary.LittleEndian.PutUint64(spec.Genesis.Seal.Ethereum.Nonce[:], genesis.Nonce)
@@ -305,42 +366,77 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
spec.Genesis.ExtraData = (hexutil.Bytes)(genesis.ExtraData)
spec.Genesis.GasLimit = (hexutil.Uint64)(genesis.GasLimit)
- spec.Accounts = make(map[common.Address]*parityChainSpecAccount)
+ spec.Accounts = make(map[common.UnprefixedAddress]*parityChainSpecAccount)
for address, account := range genesis.Alloc {
- spec.Accounts[address] = &parityChainSpecAccount{
- Balance: (*hexutil.Big)(account.Balance),
- Nonce: account.Nonce,
+ bal := math2.HexOrDecimal256(*account.Balance)
+
+ spec.Accounts[common.UnprefixedAddress(address)] = &parityChainSpecAccount{
+ Balance: bal,
+ Nonce: math2.HexOrDecimal64(account.Nonce),
}
}
- spec.Accounts[common.BytesToAddress([]byte{1})].Builtin = &parityChainSpecBuiltin{
- Name: "ecrecover", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 3000}},
- }
- spec.Accounts[common.BytesToAddress([]byte{2})].Builtin = &parityChainSpecBuiltin{
+ spec.setPrecompile(1, &parityChainSpecBuiltin{Name: "ecrecover",
+ Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 3000}}})
+
+ spec.setPrecompile(2, &parityChainSpecBuiltin{
Name: "sha256", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 60, Word: 12}},
- }
- spec.Accounts[common.BytesToAddress([]byte{3})].Builtin = &parityChainSpecBuiltin{
+ })
+ spec.setPrecompile(3, &parityChainSpecBuiltin{
Name: "ripemd160", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 600, Word: 120}},
- }
- spec.Accounts[common.BytesToAddress([]byte{4})].Builtin = &parityChainSpecBuiltin{
+ })
+ spec.setPrecompile(4, &parityChainSpecBuiltin{
Name: "identity", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 15, Word: 3}},
- }
+ })
if genesis.Config.ByzantiumBlock != nil {
- spec.Accounts[common.BytesToAddress([]byte{5})].Builtin = &parityChainSpecBuiltin{
- Name: "modexp", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{ModExp: &parityChainSpecModExpPricing{Divisor: 20}},
- }
- spec.Accounts[common.BytesToAddress([]byte{6})].Builtin = &parityChainSpecBuiltin{
- Name: "alt_bn128_add", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 500}},
- }
- spec.Accounts[common.BytesToAddress([]byte{7})].Builtin = &parityChainSpecBuiltin{
- Name: "alt_bn128_mul", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 40000}},
- }
- spec.Accounts[common.BytesToAddress([]byte{8})].Builtin = &parityChainSpecBuiltin{
- Name: "alt_bn128_pairing", ActivateAt: genesis.Config.ByzantiumBlock.Uint64(), Pricing: &parityChainSpecPricing{AltBnPairing: &parityChainSpecAltBnPairingPricing{Base: 100000, Pair: 80000}},
- }
+ blnum := math2.HexOrDecimal64(genesis.Config.ByzantiumBlock.Uint64())
+ spec.setPrecompile(5, &parityChainSpecBuiltin{
+ Name: "modexp", ActivateAt: blnum, Pricing: &parityChainSpecPricing{ModExp: &parityChainSpecModExpPricing{Divisor: 20}},
+ })
+ spec.setPrecompile(6, &parityChainSpecBuiltin{
+ Name: "alt_bn128_add", ActivateAt: blnum, Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 500}},
+ })
+ spec.setPrecompile(7, &parityChainSpecBuiltin{
+ Name: "alt_bn128_mul", ActivateAt: blnum, Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 40000}},
+ })
+ spec.setPrecompile(8, &parityChainSpecBuiltin{
+ Name: "alt_bn128_pairing", ActivateAt: blnum, Pricing: &parityChainSpecPricing{AltBnPairing: &parityChainSpecAltBnPairingPricing{Base: 100000, Pair: 80000}},
+ })
}
return spec, nil
}
+func (spec *parityChainSpec) setPrecompile(address byte, data *parityChainSpecBuiltin) {
+ if spec.Accounts == nil {
+ spec.Accounts = make(map[common.UnprefixedAddress]*parityChainSpecAccount)
+ }
+ a := common.UnprefixedAddress(common.BytesToAddress([]byte{address}))
+ if _, exist := spec.Accounts[a]; !exist {
+ spec.Accounts[a] = &parityChainSpecAccount{}
+ }
+ spec.Accounts[a].Builtin = data
+}
+
+func (spec *parityChainSpec) setByzantium(num *big.Int) {
+ spec.Engine.Ethash.Params.BlockReward[hexutil.EncodeBig(num)] = hexutil.EncodeBig(ethash.ByzantiumBlockReward)
+ spec.Engine.Ethash.Params.DifficultyBombDelays[hexutil.EncodeBig(num)] = hexutil.EncodeUint64(3000000)
+ n := hexutil.Uint64(num.Uint64())
+ spec.Engine.Ethash.Params.EIP100bTransition = n
+ spec.Params.EIP140Transition = n
+ spec.Params.EIP211Transition = n
+ spec.Params.EIP214Transition = n
+ spec.Params.EIP658Transition = n
+}
+
+func (spec *parityChainSpec) setConstantinople(num *big.Int) {
+ spec.Engine.Ethash.Params.BlockReward[hexutil.EncodeBig(num)] = hexutil.EncodeBig(ethash.ConstantinopleBlockReward)
+ spec.Engine.Ethash.Params.DifficultyBombDelays[hexutil.EncodeBig(num)] = hexutil.EncodeUint64(2000000)
+ n := hexutil.Uint64(num.Uint64())
+ spec.Params.EIP145Transition = n
+ spec.Params.EIP1014Transition = n
+ spec.Params.EIP1052Transition = n
+ spec.Params.EIP1283Transition = n
+}
+
// pyEthereumGenesisSpec represents the genesis specification format used by the
// Python Ethereum implementation.
type pyEthereumGenesisSpec struct {
diff --git a/cmd/puppeth/module_dashboard.go b/cmd/puppeth/module_dashboard.go
index d22bd8110..cb3ed6e71 100644
--- a/cmd/puppeth/module_dashboard.go
+++ b/cmd/puppeth/module_dashboard.go
@@ -640,7 +640,7 @@ func deployDashboard(client *sshClient, network string, conf *config, config *da
files[filepath.Join(workdir, network+".json")] = genesis
if conf.Genesis.Config.Ethash != nil {
- cppSpec, err := newCppEthereumGenesisSpec(network, conf.Genesis)
+ cppSpec, err := newAlethGenesisSpec(network, conf.Genesis)
if err != nil {
return nil, err
}
diff --git a/cmd/puppeth/puppeth.go b/cmd/puppeth/puppeth.go
index df3fff51b..3af1751ea 100644
--- a/cmd/puppeth/puppeth.go
+++ b/cmd/puppeth/puppeth.go
@@ -18,11 +18,15 @@
package main
import (
+ "encoding/json"
+ "io/ioutil"
"math/rand"
"os"
"strings"
"time"
+ "github.com/ethereum/go-ethereum/cmd/utils"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/log"
"gopkg.in/urfave/cli.v1"
)
@@ -43,6 +47,14 @@ func main() {
Usage: "log level to emit to the screen",
},
}
+ app.Commands = []cli.Command{
+ cli.Command{
+ Action: utils.MigrateFlags(convert),
+ Name: "convert",
+ Usage: "Convert from geth genesis into chainspecs for other nodes.",
+ ArgsUsage: "<geth-genesis.json>",
+ },
+ }
app.Action = func(c *cli.Context) error {
// Set up the logger to print everything and the random generator
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int("loglevel")), log.StreamHandler(os.Stdout, log.TerminalFormat(true))))
@@ -58,3 +70,23 @@ func main() {
}
app.Run(os.Args)
}
+
+func convert(ctx *cli.Context) error {
+ // Ensure we have a source genesis
+ log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stdout, log.TerminalFormat(true))))
+ if len(ctx.Args()) != 1 {
+ utils.Fatalf("No geth genesis provided")
+ }
+ blob, err := ioutil.ReadFile(ctx.Args().First())
+ if err != nil {
+ utils.Fatalf("Could not read file: %v", err)
+ }
+
+ var genesis core.Genesis
+ if err := json.Unmarshal(blob, &genesis); err != nil {
+ utils.Fatalf("Failed parsing genesis: %v", err)
+ }
+ basename := strings.TrimRight(ctx.Args().First(), ".json")
+ convertGenesis(&genesis, basename, basename, []string{})
+ return nil
+}
diff --git a/cmd/puppeth/puppeth_test.go b/cmd/puppeth/puppeth_test.go
new file mode 100644
index 000000000..ae0752d54
--- /dev/null
+++ b/cmd/puppeth/puppeth_test.go
@@ -0,0 +1,91 @@
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/ethereum/go-ethereum/core"
+)
+
+func TestConverter_AlethStureby(t *testing.T) {
+ blob, err := ioutil.ReadFile("testdata/stureby_geth.json")
+ if err != nil {
+ t.Fatalf("could not read file: %v", err)
+ }
+ var genesis core.Genesis
+ if err := json.Unmarshal(blob, &genesis); err != nil {
+ t.Fatalf("failed parsing genesis: %v", err)
+ }
+ spec, err := newAlethGenesisSpec("stureby", &genesis)
+ if err != nil {
+ t.Fatalf("failed creating chainspec: %v", err)
+ }
+
+ expBlob, err := ioutil.ReadFile("testdata/stureby_aleth.json")
+ if err != nil {
+ t.Fatalf("could not read file: %v", err)
+ }
+ expspec := &alethGenesisSpec{}
+ if err := json.Unmarshal(expBlob, expspec); err != nil {
+ t.Fatalf("failed parsing genesis: %v", err)
+ }
+ if !reflect.DeepEqual(expspec, spec) {
+ t.Errorf("chainspec mismatch")
+ c := spew.ConfigState{
+ DisablePointerAddresses: true,
+ SortKeys: true,
+ }
+ exp := strings.Split(c.Sdump(expspec), "\n")
+ got := strings.Split(c.Sdump(spec), "\n")
+ for i := 0; i < len(exp) && i < len(got); i++ {
+ if exp[i] != got[i] {
+ fmt.Printf("got: %v\nexp: %v\n", exp[i], got[i])
+ }
+ }
+ }
+}
+
+func TestConverter_ParityStureby(t *testing.T) {
+ blob, err := ioutil.ReadFile("testdata/stureby_geth.json")
+ if err != nil {
+ t.Fatalf("could not read file: %v", err)
+ }
+ var genesis core.Genesis
+ if err := json.Unmarshal(blob, &genesis); err != nil {
+ t.Fatalf("failed parsing genesis: %v", err)
+ }
+ spec, err := newParityChainSpec("Stureby", &genesis, []string{})
+ if err != nil {
+ t.Fatalf("failed creating chainspec: %v", err)
+ }
+
+ expBlob, err := ioutil.ReadFile("testdata/stureby_parity.json")
+ if err != nil {
+ t.Fatalf("could not read file: %v", err)
+ }
+ expspec := &parityChainSpec{}
+ if err := json.Unmarshal(expBlob, expspec); err != nil {
+ t.Fatalf("failed parsing genesis: %v", err)
+ }
+ expspec.Nodes = []string{}
+
+ if !reflect.DeepEqual(expspec, spec) {
+ t.Errorf("chainspec mismatch")
+ c := spew.ConfigState{
+ DisablePointerAddresses: true,
+ SortKeys: true,
+ }
+ exp := strings.Split(c.Sdump(expspec), "\n")
+ got := strings.Split(c.Sdump(spec), "\n")
+ for i := 0; i < len(exp) && i < len(got); i++ {
+ if exp[i] != got[i] {
+ fmt.Printf("got: %v\nexp: %v\n", exp[i], got[i])
+ }
+ }
+ }
+}
diff --git a/cmd/puppeth/testdata/stureby_aleth.json b/cmd/puppeth/testdata/stureby_aleth.json
new file mode 100644
index 000000000..1ef1d8ae1
--- /dev/null
+++ b/cmd/puppeth/testdata/stureby_aleth.json
@@ -0,0 +1,112 @@
+{
+ "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
+ },
+ "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
+ }
+ }
+ },
+ "0000000000000000000000000000000000000002":{
+ "balance":"1",
+ "precompiled":{
+ "name":"sha256",
+ "linear":{
+ "base":60,
+ "word":12
+ }
+ }
+ },
+ "0000000000000000000000000000000000000003":{
+ "balance":"1",
+ "precompiled":{
+ "name":"ripemd160",
+ "linear":{
+ "base":600,
+ "word":120
+ }
+ }
+ },
+ "0000000000000000000000000000000000000004":{
+ "balance":"1",
+ "precompiled":{
+ "name":"identity",
+ "linear":{
+ "base":15,
+ "word":3
+ }
+ }
+ },
+ "0000000000000000000000000000000000000005":{
+ "balance":"1",
+ "precompiled":{
+ "name":"modexp",
+ "startingBlock":"0x7530"
+ }
+ },
+ "0000000000000000000000000000000000000006":{
+ "balance":"1",
+ "precompiled":{
+ "name":"alt_bn128_G1_add",
+ "startingBlock":"0x7530",
+ "linear":{
+ "base":500,
+ "word":0
+ }
+ }
+ },
+ "0000000000000000000000000000000000000007":{
+ "balance":"1",
+ "precompiled":{
+ "name":"alt_bn128_G1_mul",
+ "startingBlock":"0x7530",
+ "linear":{
+ "base":40000,
+ "word":0
+ }
+ }
+ },
+ "0000000000000000000000000000000000000008":{
+ "balance":"1",
+ "precompiled":{
+ "name":"alt_bn128_pairing_product",
+ "startingBlock":"0x7530"
+ }
+ }
+ }
+}
diff --git a/cmd/puppeth/testdata/stureby_geth.json b/cmd/puppeth/testdata/stureby_geth.json
new file mode 100644
index 000000000..c8c3b3c95
--- /dev/null
+++ b/cmd/puppeth/testdata/stureby_geth.json
@@ -0,0 +1,47 @@
+{
+ "config": {
+ "ethash":{},
+ "chainId": 314158,
+ "homesteadBlock": 10000,
+ "eip150Block": 15000,
+ "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "eip155Block": 23000,
+ "eip158Block": 23000,
+ "byzantiumBlock": 30000,
+ "constantinopleBlock": 40000
+ },
+ "nonce": "0x0",
+ "timestamp": "0x59a4e76d",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "extraData": "0x0000000000000000000000000000000000000000000000000000000b4dc0ffee",
+ "gasLimit": "0x47b760",
+ "difficulty": "0x20000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "coinbase": "0x0000000000000000000000000000000000000000",
+ "alloc": {
+ "0000000000000000000000000000000000000001": {
+ "balance": "0x01"
+ },
+ "0000000000000000000000000000000000000002": {
+ "balance": "0x01"
+ },
+ "0000000000000000000000000000000000000003": {
+ "balance": "0x01"
+ },
+ "0000000000000000000000000000000000000004": {
+ "balance": "0x01"
+ },
+ "0000000000000000000000000000000000000005": {
+ "balance": "0x01"
+ },
+ "0000000000000000000000000000000000000006": {
+ "balance": "0x01"
+ },
+ "0000000000000000000000000000000000000007": {
+ "balance": "0x01"
+ },
+ "0000000000000000000000000000000000000008": {
+ "balance": "0x01"
+ }
+ }
+}
diff --git a/cmd/puppeth/testdata/stureby_parity.json b/cmd/puppeth/testdata/stureby_parity.json
new file mode 100644
index 000000000..f3fa8386a
--- /dev/null
+++ b/cmd/puppeth/testdata/stureby_parity.json
@@ -0,0 +1,181 @@
+{
+ "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"
+ }
+ }
+ }
+ },
+ "params":{
+ "accountStartNonce":"0x0",
+ "maximumExtraDataSize":"0x20",
+ "gasLimitBoundDivisor":"0x400",
+ "minGasLimit":"0x1388",
+ "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"
+ },
+ "genesis":{
+ "seal":{
+ "ethereum":{
+ "nonce":"0x0000000000000000",
+ "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000"
+ }
+ },
+ "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
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000002":{
+ "balance":"1",
+ "nonce":"0",
+ "builtin":{
+ "name":"sha256",
+ "pricing":{
+ "linear":{
+ "base":60,
+ "word":12
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000003":{
+ "balance":"1",
+ "nonce":"0",
+ "builtin":{
+ "name":"ripemd160",
+ "pricing":{
+ "linear":{
+ "base":600,
+ "word":120
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000004":{
+ "balance":"1",
+ "nonce":"0",
+ "builtin":{
+ "name":"identity",
+ "pricing":{
+ "linear":{
+ "base":15,
+ "word":3
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000005":{
+ "balance":"1",
+ "nonce":"0",
+ "builtin":{
+ "name":"modexp",
+ "activate_at":"0x7530",
+ "pricing":{
+ "modexp":{
+ "divisor":20
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000006":{
+ "balance":"1",
+ "nonce":"0",
+ "builtin":{
+ "name":"alt_bn128_add",
+ "activate_at":"0x7530",
+ "pricing":{
+ "linear":{
+ "base":500,
+ "word":0
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000007":{
+ "balance":"1",
+ "nonce":"0",
+ "builtin":{
+ "name":"alt_bn128_mul",
+ "activate_at":"0x7530",
+ "pricing":{
+ "linear":{
+ "base":40000,
+ "word":0
+ }
+ }
+ }
+ },
+ "0000000000000000000000000000000000000008":{
+ "balance":"1",
+ "nonce":"0",
+ "builtin":{
+ "name":"alt_bn128_pairing",
+ "activate_at":"0x7530",
+ "pricing":{
+ "alt_bn128_pairing":{
+ "base":100000,
+ "pair":80000
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/cmd/puppeth/wizard.go b/cmd/puppeth/wizard.go
index b88a61de7..42fc125e5 100644
--- a/cmd/puppeth/wizard.go
+++ b/cmd/puppeth/wizard.go
@@ -104,6 +104,28 @@ func (w *wizard) readString() string {
}
}
+// readYesNo reads a yes or no from stdin, returning boolean true for yes
+func (w *wizard) readYesNo(def bool) bool {
+ for {
+ fmt.Printf("> ")
+ text, err := w.in.ReadString('\n')
+ if err != nil {
+ log.Crit("Failed to read user input", "err", err)
+ }
+ text = strings.ToLower(strings.TrimSpace(text))
+ if text == "y" || text == "yes" {
+ return true
+ }
+ if text == "n" || text == "no" {
+ return false
+ }
+ if len(text) == 0 {
+ return def
+ }
+ fmt.Println("Valid answers: y, yes, n, no or leave empty for default")
+ }
+}
+
// readDefaultString reads a single line from stdin, trimming if from spaces. If
// an empty line is entered, the default value is returned.
func (w *wizard) readDefaultString(def string) string {
diff --git a/cmd/puppeth/wizard_genesis.go b/cmd/puppeth/wizard_genesis.go
index 6c4cd571f..681a387df 100644
--- a/cmd/puppeth/wizard_genesis.go
+++ b/cmd/puppeth/wizard_genesis.go
@@ -114,9 +114,13 @@ func (w *wizard) makeGenesis() {
}
break
}
- // Add a batch of precompile balances to avoid them getting deleted
- for i := int64(0); i < 256; i++ {
- genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)}
+ fmt.Println()
+ fmt.Println("Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)")
+ if w.readYesNo(true) {
+ // Add a batch of precompile balances to avoid them getting deleted
+ for i := int64(0); i < 256; i++ {
+ genesis.Alloc[common.BigToAddress(big.NewInt(i))] = core.GenesisAccount{Balance: big.NewInt(1)}
+ }
}
// Query the user for some custom extras
fmt.Println()
@@ -136,47 +140,57 @@ func (w *wizard) manageGenesis() {
// Figure out whether to modify or export the genesis
fmt.Println()
fmt.Println(" 1. Modify existing fork rules")
- fmt.Println(" 2. Export genesis configuration")
+ fmt.Println(" 2. Export genesis configurations")
fmt.Println(" 3. Remove genesis configuration")
choice := w.read()
- switch {
- case choice == "1":
+ switch choice {
+ case "1":
// Fork rule updating requested, iterate over each fork
fmt.Println()
fmt.Printf("Which block should Homestead come into effect? (default = %v)\n", w.conf.Genesis.Config.HomesteadBlock)
w.conf.Genesis.Config.HomesteadBlock = w.readDefaultBigInt(w.conf.Genesis.Config.HomesteadBlock)
fmt.Println()
- fmt.Printf("Which block should EIP150 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP150Block)
+ fmt.Printf("Which block should EIP150 (Tangerine Whistle) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP150Block)
w.conf.Genesis.Config.EIP150Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP150Block)
fmt.Println()
- fmt.Printf("Which block should EIP155 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP155Block)
+ fmt.Printf("Which block should EIP155 (Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP155Block)
w.conf.Genesis.Config.EIP155Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP155Block)
fmt.Println()
- fmt.Printf("Which block should EIP158 come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP158Block)
+ fmt.Printf("Which block should EIP158/161 (also Spurious Dragon) come into effect? (default = %v)\n", w.conf.Genesis.Config.EIP158Block)
w.conf.Genesis.Config.EIP158Block = w.readDefaultBigInt(w.conf.Genesis.Config.EIP158Block)
fmt.Println()
fmt.Printf("Which block should Byzantium come into effect? (default = %v)\n", w.conf.Genesis.Config.ByzantiumBlock)
w.conf.Genesis.Config.ByzantiumBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ByzantiumBlock)
+ fmt.Println()
+ fmt.Printf("Which block should Constantinople come into effect? (default = %v)\n", w.conf.Genesis.Config.ByzantiumBlock)
+ w.conf.Genesis.Config.ConstantinopleBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ConstantinopleBlock)
+
out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", " ")
fmt.Printf("Chain configuration updated:\n\n%s\n", out)
- case choice == "2":
+ case "2":
// Save whatever genesis configuration we currently have
fmt.Println()
- fmt.Printf("Which file to save the genesis into? (default = %s.json)\n", w.network)
+ fmt.Printf("Which base filename to save the genesis specifications into? (default = %s)\n", w.network)
out, _ := json.MarshalIndent(w.conf.Genesis, "", " ")
- if err := ioutil.WriteFile(w.readDefaultString(fmt.Sprintf("%s.json", w.network)), out, 0644); err != nil {
+ basename := w.readDefaultString(fmt.Sprintf("%s.json", w.network))
+
+ gethJson := fmt.Sprintf("%s.json", basename)
+ if err := ioutil.WriteFile((gethJson), out, 0644); err != nil {
log.Error("Failed to save genesis file", "err", err)
}
- log.Info("Exported existing genesis block")
+ log.Info("Saved geth genesis as %v", gethJson)
+ if err := convertGenesis(w.conf.Genesis, basename, w.network, w.conf.bootnodes); err != nil {
+ log.Error("Conversion failed", "err", err)
+ }
- case choice == "3":
+ case "3":
// Make sure we don't have any services running
if len(w.conf.servers()) > 0 {
log.Error("Genesis reset requires all services and servers torn down")
@@ -186,8 +200,31 @@ func (w *wizard) manageGenesis() {
w.conf.Genesis = nil
w.conf.flush()
-
default:
log.Error("That's not something I can do")
}
}
+
+func saveGenesis(basename, client string, spec interface{}) {
+ filename := fmt.Sprintf("%s-%s.json", basename, client)
+ out, _ := json.Marshal(spec)
+ if err := ioutil.WriteFile(filename, out, 0644); err != nil {
+ log.Error("failed to save genesis file", "client", client, "err", err)
+ }
+ log.Info("saved chainspec", "client", client, "filename", filename)
+}
+
+func convertGenesis(genesis *core.Genesis, basename string, network string, bootnodes []string) error {
+ if spec, err := newAlethGenesisSpec(network, genesis); err == nil {
+ saveGenesis(basename, "aleth", spec)
+ } else {
+ log.Error("failed to create chain spec", "client", "aleth", "err", err)
+ }
+ if spec, err := newParityChainSpec(network, genesis, []string{}); err == nil {
+ saveGenesis(basename, "parity", spec)
+ } else {
+ log.Error("failed to create chain spec", "client", "parity", "err", err)
+ }
+ saveGenesis(basename, "harmony", genesis)
+ return nil
+}