| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | // Copyright 2017 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of go-ethereum. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum 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 General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2017-10-19 13:59:02 +03:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"math/rand" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"text/template" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 13:59:02 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/log" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // nodeDockerfile is the Dockerfile required to run an Ethereum node. | 
					
						
							|  |  |  | var nodeDockerfile = ` | 
					
						
							| 
									
										
										
										
											2017-09-05 16:06:36 +03:00
										 |  |  | FROM ethereum/client-go:latest | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ADD genesis.json /genesis.json | 
					
						
							|  |  |  | {{if .Unlock}} | 
					
						
							|  |  |  | 	ADD signer.json /signer.json | 
					
						
							|  |  |  | 	ADD signer.pass /signer.pass | 
					
						
							|  |  |  | {{end}} | 
					
						
							|  |  |  | RUN \ | 
					
						
							| 
									
										
										
										
											2018-04-23 15:23:56 +03:00
										 |  |  |   echo 'geth --cache 512 init /genesis.json' > geth.sh && \{{if .Unlock}} | 
					
						
							|  |  |  | 	echo 'mkdir -p /root/.ethereum/keystore/ && cp /signer.json /root/.ethereum/keystore/' >> geth.sh && \{{end}} | 
					
						
							| 
									
										
										
										
											2018-08-29 12:21:12 +03:00
										 |  |  | 	echo $'exec geth --networkid {{.NetworkID}} --cache 512 --port {{.Port}} --maxpeers {{.Peers}} {{.LightFlag}} --ethstats \'{{.Ethstats}}\' {{if .Bootnodes}}--bootnodes {{.Bootnodes}}{{end}} {{if .Etherbase}}--miner.etherbase {{.Etherbase}} --mine --miner.threads 1{{end}} {{if .Unlock}}--unlock 0 --password /signer.pass --mine{{end}} --miner.gastarget {{.GasTarget}} --miner.gaslimit {{.GasLimit}} --miner.gasprice {{.GasPrice}}' >> geth.sh | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-23 15:23:56 +03:00
										 |  |  | ENTRYPOINT ["/bin/sh", "geth.sh"] | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | ` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // nodeComposefile is the docker-compose.yml file required to deploy and maintain | 
					
						
							|  |  |  | // an Ethereum node (bootnode or miner for now). | 
					
						
							|  |  |  | var nodeComposefile = ` | 
					
						
							|  |  |  | version: '2' | 
					
						
							|  |  |  | services: | 
					
						
							|  |  |  |   {{.Type}}: | 
					
						
							|  |  |  |     build: . | 
					
						
							|  |  |  |     image: {{.Network}}/{{.Type}} | 
					
						
							|  |  |  |     ports: | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  |       - "{{.Port}}:{{.Port}}" | 
					
						
							|  |  |  |       - "{{.Port}}:{{.Port}}/udp" | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  |     volumes: | 
					
						
							| 
									
										
										
										
											2017-10-19 17:50:34 +03:00
										 |  |  |       - {{.Datadir}}:/root/.ethereum{{if .Ethashdir}} | 
					
						
							|  |  |  |       - {{.Ethashdir}}:/root/.ethash{{end}} | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  |     environment: | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  |       - PORT={{.Port}}/tcp | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  |       - TOTAL_PEERS={{.TotalPeers}} | 
					
						
							|  |  |  |       - LIGHT_PEERS={{.LightPeers}} | 
					
						
							|  |  |  |       - STATS_NAME={{.Ethstats}} | 
					
						
							|  |  |  |       - MINER_NAME={{.Etherbase}} | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  |       - GAS_TARGET={{.GasTarget}} | 
					
						
							| 
									
										
										
										
											2018-08-29 12:21:12 +03:00
										 |  |  |       - GAS_LIMIT={{.GasLimit}} | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  |       - GAS_PRICE={{.GasPrice}} | 
					
						
							| 
									
										
										
										
											2017-07-17 20:38:40 +03:00
										 |  |  |     logging: | 
					
						
							|  |  |  |       driver: "json-file" | 
					
						
							|  |  |  |       options: | 
					
						
							|  |  |  |         max-size: "1m" | 
					
						
							|  |  |  |         max-file: "10" | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  |     restart: always | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // deployNode deploys a new Ethereum node container to a remote machine via SSH, | 
					
						
							|  |  |  | // docker and docker-compose. If an instance with the specified network name | 
					
						
							|  |  |  | // already exists there, it will be overwritten! | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | func deployNode(client *sshClient, network string, bootnodes []string, config *nodeInfos, nocache bool) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	kind := "sealnode" | 
					
						
							|  |  |  | 	if config.keyJSON == "" && config.etherbase == "" { | 
					
						
							|  |  |  | 		kind = "bootnode" | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 		bootnodes = make([]string, 0) | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Generate the content to upload to the server | 
					
						
							|  |  |  | 	workdir := fmt.Sprintf("%d", rand.Int63()) | 
					
						
							|  |  |  | 	files := make(map[string][]byte) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lightFlag := "" | 
					
						
							|  |  |  | 	if config.peersLight > 0 { | 
					
						
							|  |  |  | 		lightFlag = fmt.Sprintf("--lightpeers=%d --lightserv=50", config.peersLight) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	dockerfile := new(bytes.Buffer) | 
					
						
							|  |  |  | 	template.Must(template.New("").Parse(nodeDockerfile)).Execute(dockerfile, map[string]interface{}{ | 
					
						
							|  |  |  | 		"NetworkID": config.network, | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 		"Port":      config.port, | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 		"Peers":     config.peersTotal, | 
					
						
							|  |  |  | 		"LightFlag": lightFlag, | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 		"Bootnodes": strings.Join(bootnodes, ","), | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 		"Ethstats":  config.ethstats, | 
					
						
							|  |  |  | 		"Etherbase": config.etherbase, | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 		"GasTarget": uint64(1000000 * config.gasTarget), | 
					
						
							| 
									
										
										
										
											2018-08-29 12:21:12 +03:00
										 |  |  | 		"GasLimit":  uint64(1000000 * config.gasLimit), | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 		"GasPrice":  uint64(1000000000 * config.gasPrice), | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 		"Unlock":    config.keyJSON != "", | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	files[filepath.Join(workdir, "Dockerfile")] = dockerfile.Bytes() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	composefile := new(bytes.Buffer) | 
					
						
							|  |  |  | 	template.Must(template.New("").Parse(nodeComposefile)).Execute(composefile, map[string]interface{}{ | 
					
						
							|  |  |  | 		"Type":       kind, | 
					
						
							|  |  |  | 		"Datadir":    config.datadir, | 
					
						
							| 
									
										
										
										
											2017-10-19 17:50:34 +03:00
										 |  |  | 		"Ethashdir":  config.ethashdir, | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 		"Network":    network, | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 		"Port":       config.port, | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 		"TotalPeers": config.peersTotal, | 
					
						
							|  |  |  | 		"Light":      config.peersLight > 0, | 
					
						
							|  |  |  | 		"LightPeers": config.peersLight, | 
					
						
							|  |  |  | 		"Ethstats":   config.ethstats[:strings.Index(config.ethstats, ":")], | 
					
						
							|  |  |  | 		"Etherbase":  config.etherbase, | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 		"GasTarget":  config.gasTarget, | 
					
						
							| 
									
										
										
										
											2018-08-29 12:21:12 +03:00
										 |  |  | 		"GasLimit":   config.gasLimit, | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 		"GasPrice":   config.gasPrice, | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 	files[filepath.Join(workdir, "docker-compose.yaml")] = composefile.Bytes() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 18:06:45 +01:00
										 |  |  | 	files[filepath.Join(workdir, "genesis.json")] = config.genesis | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	if config.keyJSON != "" { | 
					
						
							|  |  |  | 		files[filepath.Join(workdir, "signer.json")] = []byte(config.keyJSON) | 
					
						
							|  |  |  | 		files[filepath.Join(workdir, "signer.pass")] = []byte(config.keyPass) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Upload the deployment files to the remote server (and clean up afterwards) | 
					
						
							|  |  |  | 	if out, err := client.Upload(files); err != nil { | 
					
						
							|  |  |  | 		return out, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer client.Run("rm -rf " + workdir) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 14:24:01 +03:00
										 |  |  | 	// Build and deploy the boot or seal node service | 
					
						
							| 
									
										
										
										
											2017-10-19 16:00:55 +03:00
										 |  |  | 	if nocache { | 
					
						
							| 
									
										
										
										
											2018-08-03 12:08:19 +03:00
										 |  |  | 		return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s build --pull --no-cache && docker-compose -p %s up -d --force-recreate --timeout 60", workdir, network, network)) | 
					
						
							| 
									
										
										
										
											2017-10-19 16:00:55 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-08-03 12:08:19 +03:00
										 |  |  | 	return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s up -d --build --force-recreate --timeout 60", workdir, network)) | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // nodeInfos is returned from a boot or seal node status check to allow reporting | 
					
						
							|  |  |  | // various configuration parameters. | 
					
						
							|  |  |  | type nodeInfos struct { | 
					
						
							|  |  |  | 	genesis    []byte | 
					
						
							|  |  |  | 	network    int64 | 
					
						
							|  |  |  | 	datadir    string | 
					
						
							| 
									
										
										
										
											2017-10-19 17:50:34 +03:00
										 |  |  | 	ethashdir  string | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	ethstats   string | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 	port       int | 
					
						
							|  |  |  | 	enode      string | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	peersTotal int | 
					
						
							|  |  |  | 	peersLight int | 
					
						
							|  |  |  | 	etherbase  string | 
					
						
							|  |  |  | 	keyJSON    string | 
					
						
							|  |  |  | 	keyPass    string | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 	gasTarget  float64 | 
					
						
							| 
									
										
										
										
											2018-08-29 12:21:12 +03:00
										 |  |  | 	gasLimit   float64 | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 	gasPrice   float64 | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 14:22:59 +02:00
										 |  |  | // Report converts the typed struct into a plain string->string map, containing | 
					
						
							| 
									
										
										
										
											2017-10-19 13:59:02 +03:00
										 |  |  | // most - but not all - fields for reporting to the user. | 
					
						
							|  |  |  | func (info *nodeInfos) Report() map[string]string { | 
					
						
							|  |  |  | 	report := map[string]string{ | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 		"Data directory":           info.datadir, | 
					
						
							|  |  |  | 		"Listener port":            strconv.Itoa(info.port), | 
					
						
							|  |  |  | 		"Peer count (all total)":   strconv.Itoa(info.peersTotal), | 
					
						
							|  |  |  | 		"Peer count (light nodes)": strconv.Itoa(info.peersLight), | 
					
						
							|  |  |  | 		"Ethstats username":        info.ethstats, | 
					
						
							| 
									
										
										
										
											2017-10-19 13:59:02 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if info.gasTarget > 0 { | 
					
						
							| 
									
										
										
										
											2017-10-19 17:50:34 +03:00
										 |  |  | 		// Miner or signer node | 
					
						
							| 
									
										
										
										
											2017-10-19 13:59:02 +03:00
										 |  |  | 		report["Gas price (minimum accepted)"] = fmt.Sprintf("%0.3f GWei", info.gasPrice) | 
					
						
							| 
									
										
										
										
											2018-08-29 12:21:12 +03:00
										 |  |  | 		report["Gas floor (baseline target)"] = fmt.Sprintf("%0.3f MGas", info.gasTarget) | 
					
						
							|  |  |  | 		report["Gas ceil  (target maximum)"] = fmt.Sprintf("%0.3f MGas", info.gasLimit) | 
					
						
							| 
									
										
										
										
											2017-10-19 17:50:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if info.etherbase != "" { | 
					
						
							|  |  |  | 			// Ethash proof-of-work miner | 
					
						
							|  |  |  | 			report["Ethash directory"] = info.ethashdir | 
					
						
							|  |  |  | 			report["Miner account"] = info.etherbase | 
					
						
							| 
									
										
										
										
											2017-10-19 13:59:02 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-10-19 17:50:34 +03:00
										 |  |  | 		if info.keyJSON != "" { | 
					
						
							|  |  |  | 			// Clique proof-of-authority signer | 
					
						
							|  |  |  | 			var key struct { | 
					
						
							|  |  |  | 				Address string `json:"address"` | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if err := json.Unmarshal([]byte(info.keyJSON), &key); err == nil { | 
					
						
							|  |  |  | 				report["Signer account"] = common.HexToAddress(key.Address).Hex() | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				log.Error("Failed to retrieve signer address", "err", err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-10-19 13:59:02 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-19 13:59:02 +03:00
										 |  |  | 	return report | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 21:32:02 +08:00
										 |  |  | // checkNode does a health-check against a boot or seal node server to verify | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | // whether it's running, and if yes, whether it's responsive. | 
					
						
							|  |  |  | func checkNode(client *sshClient, network string, boot bool) (*nodeInfos, error) { | 
					
						
							|  |  |  | 	kind := "bootnode" | 
					
						
							|  |  |  | 	if !boot { | 
					
						
							|  |  |  | 		kind = "sealnode" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Inspect a possible bootnode container on the host | 
					
						
							|  |  |  | 	infos, err := inspectContainer(client, fmt.Sprintf("%s_%s_1", network, kind)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !infos.running { | 
					
						
							|  |  |  | 		return nil, ErrServiceOffline | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Resolve a few types from the environmental variables | 
					
						
							|  |  |  | 	totalPeers, _ := strconv.Atoi(infos.envvars["TOTAL_PEERS"]) | 
					
						
							|  |  |  | 	lightPeers, _ := strconv.Atoi(infos.envvars["LIGHT_PEERS"]) | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 	gasTarget, _ := strconv.ParseFloat(infos.envvars["GAS_TARGET"], 64) | 
					
						
							| 
									
										
										
										
											2018-08-29 12:21:12 +03:00
										 |  |  | 	gasLimit, _ := strconv.ParseFloat(infos.envvars["GAS_LIMIT"], 64) | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 	gasPrice, _ := strconv.ParseFloat(infos.envvars["GAS_PRICE"], 64) | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Container available, retrieve its node ID and its genesis json | 
					
						
							|  |  |  | 	var out []byte | 
					
						
							| 
									
										
										
										
											2018-07-30 16:09:19 +03:00
										 |  |  | 	if out, err = client.Run(fmt.Sprintf("docker exec %s_%s_1 geth --exec admin.nodeInfo.id --cache=16 attach", network, kind)); err != nil { | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 		return nil, ErrServiceUnreachable | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	id := bytes.Trim(bytes.TrimSpace(out), "\"") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if out, err = client.Run(fmt.Sprintf("docker exec %s_%s_1 cat /genesis.json", network, kind)); err != nil { | 
					
						
							|  |  |  | 		return nil, ErrServiceUnreachable | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	genesis := bytes.TrimSpace(out) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	keyJSON, keyPass := "", "" | 
					
						
							|  |  |  | 	if out, err = client.Run(fmt.Sprintf("docker exec %s_%s_1 cat /signer.json", network, kind)); err == nil { | 
					
						
							|  |  |  | 		keyJSON = string(bytes.TrimSpace(out)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if out, err = client.Run(fmt.Sprintf("docker exec %s_%s_1 cat /signer.pass", network, kind)); err == nil { | 
					
						
							|  |  |  | 		keyPass = string(bytes.TrimSpace(out)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Run a sanity check to see if the devp2p is reachable | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 	port := infos.portmap[infos.envvars["PORT"]] | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	if err = checkPort(client.server, port); err != nil { | 
					
						
							|  |  |  | 		log.Warn(fmt.Sprintf("%s devp2p port seems unreachable", strings.Title(kind)), "server", client.server, "port", port, "err", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Assemble and return the useful infos | 
					
						
							|  |  |  | 	stats := &nodeInfos{ | 
					
						
							|  |  |  | 		genesis:    genesis, | 
					
						
							|  |  |  | 		datadir:    infos.volumes["/root/.ethereum"], | 
					
						
							| 
									
										
										
										
											2017-10-19 17:50:34 +03:00
										 |  |  | 		ethashdir:  infos.volumes["/root/.ethash"], | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 		port:       port, | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 		peersTotal: totalPeers, | 
					
						
							|  |  |  | 		peersLight: lightPeers, | 
					
						
							|  |  |  | 		ethstats:   infos.envvars["STATS_NAME"], | 
					
						
							|  |  |  | 		etherbase:  infos.envvars["MINER_NAME"], | 
					
						
							|  |  |  | 		keyJSON:    keyJSON, | 
					
						
							|  |  |  | 		keyPass:    keyPass, | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 		gasTarget:  gasTarget, | 
					
						
							| 
									
										
										
										
											2018-08-29 12:21:12 +03:00
										 |  |  | 		gasLimit:   gasLimit, | 
					
						
							| 
									
										
										
										
											2017-05-13 03:03:56 +03:00
										 |  |  | 		gasPrice:   gasPrice, | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-12 16:27:53 +02:00
										 |  |  | 	stats.enode = fmt.Sprintf("enode://%s@%s:%d", id, client.address, stats.port) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-11 02:25:53 +03:00
										 |  |  | 	return stats, nil | 
					
						
							|  |  |  | } |