以太坊搭建联盟链

 

 

1 安装前的准备

1.1 配置Linux系统

本文配置的为windows下的VMware软件下搭建的Linux下的cent0S-7系统,推荐系统有CentOS 7和Ubuntu 16.04有条件的可以用云服务器上的Linux系统,好处是可以搭建广域网联盟链。

本文默认你已经对以太坊和docker技术有一定的掌握和了解,并部署好相应的环境。如果你还未准备好,请参考芯链公众号前期发布的环境搭建和部署文章。

1.2 安装Docker

请使用管理员权限进行安装,

# su root

安装Docker(请参考芯链公众号发布的安装指导文章):

CentOS: yum -y install docker-io

Ubuntu: apt-get install docker-engine

安装完毕如图:

然后启动Docker服务:

#service docker start

校验docker是否安装成功:

#docker run hello-world

这个命令会下载一个测试镜像,并且运行在一个容器中。当容器运行时,他会打印一些信息,并且退出。下图表示Docker已经安装完成。

2 安装bootnode

2.1 下载bootnode镜像

运行命令如下命令:

#docker pull docker.io/hawyasunaga/ethereum-bootnode

查看镜像:docker images

2.2 Docker创建bootnode容器节点

生成引导节点:

1
#docker run -itd -m 512M --privileged=true --memory-swap -1 --net=host -p 30301:30301/udp -p 30301:30301/tcp -v /path/docker/bootnode:/root/bootnode --name genbootnode docker.io/hawyasunaga/ethereum-bootnode bootnode --genkey=/root/bootnode/boot.key

运行引导节点:

1
#docker run -itd -m 512M --privileged=true --memory-swap -1 --net=host -p 30301:30301/udp -p 30301:30301/tcp -v /path/docker/bootnode:/root/bootnode --name bootnode docker.io/hawyasunaga/ethereum-bootnode bootnode --nodekey=/root/bootnode/boot.key

注意:这两个命令参数中,-v /path/docker/bootnode:/root/bootnode为映射路径,在docker的这个bootnode容器中,出现容器内/root/bootnode路径都映射为外部路径/path/docker/bootnode。下方以太坊容器搭建节点命令同理。

2.3 查看bootnode日志得到节点

1
#docker logs -f bootnode 

得到节点如下:

将[::]替换为本机IP地址

好了,用于连接的根节点运行完毕。

3 安装以太坊节点

可以找台Linux进行节点联盟链的搭建了,这里继续以centos7继续演示了。

3.1 创建以太坊的创世文件

新建创世文件genesis.json,内容如下:

