一、前言

最近,需要接触区块链项目的主链开发,在EOSBTCethereum超级账本这几种区块链技术当中,相互对比后,最终还是以go-ethereum为解决方案。
ethereum为基准去找解决方案,最终找到了2个符合自己要求的方案,分别如下:美图、gttc。本来是想用gttc的这个解决方案的,但是它是基于go-ethereum最新源码来进行二次开发的,相对不稳定,因此还是用美图的解决方案了,毕竟这公司大一点,没那么多坑。

二、源码

为了方便测试,我们需要将节点最大验证器数修改一下,这样便于我们进行简单测试
修改consensus/dpos/dpos.go文件的maxValidator

// 新值
maxValidatorSize = 21
// 旧值
maxValidatorSize = 3

三、构建

# 进入源码根目录
docker build . -t meitugeth

注意:构建过程中会用到build\env.sh文件,会提示无权限,因此你需要给该文件赋予执行权限。

sudo chmod 777 build\env.sh

四、部署

1. 创建节点数据目录

最好事先创建好相应的目录,否则运行后,动态创建目录,会有权限的问题,当然也可以通过命令进行设置目录的权限。

mkdir ~/data
mkdir ~/data/meitu
mkdir ~/data/meitu/node1
mkdir ~/data/meitu/node2
mkdir ~/data/meitu/node3

2. 编写docker-compose.yml文件

version: '3'
services: meitu_node_1:image: meitugethcontainer_name: meitu_node_1build: context: .command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303ports: - 15450:8545- 15460:8546- 10303:30303- 10303:30303/udp- 10304:30304/udpvolumes: - /etc/localtime:/etc/localtime- ~/data/meitu/node1/:/root/.ethereum/environment: TZ: Asia/Shanghaimeitu_node_2:image: meitugethcontainer_name: meitu_node_2build: context: .command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303depends_on: - meitu_node_1ports: - 25450:8545- 25460:8546- 20303:30303- 20303:30303/udp- 20304:30304/udpvolumes: - /etc/localtime:/etc/localtime- ~/data/meitu/node2/:/root/.ethereum/environment: TZ: Asia/Shanghaimeitu_node_3:image: meitugethcontainer_name: meitu_node_3build: context: .command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303depends_on: - meitu_node_1ports: - 45450:8545- 45460:8546- 40303:30303- 40303:30303/udp- 40304:30304/udpvolumes: - /etc/localtime:/etc/localtime- ~/data/meitu/node3/:/root/.ethereum/environment: TZ: Asia/Shanghai

3. 启动节点

在根目录下启动3个以太坊节点

docker-compose up --build -d

4. 启动思路

美图以太坊这块有2种启动网络:

  • 在创世块里配置好第一验证节点,然后启动
  • 混合POW和DPOS,用POW进行投票,产生第一批验证节点,并自动切换到DPOS

5. 首次启动

1. 进入容器

进入容器命令如下:

# 模板
docker exec -it [容器名|容器ID] /bin/sh
# 例子
docker exec -it meitu_node_1 /bin/sh
docker exec -it meitu_node_2 /bin/sh
docker exec -it meitu_node_3 /bin/sh

2. 进入geth JavaScript控制台

# 方式一
geth attach ipc:/root/.ethereum/geth.ipc
# 方式二
docker exec -it meitu_node_1 geth attach ipc:/root/.ethereum/geth.ipc
# 方式三:使用别名
alias geth="docker exec -it meitu_node_1 geth attach ipc:/root/.ethereum/geth.ipc"

3. 创建账户

进入geth JavaScript 控制台后,需哟啊创建账户,命令如下;

# 模板
personal.newAccount('名称')
# 例子
personal.newAccount('test001')
"0x849f9442198282fb21539351edb0378463e4c251"
personal.newAccount('test002')
"0x2c08f54d5b324c0175ea53b997f5ce1f61a7e4ed"
personal.newAccount('test003')
"0xc4118320f3d3c37a2ca8dad5c2f2a40f2a23ba02"

创建成功后,需要将返回的地址记录起来

loop:重复1-3步骤,在node1、node2、node3分别创建账户

4. 编写创世块配置文件

将上一步操作生成的地址写入到创世块文件中,三个节点的地址分别为:

0x849f9442198282fb21539351edb0378463e4c251
0x2c08f54d5b324c0175ea53b997f5ce1f61a7e4ed
0xc4118320f3d3c37a2ca8dad5c2f2a40f2a23ba02

将3个节点地址列入第一批验证人列表

{"config": {"chainId": 7777,"eip155Block": 0,"eip158Block": 0,"byzantiumBlock":0,"dpos":{"validators":["0x849f9442198282fb21539351edb0378463e4c251","0x2c08f54d5b324c0175ea53b997f5ce1f61a7e4ed","0xc4118320f3d3c37a2ca8dad5c2f2a40f2a23ba02"]}},"nonce": "0x0000000000000042","difficulty": "0x020000","mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000","coinbase": "0x0000000000000000000000000000000000000000","timestamp": "0x00","parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000","extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa","gasLimit": "0x500000","alloc": {}
}

创世配置参数说明:

  • nonce:64位随机数,用于挖矿
  • timestamp:创世块的时间戳
  • parentHash:上一个区块的hash值,因为是创世块,所以这个值是0
  • mixHash:与nonce配合用于挖矿,由上一个区块的一部分生成hash
  • extraData:附加信息,任意填写
  • gasLimit:对GAS的消耗总量限制,用来限制区块能包含的交易信息总和
  • difficulty:难度值,越大越难
  • coinbase:矿工账号,第一个区块挖出后将给这个矿工账号发送奖励的以太币
  • alloc:预设账号以及账号的以太币数量,测试链挖矿比较容易可以不配置
  • chainId:指定了独立的区块链网络ID,不同ID网络的节点无法互相连接

5. 初始化创世目录

1. 删除每个节点下geth目录,保留keystore

移除geth目录,便于移除旧的无效数据,因为节点刚启动的时候,使用的是默认创世配置,而自定义的又不一样,因此需要移除。

sudo rm -rf ~/data/meitu/node1/geth
sudo rm -rf ~/data/meitu/node2/geth
sudo rm -rf ~/data/meitu/node3/geth

2. 拷贝创世配置到数据目录

将创世配置拷贝到数据目录中,便于容器内能访问,至于这个目录跟docker-compose.yml映射的目录有关。
因此,命令也要相应的变更。

cp genesis.json ~/data/meitu/node1
cp genesis.json ~/data/meitu/node2
cp genesis.json ~/data/meitu/node3

3. 初始化创世配置

进入容器,并执行初始化命令。

# 节点1
docker exec -it meitu_node_1 /bin/sh
geth init /root/.ethereum/genesis.json
# 节点2
docker exec -it meitu_node_2 /bin/sh
geth init /root/.ethereum/genesis.json
# 节点3
docker exec -it meitu_node_3 /bin/sh
geth init /root/.ethereum/genesis.json

**loop:重复在node2、node3上分别执行init

6. 重启节点网络

以下命令需要在docker-compose.yml文件的当前目录方可运行。

# 移除容器
docker-compose down
# 启动容器
docker-compose up -d

7. 查看验证人是否设置成功

1. 进入容器

docker exec -it meitu_node_3 /bin/sh

2. 进入geth JavaScript控制台

geth attach ipc:/root/.ethereum/geth.ipc

3. 执行获取验证人列表命令

dpos.getValidators()
["0x849f9442198282fb21539351edb0378463e4c251", "0x2c08f54d5b324c0175ea53b997f5ce1f61a7e4ed", "0xc4118320f3d3c37a2ca8dad5c2f2a40f2a23ba02"]

8. 节点互联

1. 查看节点是否互联

admin.peers
[]

返回的数据为[],说明节点之间没有互相发现。

2. 设置节点互联

1. 查看每个节点信息
admin.nodeInfo

确认:enode都不一样,protocols都一样。
记下三个enode

"enode://7f2f1a5818b4bb7e756036ab08834386534807bbf5c5a305ddcbefa1ff9ea99028feb00cb78322ac39340501d5b7c6147e169aadbb028daf20f8d73dbdfea98e@[::]:30303"
"enode://6ab4f74058b9c1e43d2d0c6f55f538ea7f2f366dd9f8f560024f14603333f017d3404b9c9711538289fa76504fecf33cf0e36cce7b0414604f673abe93012413@[::]:30303"
"enode://e82fecab04e5e902a9e4ea491527ea958d2cdeb83383dfa36562e32a51eedb204a541e00ef0b497704ec0e91017799a73283e53f6dffdeef492a4230626b10b6@[::]:30303"
2. 查看docker容器网络信息
# 显示docker所有网络信息
docker network ls
# 查看具体网络信息
docker network inspect [网络名称]
# 例子
docker network inspect docker_default

执行查看网络信息命令后,会返回一下内容

