cmd/istanbul, docker, genesis: add docker-compose and quorum flags

This commit is contained in:
mark.lin 2017-11-22 11:59:56 +08:00
parent a72a4b5633
commit 8ff6abd0e7
12 changed files with 855 additions and 20 deletions

View File

@ -99,7 +99,7 @@ seal: 0x000000000000000000000000000000000000000000000000000000000000000000000000
<details>
<summary>Click here to expand</summary>
When `--nodes --verbose` flags are given, a `static-nodes.json` template as well as the validators' node keys, public keys, and addresses are generated. When `--save` flag is given, the generated configs will be saved.
When `--nodes --verbose` flags are given, a `static-nodes.json` template as well as the validators' node keys, public keys, and addresses are generated. When `--docker-compose` is given, a `docker-compose.yml` for the validators is generated. When `--save` flag is given, all generated configs will be saved. Use Quorum when `--quorum` flag is given.
**Note**: the generated `static-nodes.json` template are set with IP `0.0.0.0`, please make according change to match your environment.
@ -201,10 +201,12 @@ DESCRIPTION:
OPTIONS:
--num value Number of validators (default: 0)
--nodes Print static nodes template
--verbose Print validator details
--save Save to files
--num value Number of validators (default: 0)
--nodes Print static nodes template
--verbose Print validator details
--quorum Use quorum
--docker-compose Print docker compose file
--save Save to files
```
</details>

View File

@ -25,13 +25,14 @@ import (
"os"
"path"
"strconv"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/urfave/cli"
istcommon "github.com/getamis/istanbul-tools/common"
"github.com/getamis/istanbul-tools/docker/compose"
"github.com/getamis/istanbul-tools/genesis"
"github.com/urfave/cli"
)
type validatorInfo struct {
@ -57,6 +58,8 @@ var (
numOfValidatorsFlag,
staticNodesFlag,
verboseFlag,
quorumFlag,
dockerComposeFlag,
saveFlag,
},
}
@ -113,12 +116,22 @@ func gen(ctx *cli.Context) error {
}
}
genesis := genesis.New(
var jsonBytes []byte
isQuorum := ctx.Bool(quorumFlag.Name)
g := genesis.New(
genesis.Validators(addrs...),
genesis.Alloc(addrs, new(big.Int).Exp(big.NewInt(10), big.NewInt(50), nil)),
)
jsonBytes, _ := json.MarshalIndent(genesis, "", " ")
jsonBytes, _ = json.MarshalIndent(g, "", " ")
fmt.Println("--Old genesis.json")
fmt.Println(string(jsonBytes))
if isQuorum {
jsonBytes, _ = json.MarshalIndent(genesis.ToQuorum(g, true), "", " ")
} else {
jsonBytes, _ = json.MarshalIndent(g, "", " ")
}
fmt.Println("genesis.json")
fmt.Println(string(jsonBytes))
@ -126,5 +139,31 @@ func gen(ctx *cli.Context) error {
ioutil.WriteFile("genesis.json", jsonBytes, os.ModePerm)
}
if ctx.Bool(dockerComposeFlag.Name) {
fmt.Print("\n\n\n")
compose := compose.New(
"172.16.239",
num,
"bb98a0b6442386d0cdf8a31b267892c1",
nodekeys,
removeSpacesAndLines(jsonBytes),
removeSpacesAndLines(staticNodes),
isQuorum)
fmt.Println("docker-compose.yml")
fmt.Println(compose.String())
if ctx.Bool(saveFlag.Name) {
ioutil.WriteFile("docker-compose.yml", []byte(compose.String()), os.ModePerm)
}
}
return nil
}
func removeSpacesAndLines(b []byte) string {
out := string(b)
out = strings.Replace(out, " ", "", -1)
out = strings.Replace(out, "\t", "", -1)
out = strings.Replace(out, "\n", "", -1)
return out
}

View File

@ -34,6 +34,16 @@ var (
Usage: "Print static nodes template",
}
dockerComposeFlag = cli.BoolFlag{
Name: "docker-compose",
Usage: "Print docker compose file",
}
quorumFlag = cli.BoolFlag{
Name: "quorum",
Usage: "Use Quorum",
}
saveFlag = cli.BoolFlag{
Name: "save",
Usage: "Save to files",

103
docker/compose/istanbul.go Normal file
View File

@ -0,0 +1,103 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package compose
import (
"bytes"
"fmt"
"strings"
"text/template"
"github.com/getamis/istanbul-tools/docker/service"
)
type Compose interface {
String() string
}
type istanbul struct {
IPPrefix string
EthStats *service.EthStats
Services []*service.Validator
}
func New(ipPrefix string, number int, secret string, nodeKeys []string,
genesis string, staticNodes string, quorum bool) Compose {
ist := &istanbul{
IPPrefix: ipPrefix,
EthStats: service.NewEthStats(fmt.Sprintf("%v.9", ipPrefix), secret),
}
ist.init(number, nodeKeys, genesis, staticNodes)
if quorum {
return newQuorum(ist, number)
}
return ist
}
func (ist *istanbul) init(number int, nodeKeys []string, genesis string, staticNodes string) {
for i := 0; i < number; i++ {
s := service.NewValidator(i,
genesis,
nodeKeys[i],
"",
30303+i,
8545+i,
ist.EthStats.Host(),
// from subnet ip 10
fmt.Sprintf("%v.%v", ist.IPPrefix, i+10),
)
staticNodes = strings.Replace(staticNodes, "0.0.0.0", s.IP, 1)
ist.Services = append(ist.Services, s)
}
// update static nodes
for i := range ist.Services {
ist.Services[i].StaticNodes = staticNodes
}
}
func (ist istanbul) String() string {
tmpl, err := template.New("istanbul").Parse(istanbulTemplate)
if err != nil {
fmt.Printf("Failed to parse template, %v", err)
return ""
}
result := new(bytes.Buffer)
err = tmpl.Execute(result, ist)
if err != nil {
fmt.Printf("Failed to render template, %v", err)
return ""
}
return result.String()
}
var istanbulTemplate = `version: '3'
services:
{{ .EthStats }}
{{- range .Services }}
{{ . }}
{{- end }}
networks:
app_net:
driver: bridge
ipam:
driver: default
config:
- subnet: {{ .IPPrefix }}.0/24`

110
docker/compose/quorum.go Normal file
View File

@ -0,0 +1,110 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package compose
import (
"bytes"
"fmt"
"text/template"
"github.com/getamis/istanbul-tools/docker/service"
)
type quorum struct {
*istanbul
Number int
QuorumServices []*service.Quorum
}
func newQuorum(ist *istanbul, number int) Compose {
q := &quorum{
istanbul: ist,
Number: number,
}
q.init()
return q
}
func (q *quorum) init() {
// set constellations
var constellations []*service.Constellation
for i := 0; i < q.Number; i++ {
constellations = append(constellations,
service.NewConstellation(q.Services[i].Identity,
// from subnet ip 100
fmt.Sprintf("%v.%v", q.IPPrefix, i+100),
10000+i,
),
)
}
for i := 0; i < q.Number; i++ {
// set othernodes
var nodes []string
for j := 0; j < q.Number; j++ {
if i != j {
nodes = append(nodes, constellations[j].Host())
}
}
constellations[i].SetOtherNodes(nodes)
// update quorum service
q.QuorumServices = append(q.QuorumServices,
service.NewQuorum(q.Services[i], constellations[i]))
}
}
func (q *quorum) String() string {
tmpl, err := template.New("quorum").Funcs(template.FuncMap(
map[string]interface{}{
"PrintVolumes": func() (result string) {
for i := 0; i < q.Number; i++ {
result += fmt.Sprintf(" \"%v\":\n", i)
}
return
},
})).Parse(quorumTemplate)
if err != nil {
fmt.Printf("Failed to parse template, %v", err)
return ""
}
result := new(bytes.Buffer)
err = tmpl.Execute(result, q)
if err != nil {
fmt.Printf("Failed to render template, %v", err)
return ""
}
return result.String()
}
var quorumTemplate = `version: '3'
services:
{{ .EthStats }}
{{- range .QuorumServices }}
{{ . }}
{{- end }}
networks:
app_net:
driver: bridge
ipam:
driver: default
config:
- subnet: {{ .IPPrefix }}.0/24
volumes:
{{ PrintVolumes }}
`

View File

@ -0,0 +1,110 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package service
import (
"bytes"
"fmt"
"strings"
"text/template"
)
type Constellation struct {
Identity int
Name string
IP string
Port int
OtherNodes string
PublicKey string
PrivateKey string
SocketPath string
ConfigPath string
Folder string
KeyPath string
}
func NewConstellation(identity int, ip string, port int) *Constellation {
folder := "/constellation"
keyPath := fmt.Sprintf("%v/tm", folder)
return &Constellation{
Identity: identity,
Name: fmt.Sprintf("constellation-%v", identity),
IP: ip,
Port: port,
PublicKey: fmt.Sprintf("%v.pub", keyPath),
PrivateKey: fmt.Sprintf("%v.key", keyPath),
SocketPath: fmt.Sprintf("%v.ipc", keyPath),
ConfigPath: fmt.Sprintf("%v.conf", keyPath),
Folder: folder,
KeyPath: keyPath,
}
}
func (c *Constellation) SetOtherNodes(nodes []string) {
c.OtherNodes = strings.Join(nodes, ",")
}
func (c Constellation) Host() string {
return fmt.Sprintf("http://%v:%v/", c.IP, c.Port)
}
func (c Constellation) String() string {
tmpl, err := template.New("constellation").Parse(constellationTemplate)
if err != nil {
fmt.Printf("Failed to parse template, %v", err)
return ""
}
result := new(bytes.Buffer)
err = tmpl.Execute(result, c)
if err != nil {
fmt.Printf("Failed to render template, %v", err)
return ""
}
return result.String()
}
var constellationTemplate = `{{ .Name }}:
hostname: {{ .Name }}
image: quay.io/amis/constellation:latest
ports:
- '{{ .Port }}:{{ .Port }}'
volumes:
- {{ .Identity }}:{{ .Folder }}:z
- .:/tmp/
entrypoint:
- /bin/sh
- -c
- |
mkdir -p {{ .Folder }}
echo "socket=\"{{ .SocketPath }}\"\npublickeys=[\"{{ .PublicKey }}\"]\n" > {{ .ConfigPath }}
constellation-node --generatekeys={{ .KeyPath }}
cp {{ .KeyPath }}.pub /tmp/tm{{ .Identity }}.pub
constellation-node \
--url={{ .Host }} \
--port={{ .Port }} \
--socket={{ .SocketPath }} \
--othernodes={{ .OtherNodes }} \
--publickeys={{ .PublicKey }} \
--privatekeys={{ .PrivateKey }} \
--storage={{ .Folder }} \
--verbosity=4
networks:
app_net:
ipv4_address: {{ .IP }}
restart: always`

View File

@ -0,0 +1,67 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package service
import (
"bytes"
"fmt"
"text/template"
)
type EthStats struct {
Secret string
IP string
}
func NewEthStats(ip string, secret string) *EthStats {
return &EthStats{
IP: ip,
Secret: secret,
}
}
func (c EthStats) Host() string {
return fmt.Sprintf("%v@%v:3000", c.Secret, c.IP)
}
func (c EthStats) String() string {
tmpl, err := template.New("eth_stats").Parse(ethStatsTemplate)
if err != nil {
fmt.Printf("Failed to parse template, %v", err)
return ""
}
result := new(bytes.Buffer)
err = tmpl.Execute(result, c)
if err != nil {
fmt.Printf("Failed to render template, %v", err)
return ""
}
return result.String()
}
var ethStatsTemplate = `eth-stats:
image: quay.io/amis/ethstats:latest
ports:
- '3000:3000'
environment:
- WS_SECRET={{ .Secret }}
restart: always
networks:
app_net:
ipv4_address: {{ .IP }}`

95
docker/service/quorum.go Normal file
View File

@ -0,0 +1,95 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package service
import (
"bytes"
"fmt"
"text/template"
)
type Quorum struct {
*Validator
Constellation *Constellation
}
func NewQuorum(v *Validator, c *Constellation) *Quorum {
return &Quorum{
Validator: v,
Constellation: c,
}
}
func (q Quorum) String() string {
tmpl, err := template.New("quorum").Parse(quorumTemplate)
if err != nil {
fmt.Printf("Failed to parse template, %v", err)
return ""
}
result := new(bytes.Buffer)
err = tmpl.Execute(result, q)
if err != nil {
fmt.Printf("Failed to render template, %v", err)
return ""
}
return result.String()
}
var quorumTemplate = `{{ .Name }}:
hostname: {{ .Name }}
image: quay.io/amis/quorum:feature_istanbul
ports:
- '{{ .Port }}:30303'
- '{{ .RPCPort }}:8545'
volumes:
- {{ .Identity }}:{{ .Constellation.Folder }}:z
depends_on:
- {{ .Constellation.Name }}
environment:
- PRIVATE_CONFIG={{ .Constellation.ConfigPath }}
entrypoint:
- /bin/sh
- -c
- |
mkdir -p /eth/geth
echo '{{ .Genesis }}' > /eth/genesis.json
echo '{{ .StaticNodes }}' > /eth/geth/static-nodes.json
geth --datadir "/eth" init "/eth/genesis.json"
geth \
--identity "{{ .Name }}" \
--rpc \
--rpcaddr "0.0.0.0" \
--rpcport "8545" \
--rpccorsdomain "*" \
--datadir "/eth" \
--port "30303" \
--rpcapi "db,eth,net,web3,istanbul,personal" \
--networkid "2017" \
--nat "any" \
--nodekeyhex "{{ .NodeKey }}" \
--mine \
--debug \
--metrics \
--syncmode "full" \
--ethstats "{{ .Name }}:{{ .EthStats }}" \
--gasprice 0
networks:
app_net:
ipv4_address: {{ .IP }}
restart: always
{{ .Constellation }}`

102
docker/service/validator.go Normal file
View File

@ -0,0 +1,102 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package service
import (
"bytes"
"fmt"
"text/template"
)
type Validator struct {
Identity int
Genesis string
NodeKey string
StaticNodes string
Port int
RPCPort int
IP string
EthStats string
Name string
}
func NewValidator(identity int, genesis string, nodeKey string, staticNodes string, port int, rpcPort int, ethStats string, ip string) *Validator {
return &Validator{
Identity: identity,
Genesis: genesis,
NodeKey: nodeKey,
Port: port,
RPCPort: rpcPort,
EthStats: ethStats,
IP: ip,
Name: fmt.Sprintf("validator-%v", identity),
}
}
func (v Validator) String() string {
tmpl, err := template.New("validator").Parse(validatorTemplate)
if err != nil {
fmt.Printf("Failed to parse template, %v", err)
return ""
}
result := new(bytes.Buffer)
err = tmpl.Execute(result, v)
if err != nil {
fmt.Printf("Failed to render template, %v", err)
return ""
}
return result.String()
}
var validatorTemplate = `{{ .Name }}:
hostname: {{ .Name }}
image: quay.io/amis/geth:latest
ports:
- '{{ .Port }}:30303'
- '{{ .RPCPort }}:8545'
entrypoint:
- /bin/sh
- -c
- |
mkdir -p /eth/geth
echo '{{ .Genesis }}' > /eth/genesis.json
echo '{{ .StaticNodes }}' > /eth/geth/static-nodes.json
geth --datadir "/eth" init "/eth/genesis.json"
geth \
--identity "{{ .Name }}" \
--rpc \
--rpcaddr "0.0.0.0" \
--rpcport "8545" \
--rpccorsdomain "*" \
--datadir "/eth" \
--port "30303" \
--rpcapi "db,eth,net,web3,istanbul,personal" \
--networkid "2017" \
--nat "any" \
--nodekeyhex "{{ .NodeKey }}" \
--mine \
--debug \
--metrics \
--syncmode "full" \
--ethstats "{{ .Name }}:{{ .EthStats }}" \
--gasprice 0
networks:
app_net:
ipv4_address: {{ .IP }}
restart: always`

View File

@ -0,0 +1,116 @@
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
package genesis
import (
"encoding/json"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/getamis/go-ethereum/common/math"
)
var _ = (*genesisSpecMarshaling)(nil)
func (q QuorumGenesis) MarshalJSON() ([]byte, error) {
type QuorumGenesis struct {
Config *QuorumChainConfig `json:"config"`
Nonce math.HexOrDecimal64 `json:"nonce"`
Timestamp math.HexOrDecimal64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
Alloc map[common.UnprefixedAddress]core.GenesisAccount `json:"alloc" gencodec:"required"`
Number math.HexOrDecimal64 `json:"number"`
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
}
var enc QuorumGenesis
enc.Config = q.Config
enc.Nonce = math.HexOrDecimal64(q.Nonce)
enc.Timestamp = math.HexOrDecimal64(q.Timestamp)
enc.ExtraData = q.ExtraData
enc.GasLimit = math.HexOrDecimal64(q.GasLimit)
enc.Difficulty = (*math.HexOrDecimal256)(q.Difficulty)
enc.Mixhash = q.Mixhash
enc.Coinbase = q.Coinbase
if q.Alloc != nil {
enc.Alloc = make(map[common.UnprefixedAddress]core.GenesisAccount, len(q.Alloc))
for k, v := range q.Alloc {
enc.Alloc[common.UnprefixedAddress(k)] = v
}
}
enc.Number = math.HexOrDecimal64(q.Number)
enc.GasUsed = math.HexOrDecimal64(q.GasUsed)
enc.ParentHash = q.ParentHash
return json.Marshal(&enc)
}
func (q *QuorumGenesis) UnmarshalJSON(input []byte) error {
type QuorumGenesis struct {
Config *QuorumChainConfig `json:"config"`
Nonce *math.HexOrDecimal64 `json:"nonce"`
Timestamp *math.HexOrDecimal64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
Mixhash *common.Hash `json:"mixHash"`
Coinbase *common.Address `json:"coinbase"`
Alloc map[common.UnprefixedAddress]core.GenesisAccount `json:"alloc" gencodec:"required"`
Number *math.HexOrDecimal64 `json:"number"`
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
ParentHash *common.Hash `json:"parentHash"`
}
var dec QuorumGenesis
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Config != nil {
q.Config = dec.Config
}
if dec.Nonce != nil {
q.Nonce = uint64(*dec.Nonce)
}
if dec.Timestamp != nil {
q.Timestamp = uint64(*dec.Timestamp)
}
if dec.ExtraData != nil {
q.ExtraData = dec.ExtraData
}
if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for QuorumGenesis")
}
q.GasLimit = uint64(*dec.GasLimit)
if dec.Difficulty == nil {
return errors.New("missing required field 'difficulty' for QuorumGenesis")
}
q.Difficulty = (*big.Int)(dec.Difficulty)
if dec.Mixhash != nil {
q.Mixhash = *dec.Mixhash
}
if dec.Coinbase != nil {
q.Coinbase = *dec.Coinbase
}
if dec.Alloc == nil {
return errors.New("missing required field 'alloc' for QuorumGenesis")
}
q.Alloc = make(core.GenesisAlloc, len(dec.Alloc))
for k, v := range dec.Alloc {
q.Alloc[common.Address(k)] = v
}
if dec.Number != nil {
q.Number = uint64(*dec.Number)
}
if dec.GasUsed != nil {
q.GasUsed = uint64(*dec.GasUsed)
}
if dec.ParentHash != nil {
q.ParentHash = *dec.ParentHash
}
return nil
}

View File

@ -18,11 +18,9 @@ package genesis
import (
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"path/filepath"
"strings"
"time"
"github.com/ethereum/go-ethereum/consensus/istanbul"
@ -84,17 +82,15 @@ func NewFile(isQuorum bool, options ...Option) string {
func Save(dataDir string, genesis *core.Genesis, isQuorum bool) error {
filePath := filepath.Join(dataDir, FileName)
raw, err := json.Marshal(genesis)
var raw []byte
var err error
if isQuorum {
raw, err = json.Marshal(ToQuorum(genesis, true))
} else {
raw, err = json.Marshal(genesis)
}
if err != nil {
return err
}
//Quorum hack: add isQuorum field
if isQuorum {
jsonStr := string(raw)
idx := strings.Index(jsonStr, ",\"istanbul\"")
jsonStr = fmt.Sprintf("%s,\"isQuorum\":true%s", jsonStr[:idx], jsonStr[idx:])
raw = []byte(jsonStr)
}
return ioutil.WriteFile(filePath, raw, 0600)
}

85
genesis/quorum.go Normal file
View File

@ -0,0 +1,85 @@
// Copyright 2017 AMIS Technologies
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package genesis
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/params"
"github.com/getamis/go-ethereum/common/math"
)
//go:generate gencodec -type QuorumGenesis -field-override genesisSpecMarshaling -out gen_quorum_genesis.go
// field type overrides for gencodec
type genesisSpecMarshaling struct {
Nonce math.HexOrDecimal64
Timestamp math.HexOrDecimal64
ExtraData hexutil.Bytes
GasLimit math.HexOrDecimal64
GasUsed math.HexOrDecimal64
Number math.HexOrDecimal64
Difficulty *math.HexOrDecimal256
Alloc map[common.UnprefixedAddress]core.GenesisAccount
}
type QuorumChainConfig struct {
*params.ChainConfig
IsQuorum bool `json:"isQuorum,omitempty"`
}
type QuorumGenesis struct {
Config *QuorumChainConfig `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 core.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"`
}
// ToQuorum converts standard genesis to quorum genesis
func ToQuorum(g *core.Genesis, isQuorum bool) *QuorumGenesis {
return &QuorumGenesis{
Config: &QuorumChainConfig{
ChainConfig: g.Config,
IsQuorum: isQuorum,
},
Nonce: g.Nonce,
Timestamp: g.Timestamp,
ExtraData: g.ExtraData,
GasLimit: g.GasLimit,
Difficulty: g.Difficulty,
Mixhash: g.Mixhash,
Coinbase: g.Coinbase,
Alloc: g.Alloc,
Number: g.Number,
GasUsed: g.GasUsed,
ParentHash: g.ParentHash,
}
}