1
2
3
4
5
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 
{

  "config": {

 "chainId": 90,   "homesteadBlock": 0,   "eip155Block": 0,   "eip158Block": 0   },   "alloc": {"0x5f38056f45091ee992298e53681b0a60c999ff95":{"balance": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7"}},   "coinbase" : "0x5f38056f45091ee992298e53681b0a60c999ff95",   "extraData" : "0x2017",   "nonce" : "0xdeadbeefdeadbeeF",   "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",   "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",   "timestamp" : "0x00",   "gasLimit": "0xffffffff",   "difficulty": "0x20000"  }

3.2 初始化创世文件

首先新建一个准备放置以太坊目录的文件,将genesis.json文件放入该地址,本文为/home/admin下:

运行如下命令

1
#docker run -itd --privileged=true -v /home/admin:/root/ethdev --name gethDev1 ethereum/client-go --datadir /root/ethdev --networkid 8765639736937780 init /root/ethdev/genesis.json

请记住—networkid 8765639736937780,这是当前搭建联盟链的ID。

查看日志文件:docker logs -f gethDev1

初始化成功。

3.3 Docker创建以太坊容器节点

运行如下命令

1
#docker rm -f gethDev1

1
#docker run -itd -m 512M --privileged=true --network=host --memory-swap -1 --net=host -p 8545:8545 -p 40303:40303 -v /home/admin:/root/ethdev --name gethDev1 ethereum/client-go --ipcdisable --port 40303 --bootnodes "enode://ad6aff917c6e8bd40cb20af4eac6ce05c16d285125b46f17fc9b5c3b0a833bd21667231215949c6ff771ba512eb8f87f138ac6679852997c3eaec1d349561d20@120.25.162.110:30301" --bootnodesv4 "enode://ad6aff917c6e8bd40cb20af4eac6ce05c16d285125b46f17fc9b5c3b0a833bd21667231215949c6ff771ba512eb8f87f138ac6679852997c3eaec1d349561d20@120.25.162.110:30301" --bootnodesv5 "enode://ad6aff917c6e8bd40cb20af4eac6ce05c16d285125b46f17fc9b5c3b0a833bd21667231215949c6ff771ba512eb8f87f138ac6679852997c3eaec1d349561d20@120.25.162.110:30301" --debug --rpcapi "db,eth,net,web3,personal,admin,miner,txpool" --datadir /root/ethdev --networkid 8765639736937780 --wsapi "db,eth,net,web3,personal,admin,miner,txpool" --ws --wsaddr "0.0.0.0" --rpc --rpcaddr "0.0.0.0" --cache=512 --verbosity 3 console

//enode为上面运行bootnode得到的节点,并将预备的私钥文件放入keystore中,并且—networkid 8765639736937780为联盟链的标识ID。

查看控制台日志:docker logs -f gethDev1

Ok,节点搭建成功。

3.4 验证联盟链的连接

在上一步搭建好节点后,等待一段时间,让节点自动连接根节点bootnode。

进入以太坊容器中:

1
#docker attach gethDev1

输入命令:admin

查看peer是否连接:

OK,连接完成,联盟链搭建完成。

连接完成后,开始同步区块:

注意:这里连接的是之前已经加入bootnode根节点的其他节点,与根节点的连接并不会显示在peers中。如果是第一个连接bootnode的节点,连接了bootnode的时候输入admin,peers是空的,需要继续搭建一个节点来测试他们互相连接。

感谢HPB团队整理。

HPB51:RLPx加密握手协议研究

JUL 26TH, 2018

加密握手协议全局位置

Server服务器作为上层使用的接口,直接调用Start启动。Start完成启动监听端口、连接以及建立通信的任务。在运行中,Star通过创建多个goroutine,并将goroutine的结果通过channel形式汇聚给run进行集中处理。当用户间建立节点以后,通过Msg格式进行通信。其中

newTransport 是和节点建立连接(tcp或者udp)后进行协商密钥、协议握手的地方,通过rlpx协议来进行握手。除了建立rlpx握手,在运行通信的整个过程中,需要进行如下判断:

加密握手协议流程

加密握手细节描述

关键步骤补充:

  生成Authpacket(Dialing执行) 接收AuthPacket(Listening执行)
  1.创建enchandshake结构体,该结构体包含 Initiator(bool) RemoteID(discover.NodeID) remotePub(ecies.pk) initNonce, respNonce(byte) randomPrivateKey(ecies.sk) remoteRandomPub(ecies.pk) 1.创建authMsgV4结构体 gotPlain(bool) initiatorPubkey(byte) Signature(byte) Nonce(byte) Version(unit) |
  2.执行makeAuthMsg方法: 1)将romteID恢复为公钥remotePub 其中ECDSA公钥作为ECIES公钥 2) 生成随机intiator nonce 3)生成随机ECDH密钥randomPrivKey 4)对信息签名得到signature(见附录) 处理后输出AuthMsgV4格式的数据 发送的数据包括: Version(=4) Nonce(随机生成)InitiatorPubKey(本地sk参与) Signature 2.读取authMsg操作readHandshakeMsg ◑ 若为pre-EIP8: 1) 将ECDSA私钥作为ECIES私钥 2) 通过私钥解密ECIES密文为明文 3) 对明文进行解码 ◑ 若为EIP8格式: 1) 增加前缀并连接 2) 解密为明文 3) 对明文进行解码 解码后的[]byte赋值给s作为authPacket |
  3.生成经过封装的AuthPacketAuthPacket=sealEIP8(AuthMsg) 封装过程如下: 1) rlp编码 2) 填充随机数据使总长至少到100byte 3) 加前缀 4) 进行ECIES加密(remotePub) |
  生成authRespPacket(Listening执行) 接收authRespPacket(Dialing执行)
  1.创建enchandshake结构体(同前) 1.创建authRespV4结构体 RandomPubkey(byte) Nonce(byte) Version(unit) |
  2.处理authMsg操作, 通过handleAuthMsg方法 1)将远端的身份传入,其中包括 ◑ nonce值传入给initNonce ◑ 将initiatorPK恢复为remotePub 其中ECDSA公钥作为ECIES公钥 2)生成随机ECDH私钥randomPrivKey 3)检查签名signature,并 恢复出remoteRandomPub 2.读取authRespMsg操作, 使用readHandshakeMsg方法 ◑ 若为pre-EIP8: 1) 将ECDSA私钥作为ECIES私钥 2) 通过私钥解密ECIES密文为明文 3) 对明文进行解码 ◑ 若为EIP8格式: 1) 增加前缀并连接 2) 解密为明文 3) 对明文进行解码 解码后byte赋值给s作为authRespPacket |
  3. 执行makeAuthMsg方法: 1)生成随机respNonce 2)创建authRespV4结构体 该结构体包括: RandomPubKey Nonce Version 3)对结构体进行copy赋值 处理后输出AuthRespV4格式的数据 发送的数据包括:Version(=4) Nonce(随机生成)RespPubKey(本地sk参与) 3.创建enchandshake结构体(同前) |
  4.生成经过封装的AuthRespPacket ◑ 若为明文格式: 需通过ECIES进行加密(remotePub)authRespPacket=sealPlain(AuthMsg) ◑ 若为非明文格式: 进行EIP8封装(同前)authRespPacket=sealEIP8(AuthMsg) 4.处理authResp操作handleAuthResp 1)读取nonce 2)将RandomPubKey恢复为remoteRandomPub 其中将输入的PK去编组化,并 将ECDSA公钥作为ECIES公钥 |