[{"Name": "docker_default","Id": "984fabf7e51b07c1984114720f98f305cc61cc26546cf9da4bcbbbc36a591351","Created": "2018-12-05T06:06:13.435067024Z","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "172.20.0.0/16","Gateway": "172.20.0.1"}]},"Internal": false,"Attachable": true,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"263f1553108cc8ea00b76598adb6d66649287943c7d0f50d0be02963863ff45c": {"Name": "meitu_node_2","EndpointID": "9f4114a81133bd490b501ac45fd50fe512309f9096b5468054bd074bad45a07d","MacAddress": "02:42:ac:14:00:03","IPv4Address": "172.20.0.3/16","IPv6Address": ""},"3acd943c8e0759dc241d7cc623b1a1ca45096480dcd2fd0daa8b951407eb40bf": {"Name": "meitu_node_3","EndpointID": "0480296c4e8217862358143a084da2d1563cd4f60105e6020434f222320681a5","MacAddress": "02:42:ac:14:00:04","IPv4Address": "172.20.0.4/16","IPv6Address": ""},"416fe5eb074c24f032d5bd49a6be68cf293a30af17780133b9fa63663e4b7097": {"Name": "meitu_node_1","EndpointID": "0dc00e9c6f63f844502525b34e87baf62f4de852ac46907951d4b689dd89635f","MacAddress": "02:42:ac:14:00:02","IPv4Address": "172.20.0.2/16","IPv6Address": ""}},"Options": {},"Labels": {"com.docker.compose.network": "default","com.docker.compose.project": "docker","com.docker.compose.version": "1.23.1"}}
]

找到不同容器中,相应的IP地址。
记录下每个节点的IP,也可以用127.0.0.1加节点映射到本机的不同网络端口。

meitu_node_1 172.20.0.2
meitu_node_2 172.20.0.3
meitu_node_3 172.20.0.4
3. 添加监视器

进入节点1 geth JavaScript 控制台后,执行以下命令:

# 添加节点2的监视器
admin.addPeer("enode://6ab4f74058b9c1e43d2d0c6f55f538ea7f2f366dd9f8f560024f14603333f017d3404b9c9711538289fa76504fecf33cf0e36cce7b0414604f673abe93012413@[172.20.0.3]:30303")
# 添加节点3的监视器
admin.addPeer("enode://e82fecab04e5e902a9e4ea491527ea958d2cdeb83383dfa36562e32a51eedb204a541e00ef0b497704ec0e91017799a73283e53f6dffdeef492a4230626b10b6@[172.20.0.4]:30303")
4.查看节点网络

在执行完添加监视器后,执行admin.peers即可看到节点已经互联起来。

admin.peers
[{caps: ["eth/62", "eth/63"],id: "6ab4f74058b9c1e43d2d0c6f55f538ea7f2f366dd9f8f560024f14603333f017d3404b9c9711538289fa76504fecf33cf0e36cce7b0414604f673abe93012413",name: "Geth/v1.7.4-stable-a487fc95/linux-amd64/go1.9.7",network: {localAddress: "172.20.0.2:60018",remoteAddress: "172.20.0.3:30303"},protocols: {eth: {difficulty: 131189,head: "0xa00badd4041033da53c0a34cce5aa59885d7f638e00e1e307b04c02ee640df19",version: 63}}
}, {caps: ["eth/62", "eth/63"],id: "e82fecab04e5e902a9e4ea491527ea958d2cdeb83383dfa36562e32a51eedb204a541e00ef0b497704ec0e91017799a73283e53f6dffdeef492a4230626b10b6",name: "Geth/v1.7.4-stable-a487fc95/linux-amd64/go1.9.7",network: {localAddress: "172.20.0.2:36700",remoteAddress: "172.20.0.4:30303"},protocols: {eth: {difficulty: 131076,head: "0xe30ff3a8d1ae16384369c45d106841ef44e83c12eae2e2c66dce1bdccc9ba4d6",version: 63}}
}]

注意:这一步完成了,仅仅是临时的,每次重启docker之后admin.peers会重新为空。

9. 配置永久互联

临时互联不方便,可以将bootnodes配置到启动文件中。
修改docker-compose.yml文件,将节点1的连接配置进去。

version: '3'
services: meitu_node_1:image: meitugethcontainer_name: meitu_node_1build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303ports: - 15450:8545- 15460:8546- 10303:30303- 10303:30303/udp- 10304:30304/udpvolumes: - /etc/localtime:/etc/localtime- ~/data/meitu/node1/:/root/.ethereum/environment: TZ: Asia/Shanghaimeitu_node_2:image: meitugethcontainer_name: meitu_node_2build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303 --bootnodes enode://7f2f1a5818b4bb7e756036ab08834386534807bbf5c5a305ddcbefa1ff9ea99028feb00cb78322ac39340501d5b7c6147e169aadbb028daf20f8d73dbdfea98e@[172.20.0.2]:30303depends_on: - meitu_node_1ports: - 25450:8545- 25460:8546- 20303:30303- 20303:30303/udp- 20304:30304/udpvolumes: - /etc/localtime:/etc/localtime- ~/data/meitu/node2/:/root/.ethereum/environment: TZ: Asia/Shanghaimeitu_node_3:image: meitugethcontainer_name: meitu_node_3build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303 --bootnodes enode://7f2f1a5818b4bb7e756036ab08834386534807bbf5c5a305ddcbefa1ff9ea99028feb00cb78322ac39340501d5b7c6147e169aadbb028daf20f8d73dbdfea98e@[172.20.0.2]:30303depends_on: - meitu_node_1ports: - 45450:8545- 45460:8546- 40303:30303- 40303:30303/udp- 40304:30304/udpvolumes: - /etc/localtime:/etc/localtime- ~/data/meitu/node3/:/root/.ethereum/environment: TZ: Asia/Shanghai

这个时候,“主网”启动成功了!!!

五、运行

1. 解锁账户

分别在3个节点上把validator无限期解锁,谁不解锁谁别出块、跳过你。
这里源码默认10秒1块。
进入geth JavaScript控制台后,执行以下命令:

# 模板
personal.unlockAccount(eth.validator,'名称',0)
# 例子
personal.unlockAccount(eth.validator,'jce001',0)
personal.unlockAccount(eth.validator,'jce002',0)
personal.unlockAccount(eth.validator,'jce003',0)

根据美图解释,这里validatorcoinbase的区别:

  • coinbase:收取挖矿奖励
  • validator:可以设置为其他地址,但默认和coinbase一样。

2. 启动挖矿

进入geth JavaScript控制台后,执行以下命令:

miner.start()

3. 获取区块信息

进入geth JavaScript控制台后,执行以下命令:

# 模板
eth.getBlock(区块编号)
# 例子
eth.getBlock(1)
# 结果
{coinbase: "0x849f9442198282fb21539351edb0378463e4c251",difficulty: 1,extraData: "0xd783010704846765746887676f312e392e37856c696e7578000000000000000084c3b20f15eb99c19bb8567d3a27a52947efb816f647cbc4491540ee5de685d54f4126d236f031d33312dfab1a5d7a895bbd4d154afd366b30918a9af6868ab300",gasLimit: 5237761,gasUsed: 0,hash: "0x30964585add8b4ef65529f38ebe00bb6581fc9ae7323327f7dfd666754de883b",logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",nonce: "0x0000000000000000",number: 1,parentHash: "0x9390ffeae9812417704193667a0e106c8cd9e701217deb054737dab0325191d3",receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",size: 794,stateRoot: "0xc5a87ecb7262f6c507f488f5f93efa27df81550f1e7691c1ab2093a4218d2ca0",timestamp: 1543990290,totalDifficulty: 131073,transactions: [],transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",uncles: [],validator: "0x849f9442198282fb21539351edb0378463e4c251"
}

六、测试

1. 获取账户余额

# 获取账户
eth.accounts# 获取余额
eth.getBalance(账户地址)# 格式化长度
web3.fromWei(数值)# 获取格式化后的余额,默认取第一个账户
web3.fromWei(eth.getBalacne(eth.accounts[0]))# 获取指定账户余额
web3.fromWei(eth.getBalance("0x849f9442198282fb21539351edb0378463e4c251"))

2. 交易

# 模板
eth.sendTransaction({from: "发送者", to: "接受者", value: 数量})
# 例子
eth.sendTransaction({from: "0x849f9442198282fb21539351edb0378463e4c251", to: "0xc4118320f3d3c37a2ca8dad5c2f2a40f2a23ba02", value: 1000000000000000000})

通过获取余额判断是否转账成功,也可通过返回的交易编号查询情况。

web3.eth.getTransactionReceipt('0x8a4104da45c736c7a671ff7974b9b9a1848ff4c001f3cbcd4eb427aab50d604f')

七、参考

  • 美团DPOS以太坊节点网络启动和测试(Docker版)
  • 以太坊测试区块链环境搭建

转载于:https://www.cnblogs.com/jianxuanbing/p/10071238.html

美图DPOS以太坊教程(Docker版)相关推荐

  1. java美图秀秀_[Java教程]简易版美图秀秀_星空网

    简易版美图秀秀 2016-10-30 0 简易板美图秀秀灰度 黑白 底片 模糊 马赛克 简单的实现了 灰度,黑白,底片,模糊,马赛克(代码比较简单,通过canvas实现的) 感觉挺有意思的,上面解释很 ...

  2. 以太坊源码linux下如何编译,以太坊教程:搭建环境、编写编译一个智能合约

    本以太坊教程主要是介绍:搭建一个开发环境.编写编译一个智能合约. 以太坊是什么 以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台.通过其专用加密货币以太币(Ether)提供去中心化 ...

  3. 以太坊教程:入门学习开发以太坊dapp

    一.区块链 1. 分布式去中心化 比特币设计的初衷就是要避免依赖中心化的机构,没有发行机构,也不可能操纵发行数量.既然没有中心化的信用机构,在电子货币运行的过程中,也势必需要一种机制来认可运行在区块链 ...

  4. Teahour 以太坊专访-文字版

    原文地址:http://ethfans.org/shaoping/articles/talk-with-jan-about-ehtereum 本文是播客Teahour以太坊专访文字版,收听地址 htt ...

  5. 以太坊教程:搭建环境、编写编译一个智能合约

    本以太坊教程主要是介绍:搭建一个开发环境.编写编译一个智能合约. 以太坊是什么 以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台.通过其专用加密货币以太币(Ether)提供去中心化 ...

  6. 美图DPOS共识机制ETH节点网络启动和测试

    源码 https://github.com/meitu/go-ethereum 节点网络启动 1.简单测试起见,需要将节点最大验证器数修改为最小数 consensus/dpos/dpos.go max ...

  7. 币图网以太坊开发实例_去中心化概念模型与架构设计

    IM 去中心化概念模型与架构设计 今天打算写写关于 IM 去中心化涉及的架构模型变化和设计思路,去中心化的概念就是说用户的访问不是集中在一个数据中心,这里的去中心是针对数据中心而言的. 站在这个角度而 ...

  8. android 相机智能补光,美图秀秀的HD1.3.1版新增智能补光将暗淡照片瞬间变亮彩

    微博里大家还在吐槽"暑假这么快就结束了"!微博外,返校后同学室友的见面狂欢其实已冲淡了大家对暑假的依恋,只是聚会大多在室内,拍起照来真是不给力.不过,今年暑假虽已不可重来,可暗淡照 ...

  9. 以太坊又一次大拥堵何去何从?深度对话美图以太坊DPoS算法实现团队

    最近,以太坊又一次出现大拥堵,美图基于以太坊框架实现了 DPoS 算法并且对代码进行了开源(链接见文末),希望借助此方案能让以太坊发展有更多的选择的可能. 图:最近一周以太坊交易又出现大范围拥堵 有些 ...

最新文章

  1. libev源码解析——调度策略
  2. 2017-2-23 C#基础 中间变量
  3. C#和SqlServer中处理时间格式问题
  4. 结对-贪吃蛇-项目进度
  5. Innodb隔离级别的实现原理
  6. AngularJs 基础教程 —— 控制器
  7. power-bi_在Power BI中的VertiPaq内-压缩成功!
  8. HDU(1175),连连看,BFS
  9. sql实现自定义排序
  10. Java使用easyexcel读大文件
  11. android定时器课程设计,定时器课程设计.doc
  12. 城阳三中2021高考成绩查询入口,2021年青岛城阳区中考录取分数线公布
  13. 震惊世人的10个Python黑科技,你知道几个?
  14. STM8S103之tim2PWM输出
  15. matlab 定步长积分,数值积分:基于牛顿-柯茨公式的定步长和自适应积分方法 [MATLAB]...
  16. 选择粘贴性无html,office无法复制粘贴-Word把内容从一个文档选择性粘贴到另一个文档,具体操作方法...
  17. 牛客练习赛47 D DongDong坐飞机 (分层最短路)
  18. GPS从入门到放弃(二十六) --- RTKLIB函数解析
  19. 小米progtx笔记本快捷键驱动安装
  20. linux更新网卡驱动版本,Linux中升级网卡驱动

热门文章

  1. 【许晓笛】EOS 智能合约案例解析(2)
  2. 应急制冷精密空调 数据中心应急制冷系统
  3. java 控制台scanner的中文输入问题
  4. LOJ#539. 「LibreOJ NOIP Round #1」旅游路线
  5. kb981833补丁蓝屏报错 0x0000006b
  6. 解决ultraedit-32卸载后文件关联问题
  7. STM32 —— Modbus 协议
  8. div中内容水平垂直居中
  9. ANSYS-复杂力学接触分析-接触不收敛的调试方法(1)
  10. 华尔街借助软件甄别忠诚员工