github.com/turingchain2020/turingchain@v1.1.21/consensus/doc.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package consensus 6 7 //共识相关的模块 8 //模块功能:模块主要的功能是实现共识排序的功能,包括完整的共识的实现。 9 /** 10 1. solo 11 提供单节点排序功能,适用于开发过程,便于调试。 12 多节点情况下部署solo,只有主节点处理交易排序打包,其余节点不作处理。 13 主节点打包完之后,广播给其它节点。 14 15 2. raft 16 实现功能: 17 1 建立raft集群,建立成功后集群中只有一个leader节点,多个follower节点。leader节点和follower节点 18 之间通过http方式通信。 19 2 选定主节点,leader从mempool中获取交易列表,排除重复后打包。将日志写到wal中,再通过raft复制到其余的从节点。 20 3 leader,follower间设定心跳包来确认leader是否还存活,超时则触发leader切换。leader切换过程中共识 21 不会出错。 22 4 节点增加,删除。共识不受影响 23 5 配置文件中新增readOnlyPeers,增加只读节点,只读节点不参与共识,即当leader发生故障时,新的leader不会从只读节点中产生, 24 而是在共识节点中产生。 25 26 运行方式(3个节点): 27 运行环境: ubuntu 28 GO版本: go1.8.4 29 步骤: 30 // 1.编译版本 31 cd $GOPATH/src/gitlab.__officeSite__/turingchain 32 git clone git@gitlab.__officeSite__:turingchain/turingchain.git 33 cd turingchain 34 go build 35 36 // 2.从管理机上拷贝可执行文件到各个节点 37 scp turingchain ubuntu@172.31.8.229:/home/ubuntu/ 38 scp turingchain ubuntu@172.31.15.241:/home/ubuntu/ 39 scp turingchain ubuntu@172.31.4.182:/home/ubuntu/ 40 41 // 3.在各个节点上,依次修改turingchain.toml 42 name="raft" 43 minerstart=true 44 genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt" 45 nodeId=1 46 raftApiPort=9121 47 isNewJoinNode=false 48 peersURL="http://127.0.0.1:9021" 49 readOnlyPeersURL="http://172.31.2.210:9021,http://172.31.2.252:9021" 50 addPeersURL="" 51 // 4.然后依次启动种子节点,raft集群相关节点 52 ./turingchain 或者写个启动脚本 53 54 // 5.动态增删节点 55 动态加入节点 56 1.)先在原有的集群随意一台机器(leader和follower都可以)上面执行 57 curl -L http://127.0.0.1:9121/4 -X POST -d http://172.31.4.185:9021 58 注意:前者为要加入的nodeId 值,后面http地址为要加入的peerUrl地址,将peerURL依次追加到addPeersURL中, 59 用逗号分隔,一次只能添加一个节点 60 2.)然后在turingchain.toml配置文件中,写好相关参数,启动turingchain即可, 61 turingchain.toml配置文件可依据前一个节点的配置 62 修改如下参数: 63 nodeId=x //第几个节点 64 isNewJoinNode=true //是否为新增节点 65 addPeersURL="xxxxx" //新增节点的URL 66 67 动态删除节点 68 1.)在非删除节点执行如下curl命令即可 69 curl -L http://127.0.0.1:9121/4 -X DELETE 70 注解,表示要删除第四个节点,删除操作为不可逆操作,一旦删除,就不会能重新添加进来. 71 72 73 问题记录及解决: 74 1. 多节点之间时间不同步导致的告警:rafthttp: the clock difference against peer 3 is too high [53.958607849s > 1s] 75 需要同步ntp时间 76 77 3. pbft: 78 79 目前实现功能: 80 可以从mempool中读取交易,进行多节点pbft共识,共识完成后执行块。nodeid是1的节点默认是primary节点,其余节点不执行打包只参与共识。 81 节点之间通信方式为tcp。目前暂不支持增加、删除节点,需要先将所有节点都写在配置文件中。 82 //TODO :1、链的可持久化,每128个块增加检查点,清理之前的log,防止过于臃肿 83 2、增加视图变更,即在不影响共识过程的情况下变更primary节点 84 85 pbft文件夹中各个模块的主要功能: 86 pbft.go:定义pbft节点的结构,整个共识过程需要用到的函数 87 block.go: 让pbftclient继承baseclient,执行打包等任务然后通过chan传递给节点进行共识 88 controllor.go: 通过config文件生成新的pbft节点 89 pbft_test.go:单元测试文件 90 91 如何使用: 92 单节点测试:直接运行pbft_test即可,会写50个区块进行测试 93 多节点测试: 94 windows和linux均可 95 develop分支请先用protoc重新生成pb.go文件 96 首先下载pbftbranch,然后创建code.aliyun.com/turingchain文件夹,将解压出来的turingchain文件夹放入下面,进入turingchain文件夹 97 执行go build命令生成可执行文件 98 因为我是在一台电脑上进行测试,因此只需要在本机上拷贝文件即可,若需要在不同的电脑上进行测试,拷贝到不同电脑上即可 99 修改个节点的turingchain.toml即可,主要修改方式如下: 100 name = "pbft" 101 genesis = "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt" 102 minerstart = true 103 genesisBlockTime = 1514533394 104 hotkeyAddr = "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv" 105 NodeId = 1 //当前节点的id,每个节点需要不同,1是默认primary节点 106 PeersURL = "127.0.0.1:8890,127.0.0.1:8891" //所有节点的ip地址,用逗号隔开,我是一台电脑所以用的本地地址只是port不同 107 ClientAddr = "127.0.0.1:8890" //当前节点的ip地址 108 //TODO 动态增加或者删除节点 109 然后turingchain命令启动所有节点后,再向mempool写入交易validator 110 111 4.tendermint: 112 实现功能: 113 1 建立tendermint集群,如果要实现拜占庭容忍至少1个节点的能力,集群至少包含4个validator节点,建立成功后集群中的proposer将轮流从validator中选择,每次选中的proposer将成为提议者和写入区块者,提议(proposal)包含从mempool中取到的交易信息,所有validator节点参与对提议(proposal)投票。 114 2 投票分为两个阶段——prevote和precommit,首先每个validator对proposal进行第一阶段投票,当每个validator收到的投票结果比例大于2/3节点个数时,每个validator根据这个结果进行第二阶段投票,当每个validator根据收到的投票结果为nil的比例大于2/3节点个数时,将开始新一轮的提议,投票, 115 当收到的投票结果相同且不为nil的比例大于2/3节点个数时,进入commit阶段。该轮的proposer写区块,非proposer等待接收广播的新区块。之后进入新高度的共识。 116 3 整个共识过程中如果小于1/3的validator出现一些异常,不影响剩下validator继续共识。 117 4 动态增加,删除validator节点,修改validator节点权限,共识不受影响 118 5 仅支持创建集群时静态配置validator,不支持通过停止所有validator,修改genesis.json配置文件来增加,删除validator节点,修改validator节点权限的操作。 119 120 运行方式(4个节点): 121 运行环境: ubuntu 122 GO版本: go1.9.2 123 步骤: 124 // 1.编译版本 125 cd $GOPATH/src/gitlab.__officeSite__/turingchain 126 git clone git@gitlab.__officeSite__:turingchain/turingchain.git 127 cd turingchain 128 go build 129 130 // 2.从管理机上拷贝可执行文件到各个节点 131 scp turingchain ubuntu@192.168.0.117:/home/ubuntu/ 132 scp turingchain ubuntu@192.168.0.119:/home/ubuntu/ 133 scp turingchain ubuntu@192.168.0.120:/home/ubuntu/ 134 scp turingchain ubuntu@192.168.0.121:/home/ubuntu/ 135 136 // 3.在各个节点上,依次修改turingchain.toml中[consensus]项 137 name="tendermint" 138 minerstart=false 139 genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt" 140 genesisBlockTime=1514533394 141 hotkeyAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv" 142 timeoutPropose=5000 143 timeoutProposeDelta=500 144 timeoutPrevote=3000 145 timeoutPrevoteDelta=500 146 timeoutPrecommit=3000 147 timeoutPrecommitDelta=500 148 timeoutCommit=3000 149 skipTimeoutCommit=false 150 createEmptyBlocks=false 151 createEmptyBlocksInterval=0 152 seeds=["192.168.0.117:46656","192.168.0.119:46656","192.168.0.120:46656","192.168.0.121:46656"] 153 // 4.然后依次启动种子节点,tendermint集群相关节点 154 ./turingchain 或者写个启动脚本 155 // 5.动态增删节点 156 动态加入节点 157 1.)将新生成的priv_validator.json文件和其他Validator节点的genesis.json和turingchain.toml拷贝到待加入集群的节点工作目录下,然后启动turingchain。 158 注意:可以修改turingchain.toml文件的[p2p]项和[consensus]项中的seeds参数,只要是集群节点就可以。 159 2.)将新节点的priv_validator.json文件中的pub_key记录下来,向集群任一节点发送交易,执行器为valnode,构建payload为ValNodeAction结构体的序列化, 160 该结构体参数Value为ValNodeAction_Node结构体地址,Ty为1,ValNodeAction_Node结构体有两个参数,PubKey为刚才记录下的字符串通过hex.DecodeString()编码生成的[]byte, 161 Power最大不能超过总power值的1/3。该笔交易执行成功即添加完成,新节点将会参与新区块的共识。 162 注意:新增节点的Power值一定不能超过总power值的1/3,否则就是该笔交易执行成功了,该节点也不能成功加入。 163 动态删除节点 164 1.)同加入节点一样,向任意节点发送一笔交易,交易格式与加入节点一样,其中pub_key为要删除的节点的pub_key,Power设置为0,该节点将不会参与新区块的共识。 165 动态修改validator的Power值 166 1.)同加入节点一样,向任意节点发送一笔交易,交易格式与加入节点一样,其中pub_key为要修改的节点的pub_key,Power为要设置的值, 167 注意:修改的Power值一定不能超过总power值的1/3,否则就是该笔交易执行成功了,该节点的Power值也不会更改。 168 */ 169 //接口设计: