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  //接口设计: