container, core, tests: add blockchain struct for testing and refactoring

This commit is contained in:
Alan Chen 2017-08-17 18:04:35 +08:00
parent 10a5aa9037
commit a5e020c4fe
9 changed files with 422 additions and 354 deletions

135
container/blockchain.go Normal file
View File

@ -0,0 +1,135 @@
// 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 container
import (
"crypto/ecdsa"
"log"
"os"
"path/filepath"
"github.com/docker/docker/client"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/phayes/freeport"
"github.com/getamis/istanbul-tools/genesis"
)
type Blockchain interface {
Start() error
Stop() error
Validators() []Ethereum
Finalize()
}
func NewBlockchain(numOfValidators int, options ...Option) (bc *blockchain) {
var keys []*ecdsa.PrivateKey
var addrs []common.Address
bc = &blockchain{}
for i := 0; i < numOfValidators; i++ {
key, err := crypto.GenerateKey()
if err != nil {
log.Fatalf("couldn't generate key: " + err.Error())
}
keys = append(keys, key)
addr := crypto.PubkeyToAddress(key.PublicKey)
addrs = append(addrs, addr)
}
setupDir, err := generateRandomDir()
if err != nil {
log.Fatal("Failed to create setup dir", err)
}
err = genesis.Save(setupDir, genesis.New(addrs))
if err != nil {
log.Fatal("Failed to save genesis", err)
}
bc.genesisFile = filepath.Join(setupDir, genesis.FileName)
dockerClient, err := client.NewEnvClient()
if err != nil {
log.Fatalf("Cannot connect to Docker daemon, err: %v", err)
}
for i := 0; i < numOfValidators; i++ {
opts := make([]Option, len(options))
copy(opts, options)
// Host data directory
dataDir, err := generateRandomDir()
if err != nil {
log.Fatal("Failed to create data dir", err)
}
opts = append(opts, HostDataDir(dataDir))
opts = append(opts, HostPort(freeport.GetPort()))
opts = append(opts, HostWebSocketPort(freeport.GetPort()))
opts = append(opts, Key(keys[i]))
geth := NewEthereum(
dockerClient,
opts...,
)
err = geth.Init(bc.genesisFile)
if err != nil {
log.Fatal("Failed to init genesis", err)
}
bc.validators = append(bc.validators, geth)
}
return bc
}
// ----------------------------------------------------------------------------
type blockchain struct {
genesisFile string
validators []Ethereum
}
func (bc *blockchain) Start() error {
for _, v := range bc.validators {
if err := v.Start(); err != nil {
return err
}
}
return nil
}
func (bc *blockchain) Stop() error {
for _, v := range bc.validators {
if err := v.Stop(); err != nil {
return err
}
}
return nil
}
func (bc *blockchain) Finalize() {
os.RemoveAll(filepath.Dir(bc.genesisFile))
}
func (bc *blockchain) Validators() []Ethereum {
return bc.validators
}

View File