感谢HPB团队整理。

HPB50:主流共识算法分析

JUL 3RD, 2018

区块链核心框架

区块链是一个不断增长的分布式账本[2],账本用“区块”的形式衔接在一起,区块中包含交易, 时间戳,随机数等元数据,每个区块中含有一个指针指向上一个交易链接,区块链的设计是安 全的,因为其具有良好的拜占庭容错能力。区块链可以概括为一个分布式的高频交易系统,如 下图 1 所示,区块链的核心技术可以总结为四部分:分布式的数据库,密码学相关理论,共识机制和 P2P 网络。

中分布式数据库负责数据的写入与读取,密码学中非对称密钥和 HASH 等算法来标识交易者的身份和保证系统的完整性;对等网络是系统运行的基础;共识算法用来保证交易信息在整个账本不同节点中写入的一致性,常用的共识算法有 POW, POS, DPOS 等。

共识算法与 CAP 理论

共识算法是为了解决在对等网络中(P2P),相互独立的节点如何达成一项决议问题的过程。简而言之,共识算法是在解决分布式系统中如何保持一致性的问题。关于此部分的讨论较为成熟和最为广泛接受的理论是 CAP 理论。CAP 由 Eric Brewer )在 2000 年 PODC 会议上提出[4],并提出分布式系统不能同时完全满足 CAP 三个要求的假设,其中包括如下三个方面:

Consistency: 一致性 从不同节点读取的数据一致。一致性是指数据的原子性,在经典的数据库中通过事务来保障,事务完成时,无论成功或回滚,数据都会处于一致的状态,在分布式环境下,一致性是指多个节点数据是否一致。

