BCSkill (Block chain skill ) 技术社区
社区QQ群:791420381
推荐论坛:https://eosfans.io
Telegram: https://t.me/bcskill

Heco系统合约分析

官方文档:https://docs.hecochain.com/#/consensus?id=%e7%b3%bb%e7%bb%9f%e5%90%88%e7%ba%a6
合约源代码:https://github.com/HuobiGroup/huobi-eco-contracts

系统合约

目前验证人的管理,均由系统合约完成,目前的系统合约有:

  • Proposal 负责管理验证人的准入资格,管理验证人提案和投票;
  • Validators 负责对验证人进行排名管理、质押和解质押操作、分发区块奖励等;
  • Punish 负责对不正常工作的活跃验证人进行惩罚操作;

区块链调用系统合约

  • 每个块结束的时候,会调用Validators合约,将区块中所有交易的手续费分发给active validator;
  • 发现validator没有正常工作的时候,会调用Punish合约,对validator进行惩罚;
  • 每个epoch结束的时候,会调用Validators合约,根据排名,更新active validator;

质押

任何账户,都可以对validator进行任意数量的质押操作,每个validator的最小质押量是32HT。 如果想取回已质押的HT,需要按照如下操作进行:

  1. 发送调用Validators合约,发送针对某一个validator的解质押(unstake)的声明交易;
  2. 等待86400个块之后,调用Validators合约,发送提取质押(withdrawStaking)的交易,将所有在此validator的质押取回;

惩罚措施

每当发现验证人没有按照预先设定进行出块的时候,就会在这个块结束时,自动调用Punish合约,对验证人进行计数。当计数达到24时,罚没验证人的所有收入。当计数达到48时,将验证人移除出活跃验证人列表,同时取消验证人资格。

合约初始化

系统合约会在第一区块时被全部初始化
(github code)
(github code2)

// Initialize all system contracts at block 1.
if header.Number.Cmp(common.Big1) == 0 {
    if err := c.initializeSystemContracts(chain, header, state); err != nil { // 在此初始化三个系统合约
        log.Error("Initialize system contracts failed", "err", err)
        return err
    }
}

编译合约

修改solc的依赖版本

 // Configure your compilers
  compilers: {
    solc: {
      version: "^0.6.1", // 修改为该版本以上,不然会报找不到对应的版本,此时会下载0.6.12版本

编译合约

truffle compile

此时会在./build/contracts下生成各个合约对应的abi json文件

参考

https://ethereum.stackexchange.com/questions/234/what-is-an-abi-and-why-is-it-needed-to-interact-with-contracts
https://ethereum.stackexchange.com/questions/1437/do-i-need-a-compiled-contract-just-to-get-the-abi-definition
https://zhuanlan.zhihu.com/p/26089385

Heco 编译及多节点部署

运行环境

测试环境
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.tomlgenesis.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",

accountscoinbase都为预先生成的地址

后台运行geth

此时关闭前面运行的geth,重新后台运行

nohup ./geth --config geth.toml --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节点同步区块,其他节点同理加入

Heco链调研

官网

https://www.hecochain.com/zh-cn/

项目介绍

https://docs.hecochain.com/#/intro

白皮书

https://www.hecochain.com/developer.133bd45.pdf

区块浏览器

测试网

https://testnet.hecoinfo.com/

正式网

https://hecoinfo.com/

测试币水龙头

https://scan-testnet.hecochain.com/faucet

开发文档

https://docs.hecochain.com/#/

开源代码

链代码

https://github.com/HuobiGroup/huobi-eco-chain

系统合约

https://github.com/HuobiGroup/huobi-eco-contracts

链相关指数

  1. TPS: 500+
  2. 出块间隔:3s
  3. 共识机制: HPoS
  4. 最大验证节点数: 21
  5. 链上原生代币:HT
  6. 交易消耗: 手续费
  7. 出块节点更新时间:200区块
  8. 最小质押:32HT
  9. 赎回质押:86400区块

链接口和合约兼容

目前与ETH目前重叠部分基本一致

genesis

https://docs.hecochain.com/#/genesis

基于ETH的链修改调研

调研背景

目前有个项目计划基于ETH做链修改,完成类似DPOS版本的ETH,
主要是为了整合现有的ETH生态,以及一些商业需求。
也为后面EOS商业链中间层组件(IBC Relayer)做储备。

现有三方项目

https://github.com/HuobiGroup/huobi-eco-chain
https://github.com/meitu/go-ethereum
https://github.com/mingjingc/dpos-go-ethereum
https://github.com/TTCECO/gttc
https://github.com/linapex/ethereum-dpos-chinese

参考文档

https://zhuanlan.zhihu.com/p/38013479
https://www.jianshu.com/p/d99c0a5afbe8

WSL中设置DNS

由于公司gitlab搬到了vpn内,虽然Windows运行了Vpn软件,并在对应的VPN网卡上设置了域DNS,但是WSL走的子系统单独的DNS,所以虽然能ping通gitlab所在服务器IP,但是无法解析gitlab对应的域名。

设置WSL子系统DNS

1. 启动WSL,进入目录,创建wsl.conf
bash
cd ~/../../etc
sudo vim wsl.conf
sudo touch wsl.conf
2. 将这些行添加到wsl.conf中
[network]
generateResolvConf=false
3. 退出WSL,关闭WSL
exit
wsl --shutdown

此时,由于有了wsl.conf,run/resolvconf应该不再存在,并且将不再被创建

4. 删除现有的符号链接文件
cd ~/../../etc
sudo rm resolv.conf
5. 创建一个新的resolv.conf
sudo vim resolv.conf
sudo touch resolv.conf
将自己的DNS,添加到resolv.conf
nameserver 8.8.8.8 // 用您喜欢的功能名称服务器替换8.8.8.8。
重启WSL
exit
wsl --shutdown
再次启动WSL
bash

此时WSL解析内网域名就OK了

参考

https://github.com/microsoft/WSL/issues/5256#issuecomment-666545999