运行环境
测试环境
OS: Ubuntu 18.04
Go: go1.15.6 linux/amd64
源代码
git clone https://github.com/HuobiGroup/huobi-eco-chain.git
当前测试 master 分支
编译
cd huobi-eco-chain/
make geth
编译完成后,生成文件在./build/bin/geth
创建 geth.toml
参考 https://github.com/HuobiGroup/huobi-eco-chain-docs/blob/master/dev/deploy.md
[Eth]
SyncMode = "fast"
DiscoveryURLs = []
TrieCleanCacheRejournal= 300000000000
[Eth.Miner]
GasFloor = 8000000
GasCeil = 8000000
GasPrice = 0
Recommit = 3000000000
Noverify = false
[Eth.Ethash]
CacheDir = "ethash"
CachesInMem = 2
CachesOnDisk = 3
CachesLockMmap = false
DatasetDir = "/data/heco/data/.ethash"
DatasetsInMem = 1
DatasetsOnDisk = 2
DatasetsLockMmap = false
PowMode = 0
[Eth.TxPool]
Locals = []
NoLocals = false
Journal = "transactions.rlp"
Rejournal = 3600000000000
PriceLimit = 1
PriceBump = 10
AccountSlots = 16
GlobalSlots = 4096
AccountQueue = 64
GlobalQueue = 1024
Lifetime = 10800000000000
[Node]
DataDir = "/data/heco/data"
InsecureUnlockAllowed = true
NoUSB = true
IPCPath = "geth.ipc"
HTTPHost = "0.0.0.0"
HTTPPort = 8545
HTTPCors = ["*"]
HTTPVirtualHosts = ["*"]
HTTPModules = ['eth', 'net', 'web3']
WSHost = "0.0.0.0"
WSPort = 8546
WSModules = ['eth', 'net', 'web3']
GraphQLVirtualHosts = ["localhost"]
[Node.P2P]
MaxPeers = 50
NoDiscovery = false
ListenAddr = ":32668"
EnableMsgEvents = false
[Node.HTTPTimeouts]
ReadTimeout = 30000000000
WriteTimeout = 30000000000
IdleTimeout = 120000000000
预先创建一个账户地址
使用MetaMask或者其他工具预先创建一个账户地址,并保存好私钥,后面这个地址会配置在初始的Validators中,并用做boot节点启动挖矿coinbase地址
创建genesis.json
参考https://docs.hecochain.com/#/genesis
根据需要修改特定的字段,常规的比如
- chainId 修改为自己的独有链id
- extraData 修改为预先创建的地址
- alloc中的
0xdaf88b74fca1246c6144bc846aaa3441ed095191
修改为初始资金接收地址,balance根据业务需要,计算相应预先发行数量(精度18位)的16进制
对于共识参数,根据需要再做修改吧
"congress": {
"period": 3, // 出块间隔(秒)
"epoch": 200 // 出块顺序刷新间隔(块数)
}
初始化并启动geth
将上面修改好的geth.toml
和genesis.json
放到规划好的位置,我们此时假设为/data/heco
。
初始化geth
在上面目录/data/heco
中执行数据初始化
./geth --datadir ./data init genesis.json
我们将链相关数据保存在/data/heco/data
下,方便磁盘数据管理,以及后期磁盘空间升级及其迁移
首次启动geth
./geth --config geth.toml --nodiscover
启动后,进入ipc导入我们预先生成的地址私钥,作为此节点的coinbase
从另一个终端进入
./geth attach ipc:/data/heco/data/geth.ipc
在geth命令行中导入预先生成地址的私钥,123456
为钱包密码,在此目录创建password文件,并将密码保存在该文件,后面后台启动会需要
personal.importRawKey("e9bc9ae610535514。。。56a272f69fd59d7986b9f4f49c025cc","123456")
并设置该地址为无限期解锁,因为后面需要使用该私钥进行出块签名。0为无限期
personal.unlockAccount("0x48F155527f2。。。7e84692AA0025C0","123456",0)
此时geth命令行中输入eth
,查看
> eth
{
accounts: ["0x48F155527f2。。。7e84692AA0025C0"],
blockNumber: 4412,
coinbase: "0x48F155527f2。。。7e84692AA0025C0",
accounts
和coinbase
都为预先生成的地址
后台运行geth
此时关闭前面运行的geth,重新后台运行
nohup ./geth --config geth.toml --networkid 65525 --unlock "0x48F155527f2。。。7e84692AA0025C0" --password ./password --mine --nodiscover --etherbase 0 2>> ./geth.log &
此时查看geth.log
文件
tail -f geth.log
即可看到geth 已经正常单节点出块
测试查询
查看前面预先设置的初始资金接收地址
eth.getBalance("0x48F155527。。。。692AA0025C0")
可查看到,该地址已经存入了balance设置对应的代币
测试转账
eth.sendTransaction({from: "0x48F155527f25EB1。。。。4692AA0025C0" , to: "0x5849cce8b6ea2。。。。7436b628df34217", value: web3.toWei(10,"ether")})
执行完,查看from和to双方账户资金转移正常
MetaMask扩展配置
Chrome浏览器安装好扩展后,进入设置
->网络
->添加网络
,输入相关信息
- 网络名称 -> 任意信息,只是本地备注
- 新增 RPC URL -> 该geth运行所在服务器访问地址+端口(端口是上面geth.toml配置的Node->HTTPPort)
- 链ID -> 上面genesis.json中配置的chainId
- 符号(选填)-> 该节点的系统代币的符号
- 屏蔽管理器 URL(选填)-> 汉化翻译不准确,其实就是区块浏览器的地址,后期可以自己拿Etherscan自己部署一套
此时就可以通过MetaMask扩展进行地址代币管理了
多节点部署
如果只是本地测试,单点足以满足需求的话,可以不必继续部署
在其他需要部署节点的服务器上准备好geth节点程序以及上面同样的geth.toml和genesis.json文件,(同一机器多个geth运行实例,修改对应端口和data目录,流程同理)
然后照搬上面的流程的初始化并启动geth
到后台运行geth
执行完成后会报
WARN [02-24|15:35:05.457] Block sealing failed err="unauthorized validator"
是因为此节点的coinbase并不在初始的Validators中,先忽略,等下后面跟进合约动态添加到Validators
数据链接
由于节点启动时关闭了自发现,所以需要我们主动去连接下
两边节点分别查下节点信息
admin.nodeInfo
将enode存下来,将ip地址127.0.0.1
修改为当前节点对应的可其他节点访问的地址
节点A
enode://219a81569be3b9f3e261f40e0edbf4893ccde5bc94df6525135eacc337122ef060bad7f220d90622349ab189b87106f26637520f272e5ae73f9797cd6506ddd4@172.17.116.158:32668?discport=0
节点B
enode://425ef46887ac2cb08076bc78e54ba11fb280c9cb2ff6a7bc173001933cfcd2b98b9f49afa3ac3857cc5e49ad01e64595a07c8c2053416390459409da7920a1c9@172.17.116.159:32668?discport=0
然后分别再对方节点上增加自己的节点
节点A执行
admin.addPeer("enode://425ef46887ac2cb08076bc78e54ba11fb280c9cb2ff6a7bc173001933cfcd2b98b9f49afa3ac3857cc5e49ad01e64595a07c8c2053416390459409da7920a1c9@172.17.116.159:32668?discport=0")
节点B执行
admin.addPeer("enode://219a81569be3b9f3e261f40e0edbf4893ccde5bc94df6525135eacc337122ef060bad7f220d90622349ab189b87106f26637520f272e5ae73f9797cd6506ddd4@172.17.116.158:32668?discport=0")
此时A节点正常出块,B节点正常从A节点同步区块,其他节点同理加入
编译合约
修改solc的依赖版本
// Configure your compilers
compilers: {
solc: {
version: "^0.6.1", // 修改为该版本以上,不然会报找不到对应的版本,此时会下载0.6.12版本
编译合约
truffle compile
此时会在./build/contracts
下生成各个合约对应的abi json
文件
其中的"abi"
节点的内容,就是下面myetherwallet
要用到的abi
合约设置
经过上面的操作,多节点网络已经运行了,下一步进行系统合约设置
以下合约操作通过https://www.myetherwallet.com/interface/interact-with-contract 工具进行交互
申请成为出块节点
选择执行createProposal
参数
- dst 需要申请添加的地址
- details 附加信息(选填)
对于genesis的预设地址,默认会在系统初始化时,自动添加到审核通过
审核出块申请
选择执行voteProposal,当前设计,合约签名地址需要为已经通过申请的用户,赞同总数或者拒绝总数,哪个先超过当前正在出块人数的 1/2+1,就执行对应的决定。这个不合理,应该是需要正在出块人中的1/2+1赞同才有效,那些之前通过审核,但不是正在出块的地址,没有审核资格。
参数
取消出块资质
选择执行setUnpassed,目前合约需要当前合约权限才能禁止掉其他人,不合理,后面进行合约修改,同样需要发起申请,通过1/2+1人通过,才会取消对应地址的资格。
创建validator地址
选择执行createOrEditValidator,需要先申请,通过后才允许创建
参数
- feeAddr 该矿工领取奖励时的接收地址
- moniker 昵称(选填)
- identity 身份(选填)
- website 网址(选填)
- email 邮箱(选填)
- details 附加信息(选填)
抵押系统代币
选择执行stake,需要创建完validator,才能进行抵押,抵押量不小于32 ether,后面挖矿奖励会根据当前用户抵押量所占总比例进行分配。
矿工主动提交所得,进行分配
链程序出块后,自动执行distributeBlockReward将打包所得手续费转到合约进行池分配(后期排查,节点程序是否可作恶,抽水),代币总量到合约后,合约根据currentValidatorSet中各自地址抵押总额,以及各自占比进行分配记账(validatorInfo[地址].hbIncoming),(对于合约分配逻辑,后面单独写文章讲解)
领取出块奖励
选择执行 withdrawProfits,参数validator为矿工地址,执行签名地址需要与创建时设置的feeAddr一致,领取时间间隔24小时(28800块)
参考
https://github.com/sigp/lighthouse/issues/2115