Availability: 可用性是指服务及时非错误地响应,服务一直保持可用的状态,当用户发出一个请求,服务能在一定的时间内返回结果,响应可终止、不会一直等待。

Partition tolerance:分区容错性即可靠性。可靠性的量化指标是周期内系统平均无故障运行时间. 即使有些消息延迟或者无法到达,并不影响系统的整体运行。简而言之,在网络分区的情况下,被分隔的节点仍能正常对外服务。

和所有分布式系统一样,区块链共识算法设计也是在权衡上面的三个因素,假如区块链中节点能立即确认交易数据,好处是不依赖其他节点立即可用,满足了 CAP 理论中的 AP,可风险是失去了强一致性,其他节点可能丢弃这个区块,因为区块所在的区块链分叉在竞争性的选举中失败了[5]。 为了获得 CP,客户端应该等待区块链大多数节点接受了这笔交易在真正接受它, 说明这笔交易所在分叉已经选举胜利,获得大部分共识,获得了强一致性,但是风险是可能unavailable ,丧失 CAP 的 A,因为网络分区通信等问题可能阻止这种共识。

研究定位

区块链系统是一个将交易数据正确地固化在分布式节点上的系统。共识算法为了解决如何更安全有效的将交易数据写入到区块链上,本质上讲,共识算法旨在解决以下问题:

  • 哪个服务节点有权利生成下一个用新区块?
  • 上一个区块与下一个区块之间应如何衔接
  • 下一个区块什么时间产生?
  • 区块中应该包含了哪些内容?
  • 区块的大小是多少,一个区块中包含多少交易数据?
  • 确认机制如果解决区块链分叉的问题?

本文档从多个角度分析不同共识算法关于以上问题的解决方案,旨在为将来实际算法设计提供相关理论参考,分析方法为以下两点:

  • 纵向分析:我们以一个交易的被确认的完整过程,勾画出整个区块链系统的工作过程,纵向的分析共识算法在整个区块链系统中所扮演的角色。
  • 横向对比:我们陈列出当前加密货币中常用的共识算法,如 POW,POS,DPOS,PBFT 等,然后从算法的一致性,容错性,网络组织情况等方面进行对比分析。

纵向定位分析

研究共识机制旨在设计更安全,高效的区块产生方案。为了让读者更加清晰的认识共识算法在整个区块链中所扮演的角色,在本章中我们勾画出区块产生的完整周期,并用以比特币的例子详细的讲解区块产生的过程。

图 2. 交易数据在区块链中被确认的过程

图 2 中展示了交易数据在区块链中一个完整的流转过程,在起始阶段,交易信息被客户端组装, 其中交易信息包含了交易的输入金额,输入账户信息和输出账户信息等,客户端可以被认为是 全节点钱包,轻钱包和各大交易平台。在一个完整的交易被生成后被称为“原始交易(Raw

Transaction)”。 原始交易并不能被矿机接收,因为缺乏相应转账人的签名。在转账人签名完成后允许将其广播到区块链系统中,矿机采集相关交易后,经过共识算法将交易数据打包并确认到对等网络中的其他节点上。下面我们以比特的例子详细阐述以上过程。

交易数据的组装

假设用户 A 给用户 B 进行转账,用户 A 的的公钥为 Pk_a,私钥为 Pr_b, 用户 B 的的公钥为Pk_b,私钥为 Pr_b. 我们按照表 1 给出的协议一步一步的给出最终可广播的内容。备注: 以下数据均为十六进制表示,我们采用比特币中最常用的 Pay-to-PubkeyHash 进行分解。经过客户端的数据组合,我们展示一个完整的交易协议如下,其中输入数据 inputs 数据可以从UTXO(Unspent Transaction Output,未开销的比特币交易输出)中获取。