@ -14,21 +14,37 @@
// 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 core
package container
import (
"fmt"
"testing"
"time"
)
func TestWriteFile(t *testing.T) {
envs := SetupEnv(4)
err := SetupNodes(envs, NewGenesis(envs))
func TestEthereumBlockchain(t *testing.T) {
chain := NewBlockchain(
4,
ImageRepository("quay.io/amis/geth"),
ImageTag("istanbul_develop"),
DataDir("/data"),
WebSocket(),
WebSocketAddress("0.0.0.0"),
WebSocketAPI("eth,net,web3,personal"),
WebSocketOrigin("*"),
NoDiscover(),
Logging(true),
)
defer chain.Finalize()
err := chain.Start()
if err != nil {
t.Fatal("failed to setup nodes", err)
t.Error(err)
}
defer Teardown(envs)
for _, env := range envs {
fmt.Println(fmt.Sprintf("%s%d%s%s", "geth ID:", env.GethID, ", dataDir:", env.DataDir))
time.Sleep(5 * time.Second)
err = chain.Stop()
if err != nil {
t.Error(err)
}
}

View File

@ -18,7 +18,9 @@ package container
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
@ -32,9 +34,10 @@ import (
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/getamis/go-ethereum/cmd/utils"
"github.com/getamis/go-ethereum/ethclient"
"github.com/getamis/istanbul-tools/core"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/getamis/istanbul-tools/genesis"
)
const (
@ -86,7 +89,6 @@ func NewEthereum(c *client.Client, options ...Option) *ethereum {
type ethereum struct {
ok bool
flags []string
hostDataDir string
dataDir string
port string
rpcPort string
@ -97,26 +99,35 @@ type ethereum struct {
imageRepository string
imageTag string
key *ecdsa.PrivateKey
logging bool
client *client.Client
}
func (eth *ethereum) Init(genesisFile string) error {
if err := saveNodeKey(eth.key, eth.dataDir); err != nil {
log.Fatal("Failed to save nodekey", err)
return err
}
binds := []string{
genesisFile + ":" + filepath.Join("/", genesis.FileName),
}
if eth.dataDir != "" {
binds = append(binds, eth.dataDir+":"+utils.DataDirFlag.Value.Value)
}
resp, err := eth.client.ContainerCreate(context.Background(),
&container.Config{
Image: eth.Image(),
Cmd: []string{
"init",
"--" + utils.DataDirFlag.Name,
eth.dataDir,
filepath.Join("/", core.GenesisFile),
utils.DataDirFlag.Value.Value,
filepath.Join("/", genesis.FileName),
},
},
&container.HostConfig{
Binds: []string{
genesisFile + ":" + filepath.Join("/", core.GenesisFile),
eth.hostDataDir + ":" + eth.dataDir,
},
Binds: binds,
}, nil, "")
if err != nil {
log.Printf("Failed to create container, err: %v", err)
@ -158,8 +169,9 @@ func (eth *ethereum) Start() error {
portBindings := nat.PortMap{}
if eth.port != "" {
exposedPorts[nat.Port(eth.port)] = struct{}{}
portBindings[nat.Port(eth.port)] = []nat.PortBinding{
port := fmt.Sprintf("%d", utils.ListenPortFlag.Value)
exposedPorts[nat.Port(port)] = struct{}{}
portBindings[nat.Port(port)] = []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: eth.port,
@ -168,8 +180,9 @@ func (eth *ethereum) Start() error {
}
if eth.rpcPort != "" {
exposedPorts[nat.Port(eth.rpcPort)] = struct{}{}
portBindings[nat.Port(eth.rpcPort)] = []nat.PortBinding{
port := fmt.Sprintf("%d", utils.RPCPortFlag.Value)
exposedPorts[nat.Port(port)] = struct{}{}
portBindings[nat.Port(port)] = []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: eth.rpcPort,
@ -178,8 +191,9 @@ func (eth *ethereum) Start() error {
}
if eth.wsPort != "" {
exposedPorts[nat.Port(eth.wsPort)] = struct{}{}
portBindings[nat.Port(eth.wsPort)] = []nat.PortBinding{
port := fmt.Sprintf("%d", utils.WSPortFlag.Value)
exposedPorts[nat.Port(port)] = struct{}{}
portBindings[nat.Port(port)] = []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: eth.wsPort,
@ -187,6 +201,11 @@ func (eth *ethereum) Start() error {
}
}
binds := []string{}
if eth.dataDir != "" {
binds = append(binds, eth.dataDir+":"+utils.DataDirFlag.Value.Value)
}
resp, err := eth.client.ContainerCreate(context.Background(),
&container.Config{
Hostname: "geth-" + eth.hostName,
@ -195,9 +214,7 @@ func (eth *ethereum) Start() error {
ExposedPorts: exposedPorts,
},
&container.HostConfig{
Binds: []string{
eth.hostDataDir + ":" + eth.dataDir,
},
Binds: binds,
PortBindings: portBindings,
}, nil, "")
if err != nil {
@ -247,6 +264,8 @@ func (eth *ethereum) Stop() error {
return err
}
os.RemoveAll(eth.dataDir)
return eth.client.ContainerRemove(context.Background(), eth.containerID,
types.ContainerRemoveOptions{
Force: true,
@ -289,7 +308,6 @@ func (eth *ethereum) NewClient() *ethclient.Client {
}
client, err := ethclient.Dial(scheme + eth.Host() + ":" + port)
if err != nil {
log.Printf("Failed to dial to geth, err: %v", err)
return nil
}
return client

View File

@ -17,54 +17,43 @@
package container
import (
"fmt"
"path/filepath"
"testing"
"github.com/getamis/istanbul-tools/core"
"github.com/docker/docker/client"
"github.com/phayes/freeport"
)
func TestEthereumContainer(t *testing.T) {
envs := core.SetupEnv(1)
defer core.Teardown(envs)
err := core.SetupNodes(envs, core.NewGenesis(envs))
dockerClient, err := client.NewEnvClient()
if err != nil {
t.Error(err)
}
for _, env := range envs {
geth := NewEthereum(
env.Client,
ImageRepository("quay.io/amis/geth"),
ImageTag("istanbul_develop"),
HostDataDir(env.DataDir),
DataDir("/data"),
Port(fmt.Sprintf("%d", env.P2PPort)),
WebSocket(),
WebSocketAddress("0.0.0.0"),
WebSocketAPI("eth,net,web3,personal"),
WebSocketPort(fmt.Sprintf("%d", env.RpcPort)),
WebSocketOrigin("*"),
NoDiscover(),
)
geth := NewEthereum(
dockerClient,
ImageRepository("quay.io/amis/geth"),
ImageTag("istanbul_develop"),
DataDir("/data"),
HostPort(freeport.GetPort()),
WebSocket(),
WebSocketAddress("0.0.0.0"),
WebSocketAPI("eth,net,web3,personal"),
HostWebSocketPort(freeport.GetPort()),
WebSocketOrigin("*"),
NoDiscover(),
)
err := geth.Init(filepath.Join(env.DataDir, core.GenesisFile))
if err != nil {
t.Error(err)
}
err = geth.Start()
if err != nil {
t.Error(err)
}
err = geth.Start()
if err != nil {
t.Error(err)
}
if !geth.Running() {
t.Error("geth should be running")
}
if !geth.Running() {
t.Error("geth should be running")
}
err = geth.Stop()
if err != nil {
t.Error(err)
}
err = geth.Stop()
if err != nil {
t.Error(err)
}
}

View File

@ -17,6 +17,7 @@
package container
import (
"crypto/ecdsa"
"fmt"
"github.com/getamis/go-ethereum/cmd/utils"
@ -44,7 +45,25 @@ func HostName(hostName string) Option {
func HostDataDir(path string) Option {
return func(eth *ethereum) {
eth.hostDataDir = path
eth.dataDir = path
}
}
func HostPort(port int) Option {
return func(eth *ethereum) {
eth.port = fmt.Sprintf("%d", port)
}
}
func HostRPCPort(port int) Option {
return func(eth *ethereum) {
eth.rpcPort = fmt.Sprintf("%d", port)
}
}
func HostWebSocketPort(port int) Option {
return func(eth *ethereum) {
eth.wsPort = fmt.Sprintf("%d", port)
}
}
@ -56,11 +75,20 @@ func Logging(enabled bool) Option {
// ----------------------------------------------------------------------------
func Key(key *ecdsa.PrivateKey) Option {
return func(eth *ethereum) {
eth.key = key
}
}
func DataDir(dir string) Option {
return func(eth *ethereum) {
utils.DataDirFlag.Value = utils.DirectoryString{
Value: dir,
}
eth.flags = append(eth.flags, "--"+utils.DataDirFlag.Name)
eth.flags = append(eth.flags, dir)
eth.dataDir = dir
}
}
@ -133,11 +161,11 @@ func NoDiscover() Option {
}
}
func Port(port string) Option {
func Port(port int) Option {
return func(eth *ethereum) {
utils.ListenPortFlag.Value = port
eth.flags = append(eth.flags, "--"+utils.ListenPortFlag.Name)
eth.flags = append(eth.flags, port)
eth.port = port
eth.flags = append(eth.flags, fmt.Sprintf("%d", port))
}
}
@ -161,11 +189,11 @@ func RPCAPI(apis string) Option {
}
}
func RPCPort(port string) Option {
func RPCPort(port int) Option {
return func(eth *ethereum) {
utils.RPCPortFlag.Value = port
eth.flags = append(eth.flags, "--"+utils.RPCPortFlag.Name)
eth.flags = append(eth.flags, port)
eth.rpcPort = port
eth.flags = append(eth.flags, fmt.Sprintf("%d", port))
}
}
@ -189,11 +217,11 @@ func WebSocketAPI(apis string) Option {
}
}
func WebSocketPort(port string) Option {
func WebSocketPort(port int) Option {
return func(eth *ethereum) {
utils.WSPortFlag.Value = port
eth.flags = append(eth.flags, "--"+utils.WSPortFlag.Name)
eth.flags = append(eth.flags, port)
eth.wsPort = port
eth.flags = append(eth.flags, fmt.Sprintf("%d", port))
}
}

64
container/utils.go Normal file
View File

@ -0,0 +1,64 @@
// 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 container
import (
"crypto/ecdsa"
"fmt"
"log"
"os"
"path/filepath"
"github.com/getamis/go-ethereum/crypto"
uuid "github.com/satori/go.uuid"
)
const (
defaultLocalDir = "/tmp/gdata"
clientIdentifier = "geth"
nodekeyFileName = "nodekey"
)
func generateRandomDir() (string, error) {
err := os.MkdirAll(filepath.Join(defaultLocalDir), 0700)
if err != nil {
log.Fatal(err)
}
instanceDir := filepath.Join(defaultLocalDir, fmt.Sprintf("%s-%s", clientIdentifier, uuid.NewV4().String()))
if err := os.MkdirAll(instanceDir, 0700); err != nil {
log.Println(fmt.Sprintf("Failed to create instance dir: %v", err))
return "", err
}
return instanceDir, nil
}
func saveNodeKey(key *ecdsa.PrivateKey, dataDir string) error {
keyDir := filepath.Join(dataDir, clientIdentifier)
if err := os.MkdirAll(keyDir, 0700); err != nil {
log.Println(fmt.Sprintf("Failed to create key dir: %v", err))
return err
}
keyfile := filepath.Join(keyDir, nodekeyFileName)
if err := crypto.SaveECDSA(keyfile, key); err != nil {
log.Println(fmt.Sprintf("Failed to persist node key: %v", err))
return err
}
return nil
}

View File

@ -1,233 +0,0 @@
// 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 core
import (
"crypto/ecdsa"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"math/big"
"net"
"net/url"
"os"
"path/filepath"
"time"
"github.com/docker/docker/client"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/istanbul"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params"
"github.com/getamis/istanbul-tools/cmd/istanbul/extradata"
"github.com/phayes/freeport"
"github.com/satori/go.uuid"
)
const (
defaultLocalDir = "/tmp/gdata"
datadirPrivateKey = "nodekey"
clientIdentifier = "geth"
staticNodeJson = "static-nodes.json"
GenesisFile = "genesis.json"
)
type Env struct {
GethID int
P2PPort uint16
RpcPort uint16
DataDir string
Key *ecdsa.PrivateKey
Client *client.Client
}
// TODO: need to refactor with ethereum/container
func (e *Env) Address() common.Address {
addrs := toAddress([]*Env{e})
return addrs[0]
}
// TODO: need to refactor with ethereum/container
func (e *Env) NodeURL() string {
nodeID := discover.PubkeyID(&e.Key.PublicKey)
daemonHost := e.Client.DaemonHost()
url, err := url.Parse(daemonHost)
if err != nil {
log.Fatalf("Failed to parse daemon host, err: %v", err)
}
var host string
if url.Scheme == "unix" {
host = "127.0.0.1"
} else {
host, _, err = net.SplitHostPort(url.Host)
if err != nil {
log.Fatalf("Failed to split host and port, err: %v", err)
}
}
return discover.NewNode(nodeID, net.ParseIP(host), 0, e.P2PPort).String()
}
func Teardown(envs []*Env) {
for _, env := range envs {
os.RemoveAll(env.DataDir)
}
}
func SetupEnv(numbers int) []*Env {
envs := make([]*Env, numbers)
rpcPort := uint16(freeport.GetPort())
p2pPort := uint16(freeport.GetPort())
for i := 0; i < len(envs); i++ {
client, err := client.NewEnvClient()
if err != nil {
log.Fatalf("Cannot connect to Docker daemon, err: %v", err)
}
key, err := crypto.GenerateKey()
if err != nil {
log.Fatalf("couldn't generate key: " + err.Error())
}
envs[i] = &Env{
GethID: i,
P2PPort: p2pPort,
RpcPort: rpcPort,
DataDir: filepath.Join(defaultLocalDir, fmt.Sprintf("%s%s", clientIdentifier, uuid.NewV4().String())),
Key: key,
Client: client,
}
rpcPort = uint16(freeport.GetPort())
p2pPort = uint16(freeport.GetPort())
}
return envs
}
func SetupNodes(envs []*Env, g *core.Genesis) error {
nodes := toStaticNodes(envs)
for _, env := range envs {
if err := saveNodeKey(env.DataDir, env.Key); err != nil {
log.Fatalf("Failed to save node key")
}
if err := saveStaticNode(env.DataDir, nodes); err != nil {
return err
}
if err := saveGenesis(env.DataDir, g); err != nil {
return err
}
}
return nil
}
func NewGenesis(envs []*Env) *core.Genesis {
extraData, err := extradata.Encode("0x00", toAddress(envs))
if err != nil {
log.Fatalf("Failed to generate genesis, err:%s", err)
}
return &core.Genesis{
Timestamp: uint64(time.Now().Unix()),
GasLimit: 4700000,
Difficulty: big.NewInt(1),
Alloc: make(core.GenesisAlloc),
Config: &params.ChainConfig{
HomesteadBlock: big.NewInt(1),
EIP150Block: big.NewInt(2),
EIP155Block: big.NewInt(3),
EIP158Block: big.NewInt(3),
Istanbul: &params.IstanbulConfig{
ProposerPolicy: uint64(istanbul.DefaultConfig.ProposerPolicy),
Epoch: istanbul.DefaultConfig.Epoch,
},
},
Mixhash: types.IstanbulDigest,
ExtraData: hexutil.MustDecode(extraData),
}
}
func saveNodeKey(dataDir string, key *ecdsa.PrivateKey) error {
err := os.MkdirAll(dataDir, 0700)
if err != nil {
log.Fatal(err)
}
keyDir := filepath.Join(dataDir, clientIdentifier)
if err := os.MkdirAll(keyDir, 0700); err != nil {
log.Println(fmt.Sprintf("Failed to create key dir: %v", err))
return err
}
keyfile := filepath.Join(keyDir, datadirPrivateKey)
if err := crypto.SaveECDSA(keyfile, key); err != nil {
log.Println(fmt.Sprintf("Failed to persist node key: %v", err))
return err
}
return nil
}
func saveStaticNode(dataDir string, nodes []string) error {
filePath := filepath.Join(dataDir, clientIdentifier)
keyPath := filepath.Join(filePath, staticNodeJson)
raw, err := json.Marshal(nodes)
if err != nil {
return err
}
return ioutil.WriteFile(keyPath, raw, 0600)
}
func saveGenesis(dataDir string, genesis *core.Genesis) error {
filePath := filepath.Join(dataDir, GenesisFile)
raw, err := json.Marshal(genesis)
if err != nil {
return err
}
return ioutil.WriteFile(filePath, raw, 0600)
}
func toStaticNodes(envs []*Env) []string {
nodes := make([]string, len(envs))
for i, env := range envs {
nodes[i] = env.NodeURL()
}
return nodes
}
func toAddress(envs []*Env) []common.Address {
addrs := make([]common.Address, len(envs))
for i, env := range envs {
addrs[i] = crypto.PubkeyToAddress(env.Key.PublicKey)
}
return addrs
}

75
genesis/genesis.go Normal file
View File

@ -0,0 +1,75 @@
// 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 (
"encoding/json"
"io/ioutil"
"math/big"
"path/filepath"
"time"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/istanbul"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/getamis/istanbul-tools/cmd/istanbul/extradata"
)
const (
FileName = "genesis.json"
)
func New(addrs []common.Address) *core.Genesis {
extraData, err := extradata.Encode("0x00", addrs)
if err != nil {
log.Fatalf("Failed to generate genesis, err:%s", err)
}
return &core.Genesis{
Timestamp: uint64(time.Now().Unix()),
GasLimit: 4700000,
Difficulty: big.NewInt(1),
Alloc: make(core.GenesisAlloc),
Config: &params.ChainConfig{
HomesteadBlock: big.NewInt(1),
EIP150Block: big.NewInt(2),
EIP155Block: big.NewInt(3),
EIP158Block: big.NewInt(3),
Istanbul: &params.IstanbulConfig{
ProposerPolicy: uint64(istanbul.DefaultConfig.ProposerPolicy),
Epoch: istanbul.DefaultConfig.Epoch,
},
},
Mixhash: types.IstanbulDigest,
ExtraData: hexutil.MustDecode(extraData),
}
}
func Save(dataDir string, genesis *core.Genesis) error {
filePath := filepath.Join(dataDir, FileName)
raw, err := json.Marshal(genesis)
if err != nil {
return err
}
return ioutil.WriteFile(filePath, raw, 0600)
}

View File

@ -18,74 +18,50 @@ package tests
import (
"context"
"fmt"
"math/big"
"path/filepath"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/getamis/istanbul-tools/container"
"github.com/getamis/istanbul-tools/core"
)
// var geths []container.Ethereum
var _ = Describe("4 validators Istanbul", func() {
const (
numberOfValidators = 4
)
var (
envs []*core.Env
geths []container.Ethereum
blockchain container.Blockchain
)
BeforeSuite(func() {
envs = core.SetupEnv(numberOfValidators)
err := core.SetupNodes(envs, core.NewGenesis(envs))
Expect(err).To(BeNil())
blockchain = container.NewBlockchain(
numberOfValidators,
container.ImageRepository("quay.io/amis/geth"),
container.ImageTag("istanbul_develop"),
container.DataDir("/data"),
container.WebSocket(),
container.WebSocketAddress("0.0.0.0"),
container.WebSocketAPI("eth,net,web3,personal,miner"),
container.WebSocketOrigin("*"),
container.NAT("any"),
container.NoDiscover(),
container.Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
container.Mine(),
container.Logging(true),
)
for _, env := range envs {
geth := container.NewEthereum(
env.Client,
container.ImageRepository("quay.io/amis/geth"),
container.ImageTag("istanbul_develop"),
container.HostDataDir(env.DataDir),
container.DataDir("/data"),
container.Port(fmt.Sprintf("%d", env.P2PPort)),
container.WebSocket(),
container.WebSocketAddress("0.0.0.0"),
container.WebSocketAPI("eth,net,web3,personal,miner"),
container.WebSocketPort(fmt.Sprintf("%d", env.RpcPort)),
container.WebSocketOrigin("*"),
container.NAT("any"),
container.NoDiscover(),
container.Etherbase("1a9afb711302c5f83b5902843d1c007a1a137632"),
container.Mine(),
container.Logging(true),
)
err := geth.Init(filepath.Join(env.DataDir, core.GenesisFile))
Expect(err).To(BeNil())
geths = append(geths, geth)
err = geth.Start()
Expect(err).To(BeNil())
}
Expect(blockchain.Start()).To(BeNil())
})
AfterSuite(func() {
for _, geth := range geths {
geth.Stop()
}
core.Teardown(envs)
Expect(blockchain.Stop()).To(BeNil())
blockchain.Finalize()
})
It("Blockchain creation", func() {
for _, geth := range geths {
for _, geth := range blockchain.Validators() {
client := geth.NewClient()
Expect(client).NotTo(BeNil())