github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/puppeth/module_wallet.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊的一部分。 11 // 12 //Go以太坊是免费软件:您可以重新发布和/或修改它 13 //根据GNU通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊的分布希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU通用公共许可证了解更多详细信息。 21 // 22 //你应该已经收到一份GNU通用公共许可证的副本 23 //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package main 26 27 import ( 28 "bytes" 29 "fmt" 30 "html/template" 31 "math/rand" 32 "path/filepath" 33 "strconv" 34 "strings" 35 36 "github.com/ethereum/go-ethereum/log" 37 ) 38 39 // 40 var walletDockerfile = ` 41 FROM puppeth/wallet:latest 42 43 ADD genesis.json /genesis.json 44 45 RUN \ 46 echo 'node server.js &' > wallet.sh && \ 47 echo 'geth --cache 512 init /genesis.json' >> wallet.sh && \ 48 echo $'exec geth --networkid {{.NetworkID}} --port {{.NodePort}} --bootnodes {{.Bootnodes}} --ethstats \'{{.Ethstats}}\' --cache=512 --rpc --rpcaddr=0.0.0.0 --rpccorsdomain "*" --rpcvhosts "*"' >> wallet.sh 49 50 RUN \ 51 sed -i 's/PuppethNetworkID/{{.NetworkID}}/g' dist/js/etherwallet-master.js && \ 52 sed -i 's/PuppethNetwork/{{.Network}}/g' dist/js/etherwallet-master.js && \ 53 sed -i 's/PuppethDenom/{{.Denom}}/g' dist/js/etherwallet-master.js && \ 54 sed -i 's/PuppethHost/{{.Host}}/g' dist/js/etherwallet-master.js && \ 55 sed -i 's/PuppethRPCPort/{{.RPCPort}}/g' dist/js/etherwallet-master.js 56 57 ENTRYPOINT ["/bin/sh", "wallet.sh"] 58 ` 59 60 // 61 // 62 var walletComposefile = ` 63 version: '2' 64 services: 65 wallet: 66 build: . 67 image: {{.Network}}/wallet 68 ports: 69 - "{{.NodePort}}:{{.NodePort}}" 70 - "{{.NodePort}}:{{.NodePort}}/udp" 71 - "{{.RPCPort}}:8545"{{if not .VHost}} 72 - "{{.WebPort}}:80"{{end}} 73 volumes: 74 - {{.Datadir}}:/root/.ethereum 75 environment: 76 - NODE_PORT={{.NodePort}}/tcp 77 - STATS={{.Ethstats}}{{if .VHost}} 78 - VIRTUAL_HOST={{.VHost}} 79 - VIRTUAL_PORT=80{{end}} 80 logging: 81 driver: "json-file" 82 options: 83 max-size: "1m" 84 max-file: "10" 85 restart: always 86 ` 87 88 // 89 //Docker和Docker组合。如果具有指定网络名称的实例 90 //已经存在,将被覆盖! 91 func deployWallet(client *sshClient, network string, bootnodes []string, config *walletInfos, nocache bool) ([]byte, error) { 92 //生成要上载到服务器的内容 93 workdir := fmt.Sprintf("%d", rand.Int63()) 94 files := make(map[string][]byte) 95 96 dockerfile := new(bytes.Buffer) 97 template.Must(template.New("").Parse(walletDockerfile)).Execute(dockerfile, map[string]interface{}{ 98 "Network": strings.ToTitle(network), 99 "Denom": strings.ToUpper(network), 100 "NetworkID": config.network, 101 "NodePort": config.nodePort, 102 "RPCPort": config.rpcPort, 103 "Bootnodes": strings.Join(bootnodes, ","), 104 "Ethstats": config.ethstats, 105 "Host": client.address, 106 }) 107 files[filepath.Join(workdir, "Dockerfile")] = dockerfile.Bytes() 108 109 composefile := new(bytes.Buffer) 110 template.Must(template.New("").Parse(walletComposefile)).Execute(composefile, map[string]interface{}{ 111 "Datadir": config.datadir, 112 "Network": network, 113 "NodePort": config.nodePort, 114 "RPCPort": config.rpcPort, 115 "VHost": config.webHost, 116 "WebPort": config.webPort, 117 "Ethstats": config.ethstats[:strings.Index(config.ethstats, ":")], 118 }) 119 files[filepath.Join(workdir, "docker-compose.yaml")] = composefile.Bytes() 120 121 files[filepath.Join(workdir, "genesis.json")] = config.genesis 122 123 //将部署文件上载到远程服务器(然后清理) 124 if out, err := client.Upload(files); err != nil { 125 return out, err 126 } 127 defer client.Run("rm -rf " + workdir) 128 129 // 130 if nocache { 131 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)) 132 } 133 return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s up -d --build --force-recreate --timeout 60", workdir, network)) 134 } 135 136 // 137 //各种配置参数。 138 type walletInfos struct { 139 genesis []byte 140 network int64 141 datadir string 142 ethstats string 143 nodePort int 144 rpcPort int 145 webHost string 146 webPort int 147 } 148 149 //报表将类型化结构转换为纯字符串->字符串映射,其中包含 150 //大多数(但不是全部)字段用于向用户报告。 151 func (info *walletInfos) Report() map[string]string { 152 report := map[string]string{ 153 "Data directory": info.datadir, 154 "Ethstats username": info.ethstats, 155 "Node listener port ": strconv.Itoa(info.nodePort), 156 "RPC listener port ": strconv.Itoa(info.rpcPort), 157 "Website address ": info.webHost, 158 "Website listener port ": strconv.Itoa(info.webPort), 159 } 160 return report 161 } 162 163 // 164 // 165 func checkWallet(client *sshClient, network string) (*walletInfos, error) { 166 // 167 infos, err := inspectContainer(client, fmt.Sprintf("%s_wallet_1", network)) 168 if err != nil { 169 return nil, err 170 } 171 if !infos.running { 172 return nil, ErrServiceOffline 173 } 174 //从主机或反向代理解析端口 175 webPort := infos.portmap["80/tcp"] 176 if webPort == 0 { 177 if proxy, _ := checkNginx(client, network); proxy != nil { 178 webPort = proxy.port 179 } 180 } 181 if webPort == 0 { 182 return nil, ErrNotExposed 183 } 184 // 185 host := infos.envvars["VIRTUAL_HOST"] 186 if host == "" { 187 host = client.server 188 } 189 // 190 nodePort := infos.portmap[infos.envvars["NODE_PORT"]] 191 if err = checkPort(client.server, nodePort); err != nil { 192 log.Warn(fmt.Sprintf("Wallet devp2p port seems unreachable"), "server", client.server, "port", nodePort, "err", err) 193 } 194 rpcPort := infos.portmap["8545/tcp"] 195 if err = checkPort(client.server, rpcPort); err != nil { 196 log.Warn(fmt.Sprintf("Wallet RPC port seems unreachable"), "server", client.server, "port", rpcPort, "err", err) 197 } 198 //收集并返回有用的信息 199 stats := &walletInfos{ 200 datadir: infos.volumes["/root/.ethereum"], 201 nodePort: nodePort, 202 rpcPort: rpcPort, 203 webHost: host, 204 webPort: webPort, 205 ethstats: infos.envvars["STATS"], 206 } 207 return stats, nil 208 }