表 1. 比特币原始区块链交易协议

  Version (版本)   01000000
  Input count (输入长度)   01 |
  inputs previous output hash (上一个脚本的 hash) be66e10da854e7aea9338c1f91cd4897 68d1d6d7189f586d7a3613f2a24d5396 |
  inputs previous output index (上一个交易的索引) 00000000 |
  inputs scriptSig length (表示脚本的长度) 19 |
  inputs scriptSig(脚本签名,实际此部分为脚本的前半部分) 76a914010966776006953d5567439e5e 39f86a0d273bee88ac |
  inputs Sequence (序列) ffffffff |
  outputs count (输出长度)   01 |
  outputs Value (需要转出的比特币的值,上面的输入的值减去) 605af40500000000 |
  outputs script length (表示脚本的长度) 19 |
  outputs script(脚本签名,实际此部分为脚本的前后半部分) 76a914097072524438d003d23a2f23ed b65aae1bb3e46988ac |
  lock time (锁定时间)   00000000 |

交易数据的签名

交易数据的完成组装后并不能立即被矿机所接受,因为交易的输出方并没有对其进行有效的签名,我们用 sha256 整体对上面的数据的 hash 进行签名,我们假设发送者的公钥是 Pk_a, 签名后的结果为 Sig_a. 为更好的理解签名后在区块链中执行的过程,我们将上面 inputs 中的scriptSig 进行分解76a914010966776006953d5567439e5e39f86a0d273bee88ac 分解后的内容如下表格,表 2. 未签名的 ScriptSig 数据格式分解,备注数字与操作符的对应关系可以通过https://en.bitcoin.it/wiki/Script 查询到,ScriptSig 格式如下:

  OP_DUP 76
  OP_HASH160 a9 |
  length 14 |
  pubKeyHash 010966776006953d5567439e5e39f86a0d273bee |
  OP_EQUALVERIFY 88 |
  OP_CHECKSIG ac |

经过签名之后我们将签名后的数据衔接在 ScriptSig 上面,因此最终的 ScriptSig 变成如下格式。表 3. 签名后的 ScriptSig 数据格式分解。

  Sig_a Sig_a.
  Pk_a Pk_a |
 
1. 安装Ubuntu系统 首先需要在服务器上安装Ubuntu系统(建议使用16.04及以上版本)。可以使用云服务器或者本地安装。 2. 安装Geth Geth是以太坊的官方客户端,可以用于搭建私有链和联盟链。可以使用以下命令安装: sudo add-apt-repository -y ppa:ethereum/ethereum sudo apt-get update sudo apt-get install -y ethereum 安装完成后,可以使用以下命令查看版本号: geth version 3. 创建创世块 首先需要创建创世块,创世块是区块链的第一个区块,包含了一些初始化的信息,如初始账户、初始余额、挖矿难度等。可以使用以下命令创建创世块: geth --datadir /path/to/chaindata init /path/to/genesis.json 其中,/path/to/chaindata为存储区块链数据的路径,/path/to/genesis.json为创世块的配置文件。 4. 启动节点 使用以下命令启动节点: geth --datadir /path/to/chaindata --networkid 1234 --nodiscover --rpc --rpcaddr "0.0.0.0" --rpcport 8545 --rpcapi "eth,web3,personal,net" console 其中,/path/to/chaindata为存储区块链数据的路径,--networkid指定联盟链的ID,--nodiscover禁用节点发现功能,--rpc启用RPC服务,--rpcaddr指定RPC服务监听的IP地址,--rpcport指定RPC服务监听的端口号,--rpcapi指定可用的RPC接口,console表示启动控制台。 5. 创建账户 在控制台中使用以下命令创建账户: personal.newAccount("password") 其中,password为账户的密码。 6. 启动挖矿 使用以下命令启动挖矿: miner.start() 7. 部署智能合约 使用Solidity编写智能合约代码,并使用Remix或Truffle等工具进行编译和部署。 以上就是在Ubuntu系统上搭建以太坊联盟链的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值