From 6f220dc1c39ae4d4738c5f4b1923e248dedd813a Mon Sep 17 00:00:00 2001 From: wuwei1972 Date: Fri, 20 Mar 2020 00:44:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9B=AE=E6=A0=87=EF=BC=9A?= =?UTF-8?q?=E5=85=B1=E8=AF=86=E6=8A=BD=E8=B1=A1=EF=BC=8C=E8=BE=BE=E5=88=B0?= =?UTF-8?q?=E5=85=B1=E8=AF=86=E5=88=87=E6=8D=A2=E3=80=82=20=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=85=B1=E8=AF=86=E5=B1=82=E7=9A=84=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=8A=BD=E8=B1=A1=EF=BC=8C=E5=B9=B6=E5=AE=9E=E7=8E=B0=E4=BA=86?= =?UTF-8?q?cfrd=E3=80=81raft=E5=8D=8F=E8=AE=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/system.conf | 4 +- .../scala/rep/app/system/ClusterSystem.scala | 5 +- .../scala/rep/network/base/BaseActor.scala | 1 + ...ctionPool.scala => ITransactionPool.scala} | 89 ++---- .../cache/cfrd/TransactionPoolOfCFRD.scala | 22 ++ .../cache/raft/TransactionPoolOfRAFT.scala | 22 ++ .../confirmblock/IConfirmOfBlock.scala | 78 +++++ .../confirmblock/common/ConfirmOfBlock.scala | 97 ++++++ .../raft/ConfirmBlockOfRAFT.scala | 68 +++++ .../network/consensus/cfrd/MsgOfCFRD.scala | 56 ++++ .../consensus/cfrd/block/Blocker.scala | 265 ----------------- .../consensus/cfrd/block/BlockerOfCFRD.scala | 71 +++++ .../consensus/cfrd/block/ConfirmOfBlock.scala | 167 ----------- .../cfrd/block/EndorseCollector.scala | 20 +- .../block/EndorsementRequest4Future.scala | 23 +- .../endorse/DispatchOfRecvEndorsement.scala | 7 +- .../consensus/cfrd/endorse/EndorseMsg.scala | 53 ---- .../cfrd/endorse/Endorser4Future.scala | 29 +- .../network/consensus/cfrd/vote/Voter.scala | 223 -------------- .../consensus/cfrd/vote/VoterBase.scala | 50 ---- .../consensus/cfrd/vote/VoterOfCFRD.scala | 92 ++++++ .../consensus/common/MsgOfConsensus.scala | 34 +++ .../common/algorithm/IAlgorithmOfVote.scala | 24 ++ .../algorithm/IRandomAlgorithmOfVote.scala} | 55 +--- .../consensus/common/block/IBlocker.scala | 141 +++++++++ .../consensus/common/vote/IVoter.scala | 89 ++++++ .../consensus/raft/block/BlockerOfRAFT.scala | 100 +++++++ .../consensus/raft/vote/VoterOfRAFT.scala | 106 +++++++ .../network/consensus/util/BlockHelp.scala | 4 +- .../block => genesis}/GenesisBlocker.scala | 67 ++--- .../scala/rep/network/module/IModule.scala | 4 + .../rep/network/module/IModuleManager.scala | 15 +- .../rep/network/module/ModuleActorType.scala | 5 + .../network/module/cfrd/CFRDActorType.scala | 5 + .../module/cfrd/ModuleManagerOfCFRD.scala | 38 ++- .../module/raft/ModuleManagerOfRAFT.scala | 46 +++ .../rep/network/persistence/BlockCache.scala | 6 +- .../{Storager.scala => IStorager.scala} | 134 ++++----- .../persistence/cfrd/StoragerOfCFRD.scala | 26 ++ .../persistence/raft/StoragerOfRAFT.scala | 26 ++ src/main/scala/rep/network/sync/SyncMsg.scala | 6 + .../sync/SynchronizeRequester4Future.scala | 275 ------------------ .../ISynchAnalyzer.scala} | 176 ++--------- .../parser/cfrd/ICFRDOfSynchAnalyzer.scala | 67 +++++ .../sync/parser/raft/IRAFTSynchAnalyzer.scala | 75 +++++ .../sync/request/ISynchRequester.scala | 194 ++++++++++++ .../request/cfrd/SynchRequesterOfCFRD.scala | 75 +++++ .../request/raft/SynchRequesterOfRAFT.scala | 79 +++++ .../{ => response}/SynchronizeResponser.scala | 29 +- .../scala/rep/network/tools/NodeMgr.scala | 6 + .../tools/transpool/TransactionPoolMgr.scala | 4 + .../transaction/DispatchOfPreload.scala | 7 +- .../transaction/PreloaderForTransaction.scala | 9 +- .../scala/rep/sc/TransactionDispatcher.scala | 26 +- src/test/scala/rep/sc/BlockStubActor.scala | 9 +- 55 files changed, 1881 insertions(+), 1523 deletions(-) rename src/main/scala/rep/network/cache/{TransactionPool.scala => ITransactionPool.scala} (62%) create mode 100644 src/main/scala/rep/network/cache/cfrd/TransactionPoolOfCFRD.scala create mode 100644 src/main/scala/rep/network/cache/raft/TransactionPoolOfRAFT.scala create mode 100644 src/main/scala/rep/network/confirmblock/IConfirmOfBlock.scala create mode 100644 src/main/scala/rep/network/confirmblock/common/ConfirmOfBlock.scala create mode 100644 src/main/scala/rep/network/confirmblock/raft/ConfirmBlockOfRAFT.scala create mode 100644 src/main/scala/rep/network/consensus/cfrd/MsgOfCFRD.scala delete mode 100644 src/main/scala/rep/network/consensus/cfrd/block/Blocker.scala create mode 100644 src/main/scala/rep/network/consensus/cfrd/block/BlockerOfCFRD.scala delete mode 100644 src/main/scala/rep/network/consensus/cfrd/block/ConfirmOfBlock.scala delete mode 100644 src/main/scala/rep/network/consensus/cfrd/endorse/EndorseMsg.scala delete mode 100644 src/main/scala/rep/network/consensus/cfrd/vote/Voter.scala delete mode 100644 src/main/scala/rep/network/consensus/cfrd/vote/VoterBase.scala create mode 100644 src/main/scala/rep/network/consensus/cfrd/vote/VoterOfCFRD.scala create mode 100644 src/main/scala/rep/network/consensus/common/MsgOfConsensus.scala create mode 100644 src/main/scala/rep/network/consensus/common/algorithm/IAlgorithmOfVote.scala rename src/main/scala/rep/network/consensus/{cfrd/vote/CRFDVoter.scala => common/algorithm/IRandomAlgorithmOfVote.scala} (61%) create mode 100644 src/main/scala/rep/network/consensus/common/block/IBlocker.scala create mode 100644 src/main/scala/rep/network/consensus/common/vote/IVoter.scala create mode 100644 src/main/scala/rep/network/consensus/raft/block/BlockerOfRAFT.scala create mode 100644 src/main/scala/rep/network/consensus/raft/vote/VoterOfRAFT.scala rename src/main/scala/rep/network/{consensus/cfrd/block => genesis}/GenesisBlocker.scala (75%) create mode 100644 src/main/scala/rep/network/module/raft/ModuleManagerOfRAFT.scala rename src/main/scala/rep/network/persistence/{Storager.scala => IStorager.scala} (70%) create mode 100644 src/main/scala/rep/network/persistence/cfrd/StoragerOfCFRD.scala create mode 100644 src/main/scala/rep/network/persistence/raft/StoragerOfRAFT.scala delete mode 100644 src/main/scala/rep/network/sync/SynchronizeRequester4Future.scala rename src/main/scala/rep/network/sync/{SynchResponseInfoAnalyzer.scala => parser/ISynchAnalyzer.scala} (52%) create mode 100644 src/main/scala/rep/network/sync/parser/cfrd/ICFRDOfSynchAnalyzer.scala create mode 100644 src/main/scala/rep/network/sync/parser/raft/IRAFTSynchAnalyzer.scala create mode 100644 src/main/scala/rep/network/sync/request/ISynchRequester.scala create mode 100644 src/main/scala/rep/network/sync/request/cfrd/SynchRequesterOfCFRD.scala create mode 100644 src/main/scala/rep/network/sync/request/raft/SynchRequesterOfRAFT.scala rename src/main/scala/rep/network/sync/{ => response}/SynchronizeResponser.scala (88%) diff --git a/conf/system.conf b/conf/system.conf index face71a9..350af868 100644 --- a/conf/system.conf +++ b/conf/system.conf @@ -188,7 +188,7 @@ system { #For config manually 手工设置超时时间,系统主动采用手工设置的时间,可以不用设置 block = 90#出块的超时时间 endorse = 3#背书超时时间,单位为秒 - transaction_preload = 1 + transaction_preload = 10 sync_chain = 15#链同步的超时时间 transcation_waiting = 900#交易在交易池中等待入块到的超时时间,单位是秒 } @@ -196,7 +196,7 @@ system { consensus { #共识类型,目前只支持一种 - type = "CRFD" + type = "RAFT"//内置三种共识协议,CFRD、RAFT、PBFT blocknumberofraft = 100 } diff --git a/src/main/scala/rep/app/system/ClusterSystem.scala b/src/main/scala/rep/app/system/ClusterSystem.scala index 8a8e2520..09834a8e 100644 --- a/src/main/scala/rep/app/system/ClusterSystem.scala +++ b/src/main/scala/rep/app/system/ClusterSystem.scala @@ -40,6 +40,7 @@ import rep.log.RepLogger import scala.concurrent.Await import scala.concurrent.duration._ import akka.actor.Terminated +import rep.network.module.raft.ModuleManagerOfRAFT /** @@ -276,10 +277,10 @@ class ClusterSystem(sysTag: String, initType: Int, sysStart: Boolean) { } val typeConsensus = SystemProfile.getTypeOfConsensus - if (typeConsensus == "CRFD") { + if (typeConsensus == "CFRD") { moduleManager = sysActor.actorOf(ModuleManagerOfCFRD.props("modulemanager", sysTag, enableStatistic, enableWebSocket, true), "modulemanager") }else if(typeConsensus == "RAFT"){ - + moduleManager = sysActor.actorOf(ModuleManagerOfRAFT.props("modulemanager", sysTag, enableStatistic, enableWebSocket, true), "modulemanager") }else if(typeConsensus == "PBFT"){ }else{ diff --git a/src/main/scala/rep/network/base/BaseActor.scala b/src/main/scala/rep/network/base/BaseActor.scala index 76842da7..a2835d47 100644 --- a/src/main/scala/rep/network/base/BaseActor.scala +++ b/src/main/scala/rep/network/base/BaseActor.scala @@ -31,6 +31,7 @@ trait BaseActor extends Actor { var schedulerLink: akka.actor.Cancellable = null + //implicit def scheduler = context.system.scheduler /** diff --git a/src/main/scala/rep/network/cache/TransactionPool.scala b/src/main/scala/rep/network/cache/ITransactionPool.scala similarity index 62% rename from src/main/scala/rep/network/cache/TransactionPool.scala rename to src/main/scala/rep/network/cache/ITransactionPool.scala index c1d3d6b4..04617450 100644 --- a/src/main/scala/rep/network/cache/TransactionPool.scala +++ b/src/main/scala/rep/network/cache/ITransactionPool.scala @@ -1,65 +1,30 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - package rep.network.cache -import java.security.cert.Certificate - -import com.google.protobuf.ByteString -import akka.actor.{Actor, Address, Props} -import akka.cluster.pubsub.DistributedPubSubMediator.Publish +import akka.actor.{Address, Props} import rep.app.conf.SystemProfile import rep.crypto.cert.SignTool -import rep.network.base.ModuleBase -import rep.network.cache.TransactionPool.CheckedTransactionResult -import rep.network.consensus.cfrd.vote.Voter.VoteOfBlocker -import rep.protos.peer.ChaincodeId -import rep.protos.peer.{Event, Transaction} -import rep.storage.IdxPrefix.WorldStateKeyPreFix -import rep.storage.ImpDataAccess -import rep.utils.{ActorUtils, GlobalUtils} -import rep.utils.GlobalUtils.EventType -import rep.utils.SerializeUtils import rep.log.RepLogger import rep.network.autotransaction.Topic +import rep.network.base.ModuleBase +import rep.network.cache.ITransactionPool.CheckedTransactionResult import rep.network.util.NodeHelp -import rep.network.module._ -import rep.network.module.cfrd.CFRDActorType +import rep.protos.peer.{Event, Transaction} +import rep.storage.ImpDataAccess +import rep.utils.ActorUtils +import rep.utils.GlobalUtils.EventType /** - * 交易缓冲池伴生对象 - * - * @author shidianyue - * @version 1.0 + * Created by jiangbuyun on 2020/03/19. + * 抽象的交易池actor */ -object TransactionPool { - def props(name: String): Props = Props(classOf[TransactionPool], name) + +object ITransactionPool{ + def props(name: String): Props = Props(classOf[ITransactionPool], name) //交易检查结果 case class CheckedTransactionResult(result: Boolean, msg: String) - } -/** - * 交易缓冲池类 - * - * @author shidianyue - * @version 1.0 - * @param moduleName - */ -class TransactionPool(moduleName: String) extends ModuleBase(moduleName) { +abstract class ITransactionPool (moduleName: String) extends ModuleBase(moduleName) { import akka.actor.ActorSelection private val transPoolActorName = "/user/modulemanager/transactionpool" @@ -93,15 +58,15 @@ class TransactionPool(moduleName: String) extends ModuleBase(moduleName) { def checkTransaction(t: Transaction, dataAccess: ImpDataAccess): CheckedTransactionResult = { var resultMsg = "" var result = false - + if(SystemProfile.getHasPreloadTransOfApi){ val sig = t.getSignature val tOutSig = t.clearSignature //t.withSignature(null) val cert = sig.getCertId - + try { val siginfo = sig.signature.toByteArray() - + if (SignTool.verify(siginfo, tOutSig.toByteArray, cert, pe.getSysTag)) { if (pe.getTransPoolMgr.findTrans(t.id) || dataAccess.isExistTrans4Txid(t.id)) { resultMsg = s"The transaction(${t.id}) is duplicated with txid" @@ -121,16 +86,20 @@ class TransactionPool(moduleName: String) extends ModuleBase(moduleName) { CheckedTransactionResult(result, resultMsg) } + protected def sendVoteMessage:Unit + private def addTransToCache(t: Transaction) = { val checkedTransactionResult = checkTransaction(t, dataaccess) - //签名验证成功 - if((checkedTransactionResult.result) && (SystemProfile.getMaxCacheTransNum == 0 || pe.getTransPoolMgr.getTransLength() < SystemProfile.getMaxCacheTransNum) ){ - pe.getTransPoolMgr.putTran(t, pe.getSysTag) - RepLogger.trace(RepLogger.System_Logger,this.getLogMsgPrefix(s"${pe.getSysTag} trans pool recv,txid=${t.id}")) - //广播接收交易事件 - if (pe.getTransPoolMgr.getTransLength() >= SystemProfile.getMinBlockTransNum) - pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker - } + //签名验证成功 + val poolIsEmpty = pe.getTransPoolMgr.isEmpty + if((checkedTransactionResult.result) && (SystemProfile.getMaxCacheTransNum == 0 || pe.getTransPoolMgr.getTransLength() < SystemProfile.getMaxCacheTransNum) ){ + pe.getTransPoolMgr.putTran(t, pe.getSysTag) + RepLogger.trace(RepLogger.System_Logger,this.getLogMsgPrefix(s"${pe.getSysTag} trans pool recv,txid=${t.id}")) + //广播接收交易事件 + //if (pe.getTransPoolMgr.getTransLength() >= SystemProfile.getMinBlockTransNum) + if (poolIsEmpty)//加入交易之前交易池为空,发送抽签消息 + sendVoteMessage + } } private def publishTrans(t: Transaction) = { @@ -151,7 +120,7 @@ class TransactionPool(moduleName: String) extends ModuleBase(moduleName) { case t: Transaction => //保存交易到本地 sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION) - addTransToCache(t) + addTransToCache(t) //广播交易到其他共识节点 if (ActorUtils.isHelper(sender().path.toString) || ActorUtils.isAPI(sender().path.toString)) { diff --git a/src/main/scala/rep/network/cache/cfrd/TransactionPoolOfCFRD.scala b/src/main/scala/rep/network/cache/cfrd/TransactionPoolOfCFRD.scala new file mode 100644 index 00000000..593e994e --- /dev/null +++ b/src/main/scala/rep/network/cache/cfrd/TransactionPoolOfCFRD.scala @@ -0,0 +1,22 @@ +package rep.network.cache.cfrd + + +import akka.actor.Props +import rep.network.cache.ITransactionPool +import rep.network.module.cfrd.CFRDActorType +import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker + +/** + * Created by jiangbuyun on 2020/03/19. + * CFRD共识的确认块actor + */ + +object TransactionPoolOfCFRD{ + def props(name: String): Props = Props(classOf[TransactionPoolOfCFRD], name) +} + +class TransactionPoolOfCFRD (moduleName: String) extends ITransactionPool(moduleName){ + override protected def sendVoteMessage: Unit = { + pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker + } +} diff --git a/src/main/scala/rep/network/cache/raft/TransactionPoolOfRAFT.scala b/src/main/scala/rep/network/cache/raft/TransactionPoolOfRAFT.scala new file mode 100644 index 00000000..464aac93 --- /dev/null +++ b/src/main/scala/rep/network/cache/raft/TransactionPoolOfRAFT.scala @@ -0,0 +1,22 @@ +package rep.network.cache.raft + +import akka.actor.Props +import rep.network.cache.ITransactionPool +import rep.network.module.cfrd.CFRDActorType +import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker + +/** + * Created by jiangbuyun on 2020/03/19. + * RAFT共识的确认块actor + */ + +object TransactionPoolOfRAFT{ + def props(name: String): Props = Props(classOf[TransactionPoolOfRAFT], name) +} + +class TransactionPoolOfRAFT (moduleName: String) extends ITransactionPool(moduleName){ + override protected def sendVoteMessage: Unit = { + pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker + } +} + diff --git a/src/main/scala/rep/network/confirmblock/IConfirmOfBlock.scala b/src/main/scala/rep/network/confirmblock/IConfirmOfBlock.scala new file mode 100644 index 00000000..12839895 --- /dev/null +++ b/src/main/scala/rep/network/confirmblock/IConfirmOfBlock.scala @@ -0,0 +1,78 @@ +package rep.network.confirmblock + + +import akka.actor.{ActorRef, Props} +import akka.util.Timeout +import rep.log.{RepLogger, RepTimeTracer} +import rep.network.base.ModuleBase +import rep.network.consensus.common.MsgOfConsensus.{ConfirmedBlock} +import rep.network.consensus.util.BlockVerify +import scala.concurrent._ + +/** + * Created by jiangbuyun on 2020/03/19. + * 抽象的确认块actor + */ + +object IConfirmOfBlock{ + def props(name: String): Props = Props(classOf[IConfirmOfBlock], name) +} + +abstract class IConfirmOfBlock(moduleName: String) extends ModuleBase(moduleName) { + import context.dispatcher + import scala.concurrent.duration._ + import rep.protos.peer._ + + implicit val timeout = Timeout(3.seconds) + + protected def asyncVerifyEndorse(e: Signature, byteOfBlock: Array[Byte]): Future[Boolean] = { + val result = Promise[Boolean] + + val tmp = BlockVerify.VerifyOneEndorseOfBlock(e, byteOfBlock, pe.getSysTag) + if (tmp._1) { + result.success(true) + } else { + result.success(false) + } + result.future + } + + protected def asyncVerifyEndorses(block: Block): Boolean = { + val b = block.clearEndorsements.toByteArray + val listOfFuture: Seq[Future[Boolean]] = block.endorsements.map(x => { + asyncVerifyEndorse(x, b) + }) + val futureOfList: Future[List[Boolean]] = Future.sequence(listOfFuture.toList).recover({ + case e: Exception => + null + }) + + val result1 = Await.result(futureOfList, timeout.duration).asInstanceOf[List[Boolean]] + + var result = true + if (result1 == null) { + false + } else { + result1.foreach(f => { + if (!f) { + result = false + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"comfirmOfBlock verify endorse is error, break,block height=${block.height},local height=${pe.getCurrentHeight}")) + } + }) + } + + result + } + + protected def handler(block: Block, actRefOfBlock: ActorRef) + + protected def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef) + + override def receive = { + case ConfirmedBlock(block, actRefOfBlock) => + RepTimeTracer.setStartTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size) + checkedOfConfirmBlock(block, actRefOfBlock) + RepTimeTracer.setEndTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size) + case _ => //ignore + } +} diff --git a/src/main/scala/rep/network/confirmblock/common/ConfirmOfBlock.scala b/src/main/scala/rep/network/confirmblock/common/ConfirmOfBlock.scala new file mode 100644 index 00000000..98f36e8f --- /dev/null +++ b/src/main/scala/rep/network/confirmblock/common/ConfirmOfBlock.scala @@ -0,0 +1,97 @@ +/* + * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BA SIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package rep.network.confirmblock.common + +import akka.actor.{ActorRef, Props} +import akka.util.Timeout +import rep.app.conf.SystemProfile +import rep.log.{RepLogger, RepTimeTracer} +import rep.network.autotransaction.Topic +import rep.network.base.ModuleBase +import rep.network.confirmblock.IConfirmOfBlock +import rep.network.consensus.common.MsgOfConsensus.{BatchStore, BlockRestore, ConfirmedBlock} +import rep.network.consensus.util.BlockVerify +import rep.network.module.ModuleActorType +import rep.network.persistence.IStorager.SourceOfBlock +import rep.network.util.NodeHelp +import rep.utils.GlobalUtils.EventType + + +/** + * Created by jiangbuyun on 2020/03/19. + * 通用的确认块actor + */ + +object ConfirmOfBlock { + def props(name: String): Props = Props(classOf[ConfirmOfBlock], name) +} + +class ConfirmOfBlock(moduleName: String) extends IConfirmOfBlock(moduleName) { + import rep.protos.peer._ + + override def preStart(): Unit = { + RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("ConfirmOfBlock module start")) + SubscribeTopic(mediator, self, selfAddr, Topic.Block, false) + } + + override protected def handler(block: Block, actRefOfBlock: ActorRef) = { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement start,height=${block.height}")) + if (SystemProfile.getIsVerifyOfEndorsement) { + if (asyncVerifyEndorses(block)) { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement end,height=${block.height}")) + //背书人的签名一致 + if (BlockVerify.verifySort(block.endorsements.toArray[Signature]) == 1 || (block.height == 1 && pe.getCurrentBlockHash == "" && block.previousBlockHash.isEmpty())) { + //背书信息排序正确 + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement sort,height=${block.height}")) + pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock)) + pe.getActorRef(ModuleActorType.ActorType.storager) ! BatchStore + sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW) + } else { + ////背书信息排序错误 + } + } else { + //背书验证有错误 + } + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement sort,height=${block.height}")) + pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock)) + pe.getActorRef(ModuleActorType.ActorType.storager) ! BatchStore + sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW) + } + } + + override protected def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef) = { + if (pe.getCurrentBlockHash == "" && block.previousBlockHash.isEmpty()) { + //if (NodeHelp.isSeedNode(pe.getNodeMgr.getStableNodeName4Addr(actRefOfBlock.path.address))) { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}")) + handler(block, actRefOfBlock) + //}else{ + // RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"not confirm genesis block,blocker is not seed node,height=${block.height}")) + //} + } else { + //与上一个块一致 + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}")) + if (NodeHelp.ConsensusConditionChecked(block.endorsements.size, pe.getNodeMgr.getStableNodes.size)) { + //符合大多数人背书要求 + handler(block, actRefOfBlock) + } else { + //错误,没有符合大多人背书要求。 + } + } + } + +} \ No newline at end of file diff --git a/src/main/scala/rep/network/confirmblock/raft/ConfirmBlockOfRAFT.scala b/src/main/scala/rep/network/confirmblock/raft/ConfirmBlockOfRAFT.scala new file mode 100644 index 00000000..f09e3d22 --- /dev/null +++ b/src/main/scala/rep/network/confirmblock/raft/ConfirmBlockOfRAFT.scala @@ -0,0 +1,68 @@ +package rep.network.confirmblock.raft + +import akka.actor.{ActorRef, Props} +import rep.app.conf.SystemProfile +import rep.log.RepLogger +import rep.network.autotransaction.Topic +import rep.network.confirmblock.IConfirmOfBlock +import rep.network.consensus.common.MsgOfConsensus.BlockRestore +import rep.network.module.ModuleActorType +import rep.network.persistence.IStorager.SourceOfBlock +import rep.network.util.NodeHelp +import rep.protos.peer.{Block, Event} +import rep.utils.GlobalUtils.EventType +import rep.network.consensus.common.MsgOfConsensus.BatchStore + +/** + * Created by jiangbuyun on 2020/03/19. + * RAFT共识的确认块actor + */ + +object ConfirmBlockOfRAFT{ + def props(name: String): Props = Props(classOf[ConfirmBlockOfRAFT], name) +} + +class ConfirmBlockOfRAFT(moduleName: String) extends IConfirmOfBlock(moduleName: String) { + override def preStart(): Unit = { + RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("ConfirmBlockOfRAFT module start")) + SubscribeTopic(mediator, self, selfAddr, Topic.Block, false) + } + + override protected def handler(block: Block, actRefOfBlock: ActorRef) = { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement start,height=${block.height}")) + if (SystemProfile.getIsVerifyOfEndorsement) { + if (asyncVerifyEndorses(block)) { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement end,height=${block.height}")) + //背书人的签名一致 + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement sort,height=${block.height}")) + pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock)) + pe.getActorRef(ModuleActorType.ActorType.storager) ! BatchStore + sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW) + } else { + //背书验证有错误 + RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement error,height=${block.height}")) + } + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement sort,height=${block.height}")) + pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock)) + pe.getActorRef(ModuleActorType.ActorType.storager) ! BatchStore + sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW) + } + } + + override protected def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef) = { + if (pe.getCurrentBlockHash == "" && block.previousBlockHash.isEmpty()) { + //if (NodeHelp.isSeedNode(pe.getNodeMgr.getStableNodeName4Addr(actRefOfBlock.path.address))) { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}")) + handler(block, actRefOfBlock) + //}else{ + // RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"not confirm genesis block,blocker is not seed node,height=${block.height}")) + //} + } else { + //与上一个块一致 + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}")) + handler(block, actRefOfBlock) + pe.setConfirmHeight(block.height) + } + } +} diff --git a/src/main/scala/rep/network/consensus/cfrd/MsgOfCFRD.scala b/src/main/scala/rep/network/consensus/cfrd/MsgOfCFRD.scala new file mode 100644 index 00000000..fb47e131 --- /dev/null +++ b/src/main/scala/rep/network/consensus/cfrd/MsgOfCFRD.scala @@ -0,0 +1,56 @@ +package rep.network.consensus.cfrd + +import akka.actor.{ActorRef, Address} +import rep.protos.peer.{Block, BlockchainInfo, Signature} +import rep.utils.GlobalUtils.BlockerInfo + + +/** + * Created by jiangbuyun on 2020/03/17. + * CFRD共识协议的各类消息汇总 + */ +object MsgOfCFRD { + ////////////////////////////////Vote(抽签)消息,开始////////////////////////////// + //通知抽签模块可以抽签的消息 + case object VoteOfBlocker + //通知抽签模块,需要强制抽签 + case object VoteOfForce + ////////////////////////////////Vote(抽签)消息,结束////////////////////////////// + + + ///////////////////////////////Block(出块)消息,开始////////////////////////////// + //抽签成功之后,向预出块的actor发送建立新块的消息,该消息由抽签actor发出 + case object CreateBlock + ///////////////////////////////Block(出块)消息,结束////////////////////////////// + + + //////////////////////////////endorsement(共识)消息,开始///////////////////////// + //背书结果消息 + case object ResultFlagOfEndorse{ + val BlockerSelfError = 1 + val CandidatorError = 2 + val BlockHeightError = 3 + val VerifyError = 4 + val EnodrseNodeIsSynching = 5 + val success = 0 + } + + //背书请求者消息 + case class RequesterOfEndorsement(blc: Block, blocker: String, endorer: Address) + case class ResendEndorseInfo(endorer: Address) + + //给背书人的背书消息 + case class EndorsementInfo(blc: Block, blocker: String) + + //背书收集者消息 + case class CollectEndorsement(blc: Block, blocker: String) + + //背书人返回的背书结果 + case class ResultOfEndorsed(result: Int, endor: Signature, BlockHash: String,endorserOfChainInfo:BlockchainInfo,endorserOfVote:BlockerInfo) + + //背书请求者返回的结果 + case class ResultOfEndorseRequester(result: Boolean, endor: Signature, BlockHash: String, endorser: Address) + //////////////////////////////endorsement(共识)消息,结束///////////////////////// + + +} diff --git a/src/main/scala/rep/network/consensus/cfrd/block/Blocker.scala b/src/main/scala/rep/network/consensus/cfrd/block/Blocker.scala deleted file mode 100644 index 31f040d4..00000000 --- a/src/main/scala/rep/network/consensus/cfrd/block/Blocker.scala +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package rep.network.consensus.cfrd.block - -import akka.util.Timeout - -import scala.concurrent.duration._ -import akka.pattern.ask -import akka.pattern.AskTimeoutException - -import scala.concurrent._ -import akka.actor.{ActorRef, Address, Props} -import akka.cluster.pubsub.DistributedPubSubMediator.Publish -import com.google.protobuf.ByteString -import rep.app.conf.{SystemProfile, TimePolicy} -import rep.crypto.Sha256 -import rep.network.consensus.cfrd.vote.Voter.VoteOfBlocker -import rep.network.base.ModuleBase -import rep.network.consensus.cfrd.block.Blocker.{ConfirmedBlock, PreTransBlock, PreTransBlockResult} -import rep.protos.peer._ -import rep.storage.ImpDataAccess -import rep.utils.GlobalUtils.{BlockEvent, EventType, NodeStatus} - -import scala.collection.mutable -import com.sun.beans.decoder.FalseElementHandler - -import scala.util.control.Breaks -import rep.network.module.ModuleActorType - -import scala.util.control.Breaks._ -import rep.network.consensus.util.{BlockHelp, BlockVerify} -import rep.network.util.NodeHelp -import rep.network.consensus.cfrd.endorse.EndorseMsg -import rep.log.RepLogger -import rep.log.RepTimeTracer -import rep.network.autotransaction.Topic -import rep.network.module.cfrd.CFRDActorType - -object Blocker { - def props(name: String): Props = Props(classOf[Blocker], name) - - case class PreTransBlock(block: Block, prefixOfDbTag: String) - //块预执行结果 - case class PreTransBlockResult(blc: Block, result: Boolean) - - //正式块 - case class ConfirmedBlock(blc: Block, actRef: ActorRef) - - case object CreateBlock - - case object EndorseOfBlockTimeOut - -} - -/** - * 出块模块 - * - * @author shidianyue - * @version 1.0 - * @since 1.0 - * @param moduleName 模块名称 - */ -class Blocker(moduleName: String) extends ModuleBase(moduleName) { - - import context.dispatcher - import scala.concurrent.duration._ - import akka.actor.ActorSelection - import scala.collection.mutable.ArrayBuffer - import rep.protos.peer.{ Transaction } - - val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag) - implicit val timeout = Timeout(TimePolicy.getTimeoutPreload.seconds) - - var preblock: Block = null - - override def preStart(): Unit = { - RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("Block module start")) - super.preStart() - } - - private def CollectedTransOfBlock(start: Int, num: Int, limitsize: Int): ArrayBuffer[Transaction] = { - var result = ArrayBuffer.empty[Transaction] - try { - val tmplist = pe.getTransPoolMgr.getTransListClone(start, num, pe.getSysTag) - if (tmplist.size > 0) { - val currenttime = System.currentTimeMillis() / 1000 - var transsize = 0 - breakable( - tmplist.foreach(f => { - transsize += f.toByteArray.size - if (transsize * 3 > limitsize) { - //区块的长度限制 - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"block too length,txid=${f.id}" + "~" + selfAddr)) - break - } else { - f +=: result - } - })) - if (result.isEmpty && tmplist.size >= SystemProfile.getMinBlockTransNum) { - result = CollectedTransOfBlock(start + num, num, limitsize) - } - } - } finally { - } - result - } - - private def ExecuteTransactionOfBlock(block: Block): Block = { - try { - //val future = pe.getActorRef(ActorType.preloaderoftransaction) ? Blocker.PreTransBlock(block, "preload") - val future = pe.getActorRef(ModuleActorType.ActorType.dispatchofpreload) ? Blocker.PreTransBlock(block, "preload") - val result = Await.result(future, timeout.duration).asInstanceOf[PreTransBlockResult] - if (result.result) { - result.blc - } else { - null - } - } catch { - case e: AskTimeoutException => null - } - } - - private def CreateBlock(start: Int = 0): Block = { - RepTimeTracer.setStartTime(pe.getSysTag, "Block", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) - RepTimeTracer.setStartTime(pe.getSysTag, "createBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) - RepTimeTracer.setStartTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) - val trans = CollectedTransOfBlock(start, SystemProfile.getLimitBlockTransNum, SystemProfile.getBlockLength).reverse - //todo 交易排序 - if (trans.size >= SystemProfile.getMinBlockTransNum) { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,CollectedTransOfBlock success,height=${pe.getBlocker.VoteHeight + 1},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) - RepTimeTracer.setEndTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, trans.size) - //此处建立新块必须采用抽签模块的抽签结果来进行出块,否则出现刚抽完签,马上有新块的存储完成,就会出现错误 - var blc = BlockHelp.WaitingForExecutionOfBlock(pe.getBlocker.voteBlockHash, pe.getBlocker.VoteHeight + 1, trans.toSeq) - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) - RepTimeTracer.setStartTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) - blc = ExecuteTransactionOfBlock(blc) - if (blc != null) { - RepTimeTracer.setEndTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,prelaod success,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) - blc = BlockHelp.AddBlockHash(blc) - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,AddBlockHash success,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) - BlockHelp.AddSignToBlock(blc, pe.getSysTag) - } else { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,preload error" + "~" + selfAddr)) - CreateBlock(start + trans.size) - } - } else { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,trans count error" + "~" + selfAddr)) - null - } - } - - - private def CreateBlock4One(start: Int = 0): Block = { - RepTimeTracer.setStartTime(pe.getSysTag, "Block", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) - RepTimeTracer.setStartTime(pe.getSysTag, "createBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) - RepTimeTracer.setStartTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) - val trans = CollectedTransOfBlock(start, SystemProfile.getLimitBlockTransNum, SystemProfile.getBlockLength).reverse.toSeq - //todo 交易排序 - if (trans.size >= SystemProfile.getMinBlockTransNum) { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,CollectedTransOfBlock success,height=${pe.getBlocker.VoteHeight },local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) - RepTimeTracer.setEndTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, trans.size) - //此处建立新块必须采用抽签模块的抽签结果来进行出块,否则出现刚抽完签,马上有新块的存储完成,就会出现错误 - var blc = BlockHelp.WaitingForExecutionOfBlock(pe.getCurrentBlockHash, pe.getCurrentHeight + 1, trans) - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,height=${blc.height},local height=${pe.getCurrentHeight}" + "~" + selfAddr)) - RepTimeTracer.setStartTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) - blc = ExecuteTransactionOfBlock(blc) - if (blc != null) { - RepTimeTracer.setEndTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,prelaod success,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) - blc = BlockHelp.AddBlockHash(blc) - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,AddBlockHash success,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) - BlockHelp.AddSignToBlock(blc, pe.getSysTag) - } else { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,preload error" + "~" + selfAddr)) - CreateBlock(start + trans.size) - } - } else { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,trans count error" + "~" + selfAddr)) - null - } - } - - private def CreateBlockHandler = { - //if (preblock == null) { - var blc : Block = null - if(SystemProfile.getNumberOfEndorsement == 1){ - blc = CreateBlock4One(0) - }else{ - blc = CreateBlock(0) - } - - if (blc != null) { - RepTimeTracer.setEndTime(pe.getSysTag, "createBlock", System.currentTimeMillis(), blc.height, blc.transactions.size) - this.preblock = blc - schedulerLink = clearSched() - - if (SystemProfile.getNumberOfEndorsement == 1) { - pe.setCreateHeight(preblock.height) - mediator ! Publish(Topic.Block, ConfirmedBlock(preblock, self)) - }else{ - //在发出背书时,告诉对方我是当前出块人,取出系统的名称 - RepTimeTracer.setStartTime(pe.getSysTag, "Endorsement", System.currentTimeMillis(), blc.height, blc.transactions.size) - pe.getActorRef(CFRDActorType.ActorType.endorsementcollectioner) ! EndorseMsg.CollectEndorsement(this.preblock, pe.getSysTag) - } - } else { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,CreateBlock is null" + "~" + selfAddr)) - pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker - } - //} - } - - override def receive = { - //创建块请求(给出块人) - case Blocker.CreateBlock => - /*if(pe.getSysTag == "121000005l35120456.node1" && pe.count <= 10){ - pe.count = pe.count + 1 - throw new Exception("^^^^^^^^^^^^^^^^exception^^^^^^^^^^") - }*/ - if (!pe.isSynching) { - if(SystemProfile.getNumberOfEndorsement == 1){ - if (NodeHelp.isBlocker(pe.getBlocker.blocker, pe.getSysTag)){ - sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.CANDIDATOR) - if (preblock == null || (preblock.previousBlockHash.toStringUtf8() != pe.getCurrentBlockHash)) { - //是出块节点 - CreateBlockHandler - } - } - - }else{ - if (NodeHelp.isBlocker(pe.getBlocker.blocker, pe.getSysTag) && pe.getBlocker.voteBlockHash == pe.getCurrentBlockHash) { - sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.CANDIDATOR) - - //是出块节点 - if (preblock == null || (preblock.previousBlockHash.toStringUtf8() != pe.getBlocker.voteBlockHash)) { - CreateBlockHandler - } - } else { - //出块标识错误,暂时不用做任何处理 - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,do not blocker or blocker hash not equal current hash,height=${pe.getCurrentHeight}" + "~" + selfAddr)) - } - } - } else { - //节点状态不对 - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,node status error,status is synching,height=${pe.getCurrentHeight}" + "~" + selfAddr)) - } - - case _ => //ignore - } - -} \ No newline at end of file diff --git a/src/main/scala/rep/network/consensus/cfrd/block/BlockerOfCFRD.scala b/src/main/scala/rep/network/consensus/cfrd/block/BlockerOfCFRD.scala new file mode 100644 index 00000000..5da8ffad --- /dev/null +++ b/src/main/scala/rep/network/consensus/cfrd/block/BlockerOfCFRD.scala @@ -0,0 +1,71 @@ +package rep.network.consensus.cfrd.block + +import akka.actor.Props +import rep.log.{RepLogger, RepTimeTracer} +import rep.network.autotransaction.Topic +import rep.network.consensus.cfrd.MsgOfCFRD.CreateBlock +import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker +import rep.network.consensus.common.block.IBlocker +import rep.network.module.cfrd.CFRDActorType +import rep.network.util.NodeHelp +import rep.protos.peer.{Block, Event} +import rep.utils.GlobalUtils.EventType +import rep.network.consensus.cfrd.MsgOfCFRD.CollectEndorsement + +/** + * Created by jiangbuyun on 2020/03/17. + * CFRD共识协议的出块人actor + */ + +object BlockerOfCFRD { + def props(name: String): Props = Props(classOf[BlockerOfCFRD], name) +} + +class BlockerOfCFRD(moduleName: String) extends IBlocker(moduleName){ + var preblock: Block = null + + override def preStart(): Unit = { + RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("CFRDBlocker module start")) + super.preStart() + } + + private def CreateBlockHandler = { + var blc : Block = null + + //blc = PackedBlock(0,pe.getBlocker.VoteHeight + 1) + blc = PackedBlock(0) + if (blc != null) { + RepTimeTracer.setEndTime(pe.getSysTag, "createBlock", System.currentTimeMillis(), blc.height, blc.transactions.size) + this.preblock = blc + schedulerLink = clearSched() + //在发出背书时,告诉对方我是当前出块人,取出系统的名称 + RepTimeTracer.setStartTime(pe.getSysTag, "Endorsement", System.currentTimeMillis(), blc.height, blc.transactions.size) + pe.getActorRef(CFRDActorType.ActorType.endorsementcollectioner) ! CollectEndorsement(this.preblock, pe.getSysTag) + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,CreateBlock is null" + "~" + selfAddr)) + pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker + } + } + + override def receive = { + //创建块请求(给出块人) + case CreateBlock => + if (!pe.isSynching) { + if (NodeHelp.isBlocker(pe.getBlocker.blocker, pe.getSysTag) && pe.getBlocker.voteBlockHash == pe.getCurrentBlockHash) { + sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.CANDIDATOR) + //是出块节点 + if (preblock == null || (preblock.previousBlockHash.toStringUtf8() != pe.getBlocker.voteBlockHash)) { + CreateBlockHandler + } + } else { + //出块标识错误,暂时不用做任何处理 + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,do not blocker or blocker hash not equal current hash,height=${pe.getCurrentHeight}" + "~" + selfAddr)) + } + } else { + //节点状态不对 + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,node status error,status is synching,height=${pe.getCurrentHeight}" + "~" + selfAddr)) + } + + case _ => //ignore + } +} diff --git a/src/main/scala/rep/network/consensus/cfrd/block/ConfirmOfBlock.scala b/src/main/scala/rep/network/consensus/cfrd/block/ConfirmOfBlock.scala deleted file mode 100644 index 76412988..00000000 --- a/src/main/scala/rep/network/consensus/cfrd/block/ConfirmOfBlock.scala +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package rep.network.consensus.cfrd.block - -import akka.util.Timeout - -import scala.concurrent.duration._ -import akka.pattern.ask -import akka.pattern.AskTimeoutException - -import scala.concurrent._ -import rep.app.conf.SystemProfile -import akka.actor.{ActorRef, Address, Props} -import rep.crypto.Sha256 -import rep.network.base.ModuleBase -import rep.network.util.NodeHelp -import rep.protos.peer.{Event, Transaction} -import rep.utils.GlobalUtils.{ BlockEvent, EventType, NodeStatus} -import com.sun.beans.decoder.FalseElementHandler - -import scala.util.control.Breaks._ -import scala.util.control.Exception.Finally -import java.util.concurrent.ConcurrentHashMap - -import rep.network.consensus.cfrd.block.Blocker.ConfirmedBlock -import rep.network.persistence.Storager.{BatchStore, BlockRestore, SourceOfBlock} -import rep.network.consensus.util.{BlockHelp, BlockVerify} -import rep.log.RepLogger -import rep.log.RepTimeTracer -import rep.network.autotransaction.Topic -import rep.network.module.ModuleActorType -import rep.network.sync.SyncMsg.SyncRequestOfStorager -import rep.network.consensus.cfrd.vote.Voter.VoteOfBlocker - -object ConfirmOfBlock { - def props(name: String): Props = Props(classOf[ConfirmOfBlock], name) -} - -class ConfirmOfBlock(moduleName: String) extends ModuleBase(moduleName) { - import context.dispatcher - - override def preStart(): Unit = { - RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("confirm Block module start")) - SubscribeTopic(mediator, self, selfAddr, Topic.Block, false) - } - import scala.concurrent.duration._ - import rep.protos.peer._ - - implicit val timeout = Timeout(3.seconds) - - private def asyncVerifyEndorse(e: Signature, byteOfBlock: Array[Byte]): Future[Boolean] = { - val result = Promise[Boolean] - - val tmp = BlockVerify.VerifyOneEndorseOfBlock(e, byteOfBlock, pe.getSysTag) - if (tmp._1) { - result.success(true) - } else { - result.success(false) - } - result.future - } - - private def asyncVerifyEndorses(block: Block): Boolean = { - val b = block.clearEndorsements.toByteArray - val listOfFuture: Seq[Future[Boolean]] = block.endorsements.map(x => { - asyncVerifyEndorse(x, b) - }) - val futureOfList: Future[List[Boolean]] = Future.sequence(listOfFuture.toList).recover({ - case e: Exception => - null - }) - - val result1 = Await.result(futureOfList, timeout.duration).asInstanceOf[List[Boolean]] - - var result = true - if (result1 == null) { - false - } else { - result1.foreach(f => { - if (!f) { - result = false - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"comfirmOfBlock verify endorse is error, break,block height=${block.height},local height=${pe.getCurrentHeight}")) - } - }) - } - - result - } - - private def handler(block: Block, actRefOfBlock: ActorRef) = { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement start,height=${block.height}")) - if (SystemProfile.getIsVerifyOfEndorsement) { - if (asyncVerifyEndorses(block)) { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement end,height=${block.height}")) - //背书人的签名一致 - if (BlockVerify.verifySort(block.endorsements.toArray[Signature]) == 1 || (block.height == 1 && pe.getCurrentBlockHash == "" && block.previousBlockHash.isEmpty())) { - //背书信息排序正确 - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement sort,height=${block.height}")) - pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock)) - pe.getActorRef(ModuleActorType.ActorType.storager) ! BatchStore - sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW) - } else { - ////背书信息排序错误 - } - } else { - //背书验证有错误 - } - } else { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement sort,height=${block.height}")) - pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock)) - pe.getActorRef(ModuleActorType.ActorType.storager) ! BatchStore - sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW) - } - } - - private def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef) = { - if (pe.getCurrentBlockHash == "" && block.previousBlockHash.isEmpty()) { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}")) - handler(block, actRefOfBlock) - } else { - //与上一个块一致 - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}")) - if (SystemProfile.getNumberOfEndorsement == 1) { - /*if (block.height > pe.getCurrentHeight + 1) { - RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify height,height=${block.height},localheight=${pe.getCurrentHeight }")) - //pe.getActorRef(ActorType.synchrequester) ! StartSync(false) - pe.getActorRef(ActorType.synchrequester) ! SyncRequestOfStorager(sender,block.height) - } else {*/ - handler(block, actRefOfBlock) - pe.setConfirmHeight(block.height) - //} - //pe.getActorRef(ActorType.voter) ! VoteOfBlocker - } else { - if (NodeHelp.ConsensusConditionChecked(block.endorsements.size, pe.getNodeMgr.getStableNodes.size)) { - //符合大多数人背书要求 - handler(block, actRefOfBlock) - } else { - //错误,没有符合大多人背书要求。 - } - } - } - } - - override def receive = { - //Endorsement block - case ConfirmedBlock(block, actRefOfBlock) => - RepTimeTracer.setStartTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size) - checkedOfConfirmBlock(block, actRefOfBlock) - RepTimeTracer.setEndTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size) - case _ => //ignore - } - -} \ No newline at end of file diff --git a/src/main/scala/rep/network/consensus/cfrd/block/EndorseCollector.scala b/src/main/scala/rep/network/consensus/cfrd/block/EndorseCollector.scala index 093bae14..c09fa75a 100644 --- a/src/main/scala/rep/network/consensus/cfrd/block/EndorseCollector.scala +++ b/src/main/scala/rep/network/consensus/cfrd/block/EndorseCollector.scala @@ -16,22 +16,15 @@ package rep.network.consensus.cfrd.block -import akka.actor.{Actor, ActorRef, ActorSelection, Address, Props} +import akka.actor.{Props} import akka.cluster.pubsub.DistributedPubSubMediator.Publish import akka.routing._ -import rep.app.conf.{SystemProfile, TimePolicy} +import rep.app.conf.{SystemProfile} import rep.network.base.ModuleBase -import rep.network.consensus.cfrd.endorse.EndorseMsg.{CollectEndorsement, RequesterOfEndorsement, ResendEndorseInfo, ResultOfEndorseRequester} -import rep.network.consensus.cfrd.block.Blocker.ConfirmedBlock -import rep.network.tools.PeerExtension +import rep.network.consensus.common.MsgOfConsensus.ConfirmedBlock +import rep.network.consensus.cfrd.MsgOfCFRD.{CollectEndorsement,ResultOfEndorseRequester,ResendEndorseInfo,RequesterOfEndorsement} import rep.protos.peer._ import rep.utils.GlobalUtils.EventType -import rep.utils._ - -import scala.collection.mutable._ -import rep.network.consensus.util.BlockVerify - -import scala.util.control.Breaks import rep.network.util.NodeHelp import rep.network.consensus.util.BlockHelp import rep.network.consensus.util.BlockVerify @@ -39,6 +32,11 @@ import rep.log.RepLogger import rep.log.RepTimeTracer import rep.network.autotransaction.Topic +/** + * Created by jiangbuyun on 2020/03/19. + * 背书的收集的actor + */ + object EndorseCollector { def props(name: String): Props = Props(classOf[EndorseCollector], name) } diff --git a/src/main/scala/rep/network/consensus/cfrd/block/EndorsementRequest4Future.scala b/src/main/scala/rep/network/consensus/cfrd/block/EndorsementRequest4Future.scala index 39072021..53c9fc09 100644 --- a/src/main/scala/rep/network/consensus/cfrd/block/EndorsementRequest4Future.scala +++ b/src/main/scala/rep/network/consensus/cfrd/block/EndorsementRequest4Future.scala @@ -17,32 +17,25 @@ package rep.network.consensus.cfrd.block import akka.util.Timeout - -import scala.concurrent.duration._ import akka.pattern.ask -import akka.pattern.AskTimeoutException - import scala.concurrent._ -import akka.actor.{Actor, ActorRef, ActorSelection, Address, Props} -import com.google.protobuf.ByteString -import com.google.protobuf.timestamp.Timestamp -import rep.app.conf.{SystemProfile, TimePolicy} +import akka.actor.{ ActorSelection, Address, Props} +import rep.app.conf.{TimePolicy} import rep.network.base.ModuleBase -import rep.network.consensus.cfrd.endorse.EndorseMsg.{EndorsementInfo, RequesterOfEndorsement, ResendEndorseInfo, ResultFlagOfEndorse, ResultOfEndorseRequester, ResultOfEndorsed} -import rep.network.tools.PeerExtension import rep.protos.peer._ -import rep.utils._ import akka.pattern.AskTimeoutException import rep.network.consensus.util.BlockVerify - -import scala.util.control.Breaks -import rep.utils.GlobalUtils.{ EventType} +import rep.network.consensus.cfrd.MsgOfCFRD.{ResultOfEndorsed,ResultOfEndorseRequester,ResendEndorseInfo,RequesterOfEndorsement,EndorsementInfo,ResultFlagOfEndorse} import rep.network.sync.SyncMsg.StartSync import rep.log.RepLogger import rep.log.RepTimeTracer -import rep.network.autotransaction.Topic import rep.network.module.cfrd.CFRDActorType +/** + * Created by jiangbuyun on 2020/03/19. + * 背书请求的actor + */ + object EndorsementRequest4Future { def props(name: String): Props = Props(classOf[EndorsementRequest4Future], name) } diff --git a/src/main/scala/rep/network/consensus/cfrd/endorse/DispatchOfRecvEndorsement.scala b/src/main/scala/rep/network/consensus/cfrd/endorse/DispatchOfRecvEndorsement.scala index afac3001..b7e09fa7 100644 --- a/src/main/scala/rep/network/consensus/cfrd/endorse/DispatchOfRecvEndorsement.scala +++ b/src/main/scala/rep/network/consensus/cfrd/endorse/DispatchOfRecvEndorsement.scala @@ -36,7 +36,12 @@ import rep.network.consensus.util.BlockVerify import rep.log.RepLogger import rep.log.RepTimeTracer import rep.network.autotransaction.Topic -import rep.network.consensus.cfrd.endorse.EndorseMsg.EndorsementInfo +import rep.network.consensus.cfrd.MsgOfCFRD.EndorsementInfo + +/** + * Created by jiangbuyun on 2020/03/19. + * 接收并分派背书请求actor + */ object DispatchOfRecvEndorsement { def props(name: String): Props = Props(classOf[DispatchOfRecvEndorsement], name) diff --git a/src/main/scala/rep/network/consensus/cfrd/endorse/EndorseMsg.scala b/src/main/scala/rep/network/consensus/cfrd/endorse/EndorseMsg.scala deleted file mode 100644 index 43b8197b..00000000 --- a/src/main/scala/rep/network/consensus/cfrd/endorse/EndorseMsg.scala +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package rep.network.consensus.cfrd.endorse - -import akka.actor.{ Address} -import rep.protos.peer.{Signature,Block,BlockchainInfo} -import rep.utils.GlobalUtils.{BlockerInfo} - -object EndorseMsg { - - case object ResultFlagOfEndorse{ - val BlockerSelfError = 1 - val CandidatorError = 2 - val BlockHeightError = 3 - val VerifyError = 4 - val EnodrseNodeIsSynching = 5 - val success = 0 - } - - //背书请求者消息 - case class RequesterOfEndorsement(blc: Block, blocker: String, endorer: Address) - - case class ResendEndorseInfo(endorer: Address) - - //给背书人的背书消息 - case class EndorsementInfo(blc: Block, blocker: String) - - //背书收集者消息 - case class CollectEndorsement(blc: Block, blocker: String) - - //背书人返回的背书结果 - case class ResultOfEndorsed(result: Int, endor: Signature, BlockHash: String,endorserOfChainInfo:BlockchainInfo,endorserOfVote:BlockerInfo) - - //背书请求者返回的结果 - case class ResultOfEndorseRequester(result: Boolean, endor: Signature, BlockHash: String, endorser: Address) - - - -} \ No newline at end of file diff --git a/src/main/scala/rep/network/consensus/cfrd/endorse/Endorser4Future.scala b/src/main/scala/rep/network/consensus/cfrd/endorse/Endorser4Future.scala index 4f42989e..fe0baeb9 100644 --- a/src/main/scala/rep/network/consensus/cfrd/endorse/Endorser4Future.scala +++ b/src/main/scala/rep/network/consensus/cfrd/endorse/Endorser4Future.scala @@ -17,37 +17,27 @@ package rep.network.consensus.cfrd.endorse import akka.util.Timeout - -import scala.concurrent.duration._ import akka.pattern.ask -import akka.pattern.AskTimeoutException - -import scala.concurrent._ -import akka.actor.{ActorRef, ActorSystemImpl, Address, Props} -import rep.crypto.Sha256 +import akka.actor.{ Props} import rep.network.base.ModuleBase import rep.network.util.NodeHelp -import rep.protos.peer.{Event, Transaction} import rep.app.conf.{SystemCertList, SystemProfile, TimePolicy} -import rep.storage.{ImpDataPreload, ImpDataPreloadMgr} -import rep.utils.GlobalUtils.{ BlockEvent, EventType, NodeStatus} -import com.sun.beans.decoder.FalseElementHandler +import rep.utils.GlobalUtils.{EventType} import rep.network.autotransaction.Topic -//import rep.network.consensus.cfrd.vote.Voter.VoteOfBlocker -import sun.font.TrueTypeFont import scala.util.control.Breaks._ import rep.network.module.ModuleActorType import rep.network.module.cfrd.CFRDActorType -import scala.util.control.Exception.Finally -import java.util.concurrent.ConcurrentHashMap -import rep.network.consensus.cfrd.endorse.EndorseMsg.{ EndorsementInfo, ResultOfEndorsed, ResultFlagOfEndorse } -import rep.network.consensus.cfrd.block.Blocker.{ PreTransBlock, PreTransBlockResult } +import rep.network.consensus.common.MsgOfConsensus.{ PreTransBlock, PreTransBlockResult } +import rep.network.consensus.cfrd.MsgOfCFRD.{EndorsementInfo,ResultOfEndorsed,ResultFlagOfEndorse,VoteOfForce} import rep.network.consensus.util.{ BlockVerify, BlockHelp } import rep.network.sync.SyncMsg.StartSync import rep.log.RepLogger import rep.log.RepTimeTracer -import rep.network.consensus.cfrd.vote.Voter +/** + * Created by jiangbuyun on 2020/03/19. + * 背书actor + */ object Endorser4Future { def props(name: String): Props = Props(classOf[Endorser4Future], name) @@ -59,7 +49,6 @@ class Endorser4Future(moduleName: String) extends ModuleBase(moduleName) { import rep.protos.peer._ import rep.storage.ImpDataAccess import scala.concurrent._ - //import java.util.concurrent.Executors implicit val timeout = Timeout(TimePolicy.getTimeoutPreload.seconds) @@ -180,7 +169,7 @@ class Endorser4Future(moduleName: String) extends ModuleBase(moduleName) { if(info.blc.height > pe.getCurrentHeight+1){ pe.getActorRef(CFRDActorType.ActorType.synchrequester) ! StartSync(false) }else if(info.blc.height > pe.getCurrentHeight+1){ - pe.getActorRef(CFRDActorType.ActorType.voter) ! Voter.VoteOfForce + pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfForce } //当前块hash和抽签的出块人都不一致,暂时不能够进行背书,可以进行缓存 RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( s"block hash is not equal or blocker is not equal,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}")) diff --git a/src/main/scala/rep/network/consensus/cfrd/vote/Voter.scala b/src/main/scala/rep/network/consensus/cfrd/vote/Voter.scala deleted file mode 100644 index bc0aa80a..00000000 --- a/src/main/scala/rep/network/consensus/cfrd/vote/Voter.scala +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package rep.network.consensus.cfrd.vote - -import akka.actor.{ Actor, Address, Props } -import rep.app.conf.{ SystemProfile, TimePolicy, SystemCertList } -import rep.crypto.Sha256 -import rep.network.base.ModuleBase -import rep.protos.peer.BlockchainInfo -import rep.storage.ImpDataAccess -import rep.utils.GlobalUtils.{ BlockEvent, BlockerInfo, NodeStatus } -import com.sun.beans.decoder.FalseElementHandler -import rep.network.util.NodeHelp -import rep.network.consensus.cfrd.block.Blocker.{ CreateBlock } -import rep.network.sync.SyncMsg.StartSync -import rep.network.consensus.cfrd.block.GenesisBlocker.GenesisBlock -import rep.log.RepLogger -import rep.network.module.cfrd.CFRDActorType - -object Voter { - - def props(name: String): Props = Props(classOf[Voter], name) - - case object VoteOfBlocker - case object VoteOfForce - -} - -class Voter(moduleName: String) extends ModuleBase(moduleName) with CRFDVoter { - - import context.dispatcher - import scala.concurrent.duration._ - - override def preStart(): Unit = { - RepLogger.info(RepLogger.Vote_Logger, this.getLogMsgPrefix("Vote module start")) - } - - val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag) - - //private var BlockHashOfVote: String = null - private var candidator: Array[String] = Array.empty[String] - private var Blocker: BlockerInfo = BlockerInfo("", -1, 0l, "", -1) - private var voteCount = 0 - private var HeightOfBlocked : String = "" - - def checkTranNum: Boolean = { - pe.getTransPoolMgr.getTransLength() >= SystemProfile.getMinBlockTransNum - } - - private def cleanVoteInfo = { - this.voteCount = 0 - //this.BlockHashOfVote = null - candidator = Array.empty[String] - this.Blocker = BlockerInfo("", -1, 0l, "", -1) - pe.resetBlocker(this.Blocker) - } - - private def getSystemBlockHash: String = { - if (pe.getCurrentBlockHash == "") { - pe.resetSystemCurrentChainStatus(dataaccess.getBlockChainInfo()) - } - pe.getCurrentBlockHash - } - - private def resetCandidator(currentblockhash: String) = { - //this.BlockHashOfVote = pe.getCurrentBlockHash - candidator = candidators(pe.getSysTag, currentblockhash, SystemCertList.getSystemCertList, Sha256.hash(currentblockhash)) - //pe.getNodeMgr.resetCandidator(candidatorCur) - } - - private def resetBlocker(idx: Int, currentblockhash: String, currentheight: Long) = { - if(SystemProfile.getNumberOfEndorsement == 1){ - pe.setConfirmHeight(0) - pe.setCreateHeight(0) - } - - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},votelist=${candidator.toArray[String].mkString("|")},idx=${idx}")) - this.Blocker = BlockerInfo(blocker(candidator.toArray[String], idx), idx, System.currentTimeMillis(), currentblockhash, currentheight) - pe.resetBlocker(this.Blocker) - NoticeBlockerMsg - } - - private def NoticeBlockerMsg = { - if (this.Blocker.blocker.equals(pe.getSysTag)) { - //发送建立新块的消息 - pe.getActorRef(CFRDActorType.ActorType.blocker) ! CreateBlock - } - } - - private def DelayVote = { - this.voteCount += 1 - var time = this.voteCount * TimePolicy.getVoteRetryDelay - schedulerLink = clearSched() - schedulerLink = scheduler.scheduleOnce(TimePolicy.getVoteRetryDelay.millis, self, Voter.VoteOfBlocker) - } - - private def vote4One = { - - if(this.Blocker.blocker == ""){ - val maxinfo = pe.getStartVoteInfo - var currentblockhash:String = "" - var currentheight : Long = 0 - if(maxinfo.height > 0){ - currentblockhash = maxinfo.hash - currentheight = maxinfo.height - }else{ - currentblockhash = pe.getCurrentBlockHash - currentheight = pe.getCurrentHeight - } - if(currentheight > 0){ - this.cleanVoteInfo - this.resetCandidator(currentblockhash) - this.resetBlocker(0, currentblockhash, currentheight) - } - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},first voter,currentHeight=${currentheight},currentHash=${currentblockhash}" + "~" + selfAddr)) - }else if((this.Blocker.VoteHeight +SystemProfile.getBlockNumberOfRaft) <= pe.getMaxHeight4SimpleRaft){ - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},second voter,currentHeight=${pe.getMaxHeight4SimpleRaft}" + "~" + selfAddr)) - val block = dataaccess.getBlock4ObjectByHeight(this.Blocker.VoteHeight +SystemProfile.getBlockNumberOfRaft) - if(block != null){ - val currentblockhash = block.hashOfBlock.toStringUtf8() - val currentheight = block.height - this.cleanVoteInfo - this.resetCandidator(currentblockhash) - this.resetBlocker(0, currentblockhash, currentheight) - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},read block voter,currentHeight=${this.Blocker.VoteHeight +SystemProfile.getBlockNumberOfRaft},currentHash=${currentblockhash}" + "~" + selfAddr)) - }else{ - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},second voter in synch,currentHeight=${this.Blocker.VoteHeight +SystemProfile.getBlockNumberOfRaft}" + "~" + selfAddr)) - pe.getActorRef(CFRDActorType.ActorType.synchrequester) ! StartSync(false) - } - }else{ - NoticeBlockerMsg - } - } - - private def vote(isForce:Boolean) = { - if (checkTranNum || isForce) { - val currentblockhash = pe.getCurrentBlockHash - val currentheight = pe.getCurrentHeight - if (this.Blocker.voteBlockHash == "") { - this.cleanVoteInfo - this.resetCandidator(currentblockhash) - this.resetBlocker(0, currentblockhash, currentheight) - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},first voter,blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr)) - } else { - if (!this.Blocker.voteBlockHash.equals(currentblockhash)) { - //抽签的基础块已经变化,需要重续选择候选人 - this.cleanVoteInfo - this.resetCandidator(currentblockhash) - this.resetBlocker(0, currentblockhash, currentheight) - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},hash change,reset voter,height=${currentheight},hash=${currentblockhash},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr)) - } else { - if (this.Blocker.blocker == "") { - this.cleanVoteInfo - this.resetCandidator(currentblockhash) - this.resetBlocker(0, currentblockhash, currentheight) - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},blocker=null,reset voter,height=${currentheight},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr)) - } else { - if ((System.currentTimeMillis() - this.Blocker.voteTime) / 1000 > TimePolicy.getTimeOutBlock) { - //说明出块超时 - this.voteCount = 0 - this.resetBlocker(this.Blocker.VoteIndex + 1, currentblockhash, currentheight) - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},block timeout,reset voter,height=${currentheight},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr)) - } else { - NoticeBlockerMsg - } - } - } - } - } else { - RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},transaction is not enough,waiting transaction,height=${pe.getCurrentHeight}" + "~" + selfAddr)) - } - } - - private def voteMsgHandler(isForce:Boolean) = { - if (pe.getNodeMgr.getStableNodes.size >= SystemProfile.getVoteNoteMin) { - //只有共识节点符合要求之后开始工作 - if (getSystemBlockHash == "") { - //系统属于初始化状态 - if (NodeHelp.isSeedNode(pe.getSysTag)) { - // 建立创世块消息 - pe.getActorRef(CFRDActorType.ActorType.gensisblock) ! GenesisBlock - } else { - // 发出同步消息 - //pe.setSystemStatus(NodeStatus.Synching) - //pe.getActorRef(ActorType.synchrequester) ! StartSync - } - } else { - if (!pe.isSynching) { - if(SystemProfile.getNumberOfEndorsement == 1){ - vote4One - }else{ - vote(isForce) - } - } - } - } - DelayVote - } - - override def receive = { - case Voter.VoteOfBlocker => - if (NodeHelp.isCandidateNow(pe.getSysTag, SystemCertList.getSystemCertList)) { - voteMsgHandler(false) - } - case Voter.VoteOfForce=> - voteMsgHandler(true) - - } -} \ No newline at end of file diff --git a/src/main/scala/rep/network/consensus/cfrd/vote/VoterBase.scala b/src/main/scala/rep/network/consensus/cfrd/vote/VoterBase.scala deleted file mode 100644 index cf1bf147..00000000 --- a/src/main/scala/rep/network/consensus/cfrd/vote/VoterBase.scala +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package rep.network.consensus.cfrd.vote - - - - -/** - * 特质:全局节点控制 - * Created by shidianyue on 2017/5/15. - * @update 2018-05 jiangbuyun - */ -trait VoterBase { - - - - - /** - * 获取出块人(竞争胜出者) - * @param nodes - * @tparam T - * @return - */ - //def blocker[T](nodes:Set[T], position:Int):Option[T] - def blocker(nodes:Array[String], position:Int):String - - /** - * 获取候选人节点 - * @param nodes - * @tparam T - * @param seed 随机种子(这里写的不太好,应该改一下) - * @return - */ - //def candidators[T](nodes:Set[T], seed:Array[Byte]):Set[T] - def candidators(Systemname:String,hash:String,nodes:Set[String], seed:Array[Byte]):Array[String] -} diff --git a/src/main/scala/rep/network/consensus/cfrd/vote/VoterOfCFRD.scala b/src/main/scala/rep/network/consensus/cfrd/vote/VoterOfCFRD.scala new file mode 100644 index 00000000..df902d8c --- /dev/null +++ b/src/main/scala/rep/network/consensus/cfrd/vote/VoterOfCFRD.scala @@ -0,0 +1,92 @@ +package rep.network.consensus.cfrd.vote + +import akka.actor.Props +import rep.app.conf.{SystemCertList, TimePolicy} +import rep.log.RepLogger +import rep.network.consensus.common.vote.IVoter +import rep.network.module.cfrd.CFRDActorType +import rep.network.consensus.cfrd.MsgOfCFRD.{CreateBlock, VoteOfBlocker,VoteOfForce} +import rep.network.util.NodeHelp +import rep.network.consensus.common.algorithm.IRandomAlgorithmOfVote + +/** + * Created by jiangbuyun on 2020/03/17. + * 实现CFRD抽签actor + */ + +object VoterOfCFRD{ + def props(name: String): Props = Props(classOf[VoterOfCFRD],name) +} + +class VoterOfCFRD(moduleName: String) extends IVoter(moduleName: String) { + import scala.concurrent.duration._ + import context.dispatcher + + this.algorithmInVoted = new IRandomAlgorithmOfVote + + override def preStart(): Unit = { + RepLogger.info(RepLogger.Vote_Logger, this.getLogMsgPrefix("VoterOfCFRD module start")) + } + + override protected def NoticeBlockerMsg: Unit = { + if (this.Blocker.blocker.equals(pe.getSysTag)) { + //发送建立新块的消息 + pe.getActorRef(CFRDActorType.ActorType.blocker) ! CreateBlock + } + } + + override protected def DelayVote: Unit = { + this.voteCount += 1 + var time = this.voteCount * TimePolicy.getVoteRetryDelay + schedulerLink = clearSched() + schedulerLink = scheduler.scheduleOnce(TimePolicy.getVoteRetryDelay.millis, self, VoteOfBlocker) + } + + override protected def vote(isForce: Boolean): Unit = { + if (checkTranNum || isForce) { + val currentblockhash = pe.getCurrentBlockHash + val currentheight = pe.getCurrentHeight + if (this.Blocker.voteBlockHash == "") { + this.cleanVoteInfo + this.resetCandidator(currentblockhash) + this.resetBlocker(0, currentblockhash, currentheight) + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},first voter,blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr)) + } else { + if (!this.Blocker.voteBlockHash.equals(currentblockhash)) { + //抽签的基础块已经变化,需要重续选择候选人 + this.cleanVoteInfo + this.resetCandidator(currentblockhash) + this.resetBlocker(0, currentblockhash, currentheight) + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},hash change,reset voter,height=${currentheight},hash=${currentblockhash},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr)) + } else { + if (this.Blocker.blocker == "") { + this.cleanVoteInfo + this.resetCandidator(currentblockhash) + this.resetBlocker(0, currentblockhash, currentheight) + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},blocker=null,reset voter,height=${currentheight},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr)) + } else { + if ((System.currentTimeMillis() - this.Blocker.voteTime) / 1000 > TimePolicy.getTimeOutBlock) { + //说明出块超时 + this.voteCount = 0 + this.resetBlocker(this.Blocker.VoteIndex + 1, currentblockhash, currentheight) + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},block timeout,reset voter,height=${currentheight},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr)) + } else { + NoticeBlockerMsg + } + } + } + } + } else { + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},transaction is not enough,waiting transaction,height=${pe.getCurrentHeight}" + "~" + selfAddr)) + } + } + + override def receive: Receive = { + case VoteOfBlocker => + if (NodeHelp.isCandidateNow(pe.getSysTag, SystemCertList.getSystemCertList)) { + voteMsgHandler(false) + } + case VoteOfForce=> + voteMsgHandler(true) + } +} diff --git a/src/main/scala/rep/network/consensus/common/MsgOfConsensus.scala b/src/main/scala/rep/network/consensus/common/MsgOfConsensus.scala new file mode 100644 index 00000000..176148d6 --- /dev/null +++ b/src/main/scala/rep/network/consensus/common/MsgOfConsensus.scala @@ -0,0 +1,34 @@ +package rep.network.consensus.common + +import akka.actor.ActorRef +import rep.protos.peer.Block + + +/** + * Created by jiangbuyun on 2020/03/17. + * 汇总共识层中所有公共的消息,目前公共的消息由预出块的交易预执行消息以及持久化的存储区块的消息。 + */ +object MsgOfConsensus { + ///////////////////////////////预出块时,预执行交易的相关消息,开始////////////////////////////// + //发送预出块给交易预执行分配器,预执行预出块里面的所有交易。 + case class PreTransBlock(block: Block, prefixOfDbTag: String) + //预出块的预执行的结果消息 + case class PreTransBlockResult(blc: Block, result: Boolean) + ///////////////////////////////预出块时,预执行交易的相关消息,结束////////////////////////////// + + ///////////////////////////////存储时,发送给持久化actor的相关消息,开始////////////////////////////// + //对于单个区块需要存储时,发送下面的消息给持久化actor。 + final case class BlockRestore(blk: Block, SourceOfBlock: Int, blker: ActorRef) + //这个消息用于出块时,提高存储效率,发送批处理消息。处理机制是,先把确认块存放到缓存,发送消息给持久化,之后持久化actor开始存储。 + final case object BatchStore + ///////////////////////////////存储时,发送给持久化actor的相关消息,结束////////////////////////////// + + ///////////////////////////////创世块actor的相关消息,开始////////////////////////////// + case object GenesisBlock + ///////////////////////////////创世块actor的相关消息,结束////////////////////////////// + + ///////////////////////////////块确认actor的相关消息,开始////////////////////////////// + //共识完成之后,广播正式出块的消息 + case class ConfirmedBlock(blc: Block, actRef: ActorRef) + ///////////////////////////////块确认actor的相关消息,结束////////////////////////////// +} diff --git a/src/main/scala/rep/network/consensus/common/algorithm/IAlgorithmOfVote.scala b/src/main/scala/rep/network/consensus/common/algorithm/IAlgorithmOfVote.scala new file mode 100644 index 00000000..a9127ca9 --- /dev/null +++ b/src/main/scala/rep/network/consensus/common/algorithm/IAlgorithmOfVote.scala @@ -0,0 +1,24 @@ +package rep.network.consensus.common.algorithm + +/** + * Created by jiangbuyun on 2020/03/17. + * 定义抽签算法的接口 + */ +trait IAlgorithmOfVote { + /** + * 获取出块人(竞争胜出者) + * @param nodes + * @tparam T + * @return + */ + def blocker(nodes:Array[String], position:Int):String + + /** + * 获取候选人节点 + * @param nodes + * @tparam T + * @param seed 随机种子 + * @return + */ + def candidators(Systemname:String,hash:String,nodes:Set[String], seed:Array[Byte]):Array[String] +} diff --git a/src/main/scala/rep/network/consensus/cfrd/vote/CRFDVoter.scala b/src/main/scala/rep/network/consensus/common/algorithm/IRandomAlgorithmOfVote.scala similarity index 61% rename from src/main/scala/rep/network/consensus/cfrd/vote/CRFDVoter.scala rename to src/main/scala/rep/network/consensus/common/algorithm/IRandomAlgorithmOfVote.scala index 258b16da..afff806b 100644 --- a/src/main/scala/rep/network/consensus/cfrd/vote/CRFDVoter.scala +++ b/src/main/scala/rep/network/consensus/common/algorithm/IRandomAlgorithmOfVote.scala @@ -1,39 +1,18 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ +package rep.network.consensus.common.algorithm -package rep.network.consensus.cfrd.vote - -import rep.crypto.Sha256 -import scala.collection.mutable -import rep.storage.util.pathUtil -import scala.math._ import rep.log.RepLogger +import rep.storage.util.pathUtil + +import scala.math.pow /** - * 系统默认 - * 候选人竞争实现 - * 出块人竞争实现 - * Created by shidianyue on 2017/5/15. - * - * @update 2018-05 jiangbuyun - */ -//TODO kami 应该在init的时候载入一个实现函数或者类。然后调用方法。写的更通用一些 -trait CRFDVoter extends VoterBase { + * Created by jiangbuyun on 2020/03/17. + * 实现随机抽签的算法 + */ + +class IRandomAlgorithmOfVote extends IAlgorithmOfVote { case class randomNumber(var number:Long,var generateSerial:Int) - + override def blocker(nodes: Array[String], position:Int): String = { if(nodes.nonEmpty){ var pos = position @@ -45,7 +24,7 @@ trait CRFDVoter extends VoterBase { null } } - + private def getRandomList(seed:Long,candidatorTotal:Int):Array[randomNumber]={ val m = pow(2,20).toLong val a = 2045 @@ -60,13 +39,13 @@ trait CRFDVoter extends VoterBase { var randomobj = new randomNumber(hashSeed,i) randomArray(i) = randomobj } - + randomArray = randomArray.sortWith( - (randomNumber_left,randomNumber_right)=> randomNumber_left.number < randomNumber_right.number) - + (randomNumber_left,randomNumber_right)=> randomNumber_left.number < randomNumber_right.number) + randomArray } - + override def candidators(Systemname:String,hash:String,nodes: Set[String], seed: Array[Byte]): Array[String] = { var nodesSeq = nodes.toSeq.sortBy(f=>(f)) var len = nodes.size / 2 + 1 @@ -91,10 +70,8 @@ trait CRFDVoter extends VoterBase { } RepLogger.debug(RepLogger.Vote_Logger, s"sysname=${Systemname},hash=${hash},hashvalue=${hashSeed},randomList=${randomList.mkString("|")}") RepLogger.debug(RepLogger.Vote_Logger, s"sysname=${Systemname},candidates=${candidate.mkString("|")}") - + candidate } } - - } diff --git a/src/main/scala/rep/network/consensus/common/block/IBlocker.scala b/src/main/scala/rep/network/consensus/common/block/IBlocker.scala new file mode 100644 index 00000000..cd46871e --- /dev/null +++ b/src/main/scala/rep/network/consensus/common/block/IBlocker.scala @@ -0,0 +1,141 @@ +package rep.network.consensus.common.block + +import akka.actor.Props +import akka.pattern.{AskTimeoutException, ask} +import akka.util.Timeout +import rep.app.conf.{SystemProfile, TimePolicy} +import rep.log.{RepLogger, RepTimeTracer} +import rep.network.base.ModuleBase +import rep.network.consensus.common.MsgOfConsensus.{PreTransBlock, PreTransBlockResult} +import rep.network.consensus.util.BlockHelp +import rep.network.module.ModuleActorType +import rep.protos.peer.Block +import rep.storage.ImpDataAccess + +import scala.concurrent.Await +import scala.util.control.Breaks.{break, breakable} + + + +/** + * Created by jiangbuyun on 2020/03/17. + * CFRD管理的actor + */ + +object IBlocker { + def props(name: String): Props = Props(classOf[IBlocker], name) +} + +abstract class IBlocker(moduleName: String) extends ModuleBase(moduleName) { + import rep.protos.peer.Transaction + + import scala.collection.mutable.ArrayBuffer + import scala.concurrent.duration._ + + protected val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag) + implicit val timeout = Timeout(TimePolicy.getTimeoutPreload.seconds) + + protected def CollectedTransOfBlock(start: Int, num: Int, limitsize: Int): ArrayBuffer[Transaction] = { + var result = ArrayBuffer.empty[Transaction] + try { + val tmplist = pe.getTransPoolMgr.getTransListClone(start, num, pe.getSysTag) + if (tmplist.size > 0) { + val currenttime = System.currentTimeMillis() / 1000 + var transsize = 0 + breakable( + tmplist.foreach(f => { + transsize += f.toByteArray.size + if (transsize * 3 > limitsize) { + //区块的长度限制 + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"block too length,txid=${f.id}" + "~" + selfAddr)) + break + } else { + f +=: result + } + })) + if (result.isEmpty && tmplist.size >= SystemProfile.getMinBlockTransNum) { + result = CollectedTransOfBlock(start + num, num, limitsize) + } + } + } finally { + } + result + } + + + protected def ExecuteTransactionOfBlock(block: Block): Block = { + try { + val future = pe.getActorRef(ModuleActorType.ActorType.dispatchofpreload) ? PreTransBlock(block, "preload") + val result = Await.result(future, timeout.duration).asInstanceOf[PreTransBlockResult] + if (result.result) { + result.blc + } else { + null + } + } catch { + case e: AskTimeoutException => null + } + } + + + /*protected def PackedBlock(start:Int = 0, h:Long) : Block = { + RepTimeTracer.setStartTime(pe.getSysTag, "Block", System.currentTimeMillis(), h, 0) + RepTimeTracer.setStartTime(pe.getSysTag, "createBlock", System.currentTimeMillis(), h, 0) + RepTimeTracer.setStartTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), h, 0) + val trans = CollectedTransOfBlock(start, SystemProfile.getLimitBlockTransNum, SystemProfile.getBlockLength).reverse.toSeq + //todo 交易排序 + if (trans.size >= SystemProfile.getMinBlockTransNum) { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,CollectedTransOfBlock success,height=${h}" + "~" + selfAddr)) + RepTimeTracer.setEndTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), h, trans.size) + + var blc = BlockHelp.WaitingForExecutionOfBlock(pe.getBlocker.voteBlockHash, h, trans.toSeq) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,height=${blc.height},local height=${h}" + "~" + selfAddr)) + RepTimeTracer.setStartTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) + blc = ExecuteTransactionOfBlock(blc) + if (blc != null) { + RepTimeTracer.setEndTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,prelaod success,height=${blc.height}" + "~" + selfAddr)) + blc = BlockHelp.AddBlockHash(blc) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,AddBlockHash success,height=${blc.height}" + "~" + selfAddr)) + BlockHelp.AddSignToBlock(blc, pe.getSysTag) + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,preload error" + "~" + selfAddr)) + PackedBlock(start + trans.size, h) + } + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,trans count error" + "~" + selfAddr)) + null + } + }*/ + + protected def PackedBlock(start: Int = 0): Block = { + RepTimeTracer.setStartTime(pe.getSysTag, "Block", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) + RepTimeTracer.setStartTime(pe.getSysTag, "createBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) + RepTimeTracer.setStartTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) + val trans = CollectedTransOfBlock(start, SystemProfile.getLimitBlockTransNum, SystemProfile.getBlockLength).reverse + //todo 交易排序 + if (trans.size >= SystemProfile.getMinBlockTransNum) { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,CollectedTransOfBlock success,height=${pe.getBlocker.VoteHeight + 1},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) + RepTimeTracer.setEndTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, trans.size) + //此处建立新块必须采用抽签模块的抽签结果来进行出块,否则出现刚抽完签,马上有新块的存储完成,就会出现错误 + var blc = BlockHelp.WaitingForExecutionOfBlock(pe.getBlocker.voteBlockHash, pe.getBlocker.VoteHeight + 1, trans.toSeq) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) + RepTimeTracer.setStartTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) + blc = ExecuteTransactionOfBlock(blc) + if (blc != null) { + RepTimeTracer.setEndTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,prelaod success,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) + blc = BlockHelp.AddBlockHash(blc) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,AddBlockHash success,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) + BlockHelp.AddSignToBlock(blc, pe.getSysTag) + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,preload error" + "~" + selfAddr)) + PackedBlock(start + trans.size) + } + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,trans count error" + "~" + selfAddr)) + null + } + } + +} diff --git a/src/main/scala/rep/network/consensus/common/vote/IVoter.scala b/src/main/scala/rep/network/consensus/common/vote/IVoter.scala new file mode 100644 index 00000000..17635a5c --- /dev/null +++ b/src/main/scala/rep/network/consensus/common/vote/IVoter.scala @@ -0,0 +1,89 @@ +package rep.network.consensus.common.vote + +import akka.actor.Props +import rep.app.conf.{SystemCertList, SystemProfile} +import rep.crypto.Sha256 +import rep.log.RepLogger +import rep.network.base.ModuleBase +import rep.network.consensus.common.algorithm.IRandomAlgorithmOfVote +import rep.network.module.cfrd.CFRDActorType +import rep.network.util.NodeHelp +import rep.storage.ImpDataAccess +import rep.utils.GlobalUtils.BlockerInfo +import rep.network.consensus.common.MsgOfConsensus.GenesisBlock +import rep.network.consensus.common.algorithm.IAlgorithmOfVote + +/** + * Created by jiangbuyun on 2020/03/17. + * 抽象抽签类 + */ + +object IVoter{ + def props(name: String): Props = Props(classOf[IVoter], name) +} + +abstract class IVoter(moduleName: String) extends ModuleBase(moduleName) { + + val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag) + + protected var candidator: Array[String] = Array.empty[String] + protected var Blocker: BlockerInfo = BlockerInfo("", -1, 0l, "", -1) + protected var voteCount = 0 + protected var algorithmInVoted:IAlgorithmOfVote = null + + + protected def checkTranNum: Boolean = { + pe.getTransPoolMgr.getTransLength() >= SystemProfile.getMinBlockTransNum + } + + protected def cleanVoteInfo = { + this.voteCount = 0 + candidator = Array.empty[String] + this.Blocker = BlockerInfo("", -1, 0l, "", -1) + pe.resetBlocker(this.Blocker) + } + + protected def getSystemBlockHash: String = { + if (pe.getCurrentBlockHash == "") { + pe.resetSystemCurrentChainStatus(dataaccess.getBlockChainInfo()) + } + pe.getCurrentBlockHash + } + + protected def resetCandidator(currentblockhash: String) = { + candidator = algorithmInVoted.candidators(pe.getSysTag, currentblockhash, SystemCertList.getSystemCertList, Sha256.hash(currentblockhash)) + } + + protected def resetBlocker(idx: Int, currentblockhash: String, currentheight: Long) = { + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},votelist=${candidator.toArray[String].mkString("|")},idx=${idx}")) + this.Blocker = BlockerInfo(algorithmInVoted.blocker(candidator.toArray[String], idx), idx, System.currentTimeMillis(), currentblockhash, currentheight) + pe.resetBlocker(this.Blocker) + NoticeBlockerMsg + } + + protected def NoticeBlockerMsg:Unit + + protected def DelayVote:Unit + + protected def vote(isForce:Boolean):Unit + + + + protected def voteMsgHandler(isForce:Boolean) = { + if (pe.getNodeMgr.getStableNodes.size >= SystemProfile.getVoteNoteMin) { + //只有共识节点符合要求之后开始工作 + if (getSystemBlockHash == "") { + //系统属于初始化状态 + if (NodeHelp.isSeedNode(pe.getSysTag)) { + // 建立创世块消息 + pe.getActorRef(CFRDActorType.ActorType.gensisblock) ! GenesisBlock + } + } else { + if (!pe.isSynching) { + vote(isForce) + } + } + } + DelayVote + } +} diff --git a/src/main/scala/rep/network/consensus/raft/block/BlockerOfRAFT.scala b/src/main/scala/rep/network/consensus/raft/block/BlockerOfRAFT.scala new file mode 100644 index 00000000..634cbe39 --- /dev/null +++ b/src/main/scala/rep/network/consensus/raft/block/BlockerOfRAFT.scala @@ -0,0 +1,100 @@ +package rep.network.consensus.raft.block + +import akka.actor.Props +import akka.cluster.pubsub.DistributedPubSubMediator.Publish +import rep.log.{RepLogger, RepTimeTracer} +import rep.network.autotransaction.Topic +import rep.network.module.cfrd.CFRDActorType +import rep.network.util.NodeHelp +import rep.protos.peer.{Block, Event} +import rep.utils.GlobalUtils.EventType +import rep.network.consensus.cfrd.MsgOfCFRD.{ CreateBlock,VoteOfBlocker} +import rep.network.consensus.common.block.IBlocker +import rep.network.consensus.common.MsgOfConsensus.ConfirmedBlock +import rep.app.conf.{SystemProfile} +import rep.network.consensus.util.BlockHelp + + +/** + *Created by jiangbuyun on 2020/03/17. + * RAFT共识协议的出块人actor + */ +object BlockerOfRAFT { + def props(name: String): Props = Props(classOf[BlockerOfRAFT], name) +} + +class BlockerOfRAFT (moduleName: String) extends IBlocker(moduleName){ + var preblock: Block = null + + override def preStart(): Unit = { + RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("BlockerOfRAFT module start")) + //pe.register(CFRDActorType.ActorType.blocker,self) + super.preStart() + } + + override protected def PackedBlock(start: Int = 0): Block = { + RepTimeTracer.setStartTime(pe.getSysTag, "Block", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) + RepTimeTracer.setStartTime(pe.getSysTag, "createBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) + RepTimeTracer.setStartTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, 0) + val trans = CollectedTransOfBlock(start, SystemProfile.getLimitBlockTransNum, SystemProfile.getBlockLength).reverse.toSeq + //todo 交易排序 + if (trans.size >= SystemProfile.getMinBlockTransNum) { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,CollectedTransOfBlock success,height=${pe.getBlocker.VoteHeight },local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) + RepTimeTracer.setEndTime(pe.getSysTag, "collectTransToBlock", System.currentTimeMillis(), pe.getBlocker.VoteHeight + 1, trans.size) + //此处建立新块必须采用抽签模块的抽签结果来进行出块,否则出现刚抽完签,马上有新块的存储完成,就会出现错误 + var blc = BlockHelp.WaitingForExecutionOfBlock(pe.getCurrentBlockHash, pe.getCurrentHeight + 1, trans) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,height=${blc.height},local height=${pe.getCurrentHeight}" + "~" + selfAddr)) + RepTimeTracer.setStartTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) + blc = ExecuteTransactionOfBlock(blc) + if (blc != null) { + RepTimeTracer.setEndTime(pe.getSysTag, "PreloadTrans", System.currentTimeMillis(), blc.height, blc.transactions.size) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,prelaod success,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) + blc = BlockHelp.AddBlockHash(blc) + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,AddBlockHash success,height=${blc.height},local height=${pe.getBlocker.VoteHeight}" + "~" + selfAddr)) + BlockHelp.AddSignToBlock(blc, pe.getSysTag) + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,preload error" + "~" + selfAddr)) + PackedBlock(start + trans.size) + } + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,trans count error" + "~" + selfAddr)) + null + } + } + + private def CreateBlockHandler = { + var blc : Block = null + + blc = PackedBlock(0) + if (blc != null) { + RepTimeTracer.setEndTime(pe.getSysTag, "createBlock", System.currentTimeMillis(), blc.height, blc.transactions.size) + this.preblock = blc + schedulerLink = clearSched() + pe.setCreateHeight(preblock.height) + mediator ! Publish(Topic.Block, ConfirmedBlock(preblock, self)) + } else { + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,CreateBlock is null" + "~" + selfAddr)) + pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker + } + } + + override def receive = { + //创建块请求(给出块人) + case CreateBlock => + if (!pe.isSynching) { + if (NodeHelp.isBlocker(pe.getBlocker.blocker, pe.getSysTag)){ + sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.CANDIDATOR) + if (preblock == null || (preblock.previousBlockHash.toStringUtf8() != pe.getCurrentBlockHash)) { + //是出块节点 + CreateBlockHandler + } + } + } else { + //节点状态不对 + RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,node status error,status is synching,height=${pe.getCurrentHeight}" + "~" + selfAddr)) + } + + case _ => //ignore + } + +} diff --git a/src/main/scala/rep/network/consensus/raft/vote/VoterOfRAFT.scala b/src/main/scala/rep/network/consensus/raft/vote/VoterOfRAFT.scala new file mode 100644 index 00000000..3816d86b --- /dev/null +++ b/src/main/scala/rep/network/consensus/raft/vote/VoterOfRAFT.scala @@ -0,0 +1,106 @@ +package rep.network.consensus.raft.vote + +import akka.actor.Props +import rep.app.conf.{SystemCertList, SystemProfile, TimePolicy} +import rep.log.RepLogger +import rep.network.consensus.cfrd.MsgOfCFRD.{CreateBlock, VoteOfBlocker, VoteOfForce} +import rep.network.consensus.common.algorithm.IRandomAlgorithmOfVote +import rep.network.consensus.common.vote.IVoter +import rep.network.module.cfrd.CFRDActorType +import rep.network.sync.SyncMsg.StartSync +import rep.network.util.NodeHelp +import rep.utils.GlobalUtils.BlockerInfo + +/** + * Created by jiangbuyun on 2020/03/19. + * RAFT共识实现的抽签actor + */ + +object VoterOfRAFT{ + def props(name: String): Props = Props(classOf[VoterOfRAFT],name) +} + +class VoterOfRAFT (moduleName: String) extends IVoter(moduleName: String) { + import scala.concurrent.duration._ + import context.dispatcher + + this.algorithmInVoted = new IRandomAlgorithmOfVote + override def preStart(): Unit = { + RepLogger.info(RepLogger.Vote_Logger, this.getLogMsgPrefix("VoterOfCFRD module start")) + } + + override protected def NoticeBlockerMsg: Unit = { + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},notice")) + if (this.Blocker.blocker.equals(pe.getSysTag)) { + //发送建立新块的消息 + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},send create block")) + pe.getActorRef(CFRDActorType.ActorType.blocker) ! CreateBlock + } + } + + override protected def resetBlocker(idx: Int, currentblockhash: String, currentheight: Long) = { + pe.setConfirmHeight(0) + pe.setCreateHeight(0) + + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},votelist=${candidator.toArray[String].mkString("|")},idx=${idx}")) + this.Blocker = BlockerInfo(algorithmInVoted.blocker(candidator.toArray[String], idx), idx, System.currentTimeMillis(), currentblockhash, currentheight) + pe.resetBlocker(this.Blocker) + NoticeBlockerMsg + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},blocker=${this.Blocker.blocker},currentHeight=${pe.getMaxHeight4SimpleRaft}" + "~" + selfAddr)) + } + + override protected def DelayVote: Unit = { + this.voteCount += 1 + var time = this.voteCount * TimePolicy.getVoteRetryDelay + schedulerLink = clearSched() + schedulerLink = scheduler.scheduleOnce(TimePolicy.getVoteRetryDelay.millis, self, VoteOfBlocker) + } + + override protected def vote(isForce: Boolean): Unit = { + if(this.Blocker.blocker == ""){ + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},first voter,currentHeight=${pe.getCurrentHeight},currentHash=${pe.getCurrentBlockHash}" + "~" + selfAddr)) + val maxinfo = pe.getStartVoteInfo + var currentblockhash:String = "" + var currentheight : Long = 0 + if(maxinfo.height > 0){ + currentblockhash = maxinfo.hash + currentheight = maxinfo.height + }else{ + currentblockhash = pe.getCurrentBlockHash + currentheight = pe.getCurrentHeight + } + if(currentheight > 0){ + this.cleanVoteInfo + this.resetCandidator(currentblockhash) + this.resetBlocker(0, currentblockhash, currentheight) + } + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},first voter,currentHeight=${currentheight},currentHash=${currentblockhash}" + "~" + selfAddr)) + }else if((this.Blocker.VoteHeight +SystemProfile.getBlockNumberOfRaft) <= pe.getMaxHeight4SimpleRaft){ + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},second voter,currentHeight=${pe.getMaxHeight4SimpleRaft}" + "~" + selfAddr)) + val block = dataaccess.getBlock4ObjectByHeight(this.Blocker.VoteHeight +SystemProfile.getBlockNumberOfRaft) + if(block != null){ + val currentblockhash = block.hashOfBlock.toStringUtf8() + val currentheight = block.height + this.cleanVoteInfo + this.resetCandidator(currentblockhash) + this.resetBlocker(0, currentblockhash, currentheight) + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},read block voter,currentHeight=${this.Blocker.VoteHeight +SystemProfile.getBlockNumberOfRaft},currentHash=${currentblockhash}" + "~" + selfAddr)) + }else{ + RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},second voter in synch,currentHeight=${this.Blocker.VoteHeight +SystemProfile.getBlockNumberOfRaft}" + "~" + selfAddr)) + pe.getActorRef(CFRDActorType.ActorType.synchrequester) ! StartSync(false) + } + }else{ + NoticeBlockerMsg + } + } + + override def receive: Receive = { + case VoteOfBlocker => + if (NodeHelp.isCandidateNow(pe.getSysTag, SystemCertList.getSystemCertList)) { + voteMsgHandler(false) + } + case VoteOfForce=> + voteMsgHandler(true) + } + +} diff --git a/src/main/scala/rep/network/consensus/util/BlockHelp.scala b/src/main/scala/rep/network/consensus/util/BlockHelp.scala index af9e3fdf..f27812ad 100644 --- a/src/main/scala/rep/network/consensus/util/BlockHelp.scala +++ b/src/main/scala/rep/network/consensus/util/BlockHelp.scala @@ -37,6 +37,8 @@ import rep.network.autotransaction.PeerHelper import rep.utils.IdTool object BlockHelp { + + private val versionOfBlock = 1 /****************************背书相关的操作开始**********************************************************/ def SignDataOfBlock(NonEndorseDataOfBlock: Array[Byte], alise: String): Signature = { try { @@ -108,7 +110,7 @@ object BlockHelp { try { val millis = TimeUtils.getCurrentTime() new Block( - 1, + versionOfBlock, h, trans, null, diff --git a/src/main/scala/rep/network/consensus/cfrd/block/GenesisBlocker.scala b/src/main/scala/rep/network/genesis/GenesisBlocker.scala similarity index 75% rename from src/main/scala/rep/network/consensus/cfrd/block/GenesisBlocker.scala rename to src/main/scala/rep/network/genesis/GenesisBlocker.scala index 20359f89..76501dc0 100644 --- a/src/main/scala/rep/network/consensus/cfrd/block/GenesisBlocker.scala +++ b/src/main/scala/rep/network/genesis/GenesisBlocker.scala @@ -14,62 +14,35 @@ * */ -package rep.network.consensus.cfrd.block +package rep.network.genesis -import akka.util.Timeout - -import scala.concurrent.duration._ -import akka.pattern.ask -import akka.pattern.AskTimeoutException - -import scala.concurrent._ -import akka.actor.{ActorRef, Address, Props} +import akka.actor.Props import akka.cluster.pubsub.DistributedPubSubMediator.Publish -import com.google.protobuf.ByteString -import rep.app.conf.{SystemProfile, TimePolicy} -import rep.crypto.Sha256 -import rep.network._ -import rep.network.base.ModuleBase -import rep.network.consensus.cfrd.block.Blocker.{ConfirmedBlock, PreTransBlock, PreTransBlockResult} -import rep.protos.peer._ -import rep.storage.ImpDataAccess -import rep.network.module.ModuleActorType -import rep.utils.GlobalUtils.{ BlockEvent, EventType, NodeStatus} - -import scala.collection.mutable -import com.sun.beans.decoder.FalseElementHandler - -import scala.util.control.Breaks -import rep.utils.IdTool - -import scala.util.control.Breaks._ -import rep.network.consensus.util.{BlockHelp, BlockVerify} -import rep.network.util.NodeHelp +import akka.pattern.{AskTimeoutException, ask} +import akka.util.Timeout +import rep.app.conf.TimePolicy import rep.log.RepLogger import rep.network.autotransaction.Topic - -object GenesisBlocker { - def props(name: String): Props = Props(classOf[GenesisBlocker], name) - - case object GenesisBlock - -} +import rep.network.base.ModuleBase +import rep.network.consensus.util.BlockHelp +import rep.network.module.ModuleActorType +import rep.network.util.NodeHelp +import rep.protos.peer._ +import rep.storage.ImpDataAccess +import rep.network.consensus.common.MsgOfConsensus.{ConfirmedBlock,GenesisBlock,PreTransBlockResult,PreTransBlock} +import scala.concurrent._ /** - * 出块模块 - * - * @author shidianyue - * @version 1.0 - * @since 1.0 - * @param moduleName 模块名称 + * Created by jiangbuyun on 2020/03/19. + * 建立创世块actor */ +object GenesisBlocker { + def props(name: String): Props = Props(classOf[GenesisBlocker], name) +} + class GenesisBlocker(moduleName: String) extends ModuleBase(moduleName) { - import context.dispatcher import scala.concurrent.duration._ - import akka.actor.ActorSelection - import scala.collection.mutable.ArrayBuffer - import rep.protos.peer.{ Transaction } val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag) implicit val timeout = Timeout(TimePolicy.getTimeoutPreload*20.seconds) @@ -100,7 +73,7 @@ class GenesisBlocker(moduleName: String) extends ModuleBase(moduleName) { override def receive = { //创建块请求(给出块人) - case GenesisBlocker.GenesisBlock => + case GenesisBlock => if(dataaccess.getBlockChainInfo().height == 0 && NodeHelp.isSeedNode(pe.getSysTag) ){ if(this.preblock != null){ mediator ! Publish(Topic.Block, ConfirmedBlock(preblock, sender)) diff --git a/src/main/scala/rep/network/module/IModule.scala b/src/main/scala/rep/network/module/IModule.scala index c2d28efc..a2c449f3 100644 --- a/src/main/scala/rep/network/module/IModule.scala +++ b/src/main/scala/rep/network/module/IModule.scala @@ -1,5 +1,9 @@ package rep.network.module +/** + * Created by jiangbuyun on 2020/03/15. + * 模块管理的接口 + */ trait IModule { def startupConsensus: Unit def loadConsensusModule:Unit diff --git a/src/main/scala/rep/network/module/IModuleManager.scala b/src/main/scala/rep/network/module/IModuleManager.scala index 79b0e9f3..5459d0f2 100644 --- a/src/main/scala/rep/network/module/IModuleManager.scala +++ b/src/main/scala/rep/network/module/IModuleManager.scala @@ -8,15 +8,15 @@ import rep.crypto.cert.SignTool import rep.log.{RepLogger, RepTimeTracer} import rep.network.autotransaction.PeerHelper import rep.network.base.ModuleBase -import rep.network.cache.TransactionPool import rep.network.cluster.MemberListener +import rep.network.module.cfrd.CFRDActorType import rep.network.transaction.DispatchOfPreload -import rep.network.persistence.Storager import rep.sc.TransactionDispatcher import rep.storage.ImpDataAccess import rep.storage.verify.verify4Storage import rep.ui.web.EventServer import rep.utils.ActorUtils +import rep.network.genesis.GenesisBlocker /** @@ -74,7 +74,7 @@ class IModuleManager(moduleName: String, sysTag: String, enableStatistic: Boolea private def loadCommonActor:Unit = { loadApiModule loadTransModule - loadStorageModule + loadGensisModule loadClusterModule } @@ -96,17 +96,18 @@ class IModuleManager(moduleName: String, sysTag: String, enableStatistic: Boolea pe.register(ModuleActorType.ActorType.transactiondispatcher, context.actorOf(TransactionDispatcher.props("transactiondispatcher"), "transactiondispatcher")) } pe.register(ModuleActorType.ActorType.dispatchofpreload, context.actorOf(DispatchOfPreload.props("dispatchofpreload"), "dispatchofpreload")) - pe.register(ModuleActorType.ActorType.transactionpool, context.actorOf(TransactionPool.props("transactionpool"), "transactionpool")) - } - private def loadStorageModule:Any={ - pe.register(ModuleActorType.ActorType.storager,context.actorOf(Storager.props("storager"), "storager")) } private def loadClusterModule = { context.actorOf(MemberListener.props("memberlistener"), "memberlistener") } + private def loadGensisModule:Any={ + pe.register(CFRDActorType.ActorType.gensisblock,context.actorOf(GenesisBlocker.props("gensisblock"), "gensisblock")) + + } + //启动共识模块,不同的共识方式启动的actor也不相同,继承模块需要重载此方法 override def startupConsensus: Unit = ??? diff --git a/src/main/scala/rep/network/module/ModuleActorType.scala b/src/main/scala/rep/network/module/ModuleActorType.scala index 21299874..0f7d805e 100644 --- a/src/main/scala/rep/network/module/ModuleActorType.scala +++ b/src/main/scala/rep/network/module/ModuleActorType.scala @@ -1,5 +1,10 @@ package rep.network.module + +/** + * Created by jiangbuyun on 2020/03/15. + * 共识模块中管理的公共的actor + */ object ModuleActorType { //系统的actor类型的注册,关键字以10开头 diff --git a/src/main/scala/rep/network/module/cfrd/CFRDActorType.scala b/src/main/scala/rep/network/module/cfrd/CFRDActorType.scala index 9ae5ae86..d030b3e8 100644 --- a/src/main/scala/rep/network/module/cfrd/CFRDActorType.scala +++ b/src/main/scala/rep/network/module/cfrd/CFRDActorType.scala @@ -1,5 +1,10 @@ package rep.network.module.cfrd + +/** + * Created by jiangbuyun on 2020/03/15. + * CFRD管理的actor + */ object CFRDActorType { //cfrd共识模式的actor类型的注册,关键字以20开头 case object ActorType{ diff --git a/src/main/scala/rep/network/module/cfrd/ModuleManagerOfCFRD.scala b/src/main/scala/rep/network/module/cfrd/ModuleManagerOfCFRD.scala index 4c8fec34..5c66bebb 100644 --- a/src/main/scala/rep/network/module/cfrd/ModuleManagerOfCFRD.scala +++ b/src/main/scala/rep/network/module/cfrd/ModuleManagerOfCFRD.scala @@ -1,12 +1,24 @@ package rep.network.module.cfrd -import akka.actor.{ Props} -import rep.network.consensus.cfrd.block.{Blocker, ConfirmOfBlock, EndorseCollector, GenesisBlocker} +import akka.actor.Props +import rep.log.RepLogger +import rep.network.cache.cfrd.TransactionPoolOfCFRD +import rep.network.confirmblock.common.ConfirmOfBlock +import rep.network.consensus.cfrd.block.EndorseCollector import rep.network.consensus.cfrd.endorse.DispatchOfRecvEndorsement -import rep.network.consensus.cfrd.vote.Voter +import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker import rep.network.module.{IModuleManager, ModuleActorType} -import rep.network.sync.{SynchronizeRequester4Future, SynchronizeResponser} +import rep.network.sync.response.SynchronizeResponser +import rep.network.sync.request.cfrd.SynchRequesterOfCFRD +import rep.network.consensus.cfrd.block.BlockerOfCFRD +import rep.network.consensus.cfrd.vote.VoterOfCFRD +import rep.network.persistence.cfrd.StoragerOfCFRD + +/** + * Created by jiangbuyun on 2020/03/15. + * CFRD的模块管理类,继承公共的模块管理类,实现CFRD的自己的模块 + */ object ModuleManagerOfCFRD{ def props(name: String, sysTag: String, enableStatistic: Boolean, enableWebSocket: Boolean, isStartup: Boolean): Props = Props(classOf[ModuleManagerOfCFRD], name, sysTag, enableStatistic: Boolean, enableWebSocket: Boolean, isStartup: Boolean) @@ -14,20 +26,26 @@ object ModuleManagerOfCFRD{ class ModuleManagerOfCFRD(moduleName: String, sysTag: String, enableStatistic: Boolean, enableWebSocket: Boolean, isStartup: Boolean) extends IModuleManager(moduleName,sysTag, enableStatistic, enableWebSocket, isStartup){ + override def preStart(): Unit = { + RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix( "ModuleManagerOfCFRD Start")) + } + //启动共识模块,启动CFRD共识 override def startupConsensus: Unit = { - pe.getActorRef(CFRDActorType.ActorType.voter) ! Voter.VoteOfBlocker + pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker } override def loadConsensusModule = { - pe.register(CFRDActorType.ActorType.blocker,context.actorOf(Blocker.props("blocker"), "blocker")) + pe.register(ModuleActorType.ActorType.transactionpool, context.actorOf(TransactionPoolOfCFRD.props("transactionpool"), "transactionpool")) + pe.register(ModuleActorType.ActorType.storager,context.actorOf(StoragerOfCFRD.props("storager"), "storager")) + pe.register(CFRDActorType.ActorType.blocker,context.actorOf(BlockerOfCFRD.props("blocker"), "blocker")) + pe.register(CFRDActorType.ActorType.confirmerofblock,context.actorOf(ConfirmOfBlock.props("confirmerofblock"), "confirmerofblock")) pe.register(CFRDActorType.ActorType.endorsementcollectioner,context.actorOf(EndorseCollector.props("endorsementcollectioner"), "endorsementcollectioner")) pe.register(CFRDActorType.ActorType.dispatchofRecvendorsement,context.actorOf(DispatchOfRecvEndorsement.props("dispatchofRecvendorsement"), "dispatchofRecvendorsement")) - pe.register(CFRDActorType.ActorType.voter,context.actorOf(Voter.props("voter"), "voter")) - pe.register(CFRDActorType.ActorType.gensisblock,context.actorOf(GenesisBlocker.props("gensisblock"), "gensisblock")) - pe.register(CFRDActorType.ActorType.confirmerofblock,context.actorOf(ConfirmOfBlock.props("confirmerofblock"), "confirmerofblock")) + pe.register(CFRDActorType.ActorType.voter,context.actorOf(VoterOfCFRD.props("voter"), "voter")) - pe.register(CFRDActorType.ActorType.synchrequester,context.actorOf(SynchronizeRequester4Future.props("synchrequester"), "synchrequester")) + + pe.register(CFRDActorType.ActorType.synchrequester,context.actorOf(SynchRequesterOfCFRD.props("synchrequester"), "synchrequester")) pe.register(CFRDActorType.ActorType.synchresponser,context.actorOf(SynchronizeResponser.props("synchresponser"), "synchresponser")) } diff --git a/src/main/scala/rep/network/module/raft/ModuleManagerOfRAFT.scala b/src/main/scala/rep/network/module/raft/ModuleManagerOfRAFT.scala new file mode 100644 index 00000000..167124e2 --- /dev/null +++ b/src/main/scala/rep/network/module/raft/ModuleManagerOfRAFT.scala @@ -0,0 +1,46 @@ +package rep.network.module.raft + +import akka.actor.Props +import rep.log.RepLogger +import rep.network.cache.raft.TransactionPoolOfRAFT +import rep.network.confirmblock.raft.ConfirmBlockOfRAFT +import rep.network.module.{IModuleManager, ModuleActorType} +import rep.network.module.cfrd.CFRDActorType +import rep.network.sync.response.SynchronizeResponser +import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker +import rep.network.consensus.raft.block.BlockerOfRAFT +import rep.network.consensus.raft.vote.VoterOfRAFT +import rep.network.persistence.raft.StoragerOfRAFT +import rep.network.sync.request.raft.SynchRequesterOfRAFT + +/** + * Created by jiangbuyun on 2020/03/19. + * 基于RAFT共识的模块管理actor + */ + +object ModuleManagerOfRAFT{ + def props(name: String, sysTag: String, enableStatistic: Boolean, enableWebSocket: Boolean, isStartup: Boolean): Props = Props(classOf[ModuleManagerOfRAFT], name, sysTag, enableStatistic: Boolean, enableWebSocket: Boolean, isStartup: Boolean) + +} + +class ModuleManagerOfRAFT(moduleName: String, sysTag: String, enableStatistic: Boolean, enableWebSocket: Boolean, isStartup: Boolean) extends IModuleManager(moduleName,sysTag, enableStatistic, enableWebSocket, isStartup){ + override def preStart(): Unit = { + RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix( "ModuleManagerOfRAFT Start")) + } + + //启动共识模块,启动CFRD共识 + override def startupConsensus: Unit = { + pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker + } + + override def loadConsensusModule = { + pe.register(ModuleActorType.ActorType.transactionpool, context.actorOf(TransactionPoolOfRAFT.props("transactionpool"), "transactionpool")) + pe.register(ModuleActorType.ActorType.storager,context.actorOf(StoragerOfRAFT.props("storager"), "storager")) + pe.register(CFRDActorType.ActorType.blocker,context.actorOf(BlockerOfRAFT.props("blocker"), "blocker")) + pe.register(CFRDActorType.ActorType.confirmerofblock,context.actorOf(ConfirmBlockOfRAFT.props("confirmerofblock"), "confirmerofblock")) + pe.register(CFRDActorType.ActorType.voter,context.actorOf(VoterOfRAFT.props("voter"), "voter")) + + pe.register(CFRDActorType.ActorType.synchrequester,context.actorOf(SynchRequesterOfRAFT.props("synchrequester"), "synchrequester")) + pe.register(CFRDActorType.ActorType.synchresponser,context.actorOf(SynchronizeResponser.props("synchresponser"), "synchresponser")) + } +} diff --git a/src/main/scala/rep/network/persistence/BlockCache.scala b/src/main/scala/rep/network/persistence/BlockCache.scala index dc2dccbf..6ebbb21e 100644 --- a/src/main/scala/rep/network/persistence/BlockCache.scala +++ b/src/main/scala/rep/network/persistence/BlockCache.scala @@ -19,8 +19,12 @@ package rep.network.persistence import java.util.concurrent.ConcurrentHashMap //import scala.jdk.CollectionConverters._ import scala.collection.JavaConverters._ -import rep.network.persistence.Storager.{ BlockRestore} +import rep.network.consensus.common.MsgOfConsensus.BlockRestore +/** + * Created by jiangbuyun on 2020/03/19. + * 缓存经过确认后的块 + */ class BlockCache { private implicit var caches = new ConcurrentHashMap[Long, BlockRestore] asScala diff --git a/src/main/scala/rep/network/persistence/Storager.scala b/src/main/scala/rep/network/persistence/IStorager.scala similarity index 70% rename from src/main/scala/rep/network/persistence/Storager.scala rename to src/main/scala/rep/network/persistence/IStorager.scala index 2a349931..7f17751d 100644 --- a/src/main/scala/rep/network/persistence/Storager.scala +++ b/src/main/scala/rep/network/persistence/IStorager.scala @@ -1,50 +1,28 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - package rep.network.persistence - import akka.actor.{ActorRef, Props} import akka.cluster.pubsub.DistributedPubSubMediator.Publish import com.google.protobuf.ByteString -import rep.network.base.ModuleBase -import rep.protos.peer._ -import rep.storage.ImpDataAccess -import rep.network.consensus.cfrd.vote.Voter.VoteOfBlocker - -import scala.collection.mutable -import rep.utils.GlobalUtils.{ BlockEvent, EventType, NodeStatus} - -import scala.collection.immutable -import rep.network.sync.SyncMsg.{StartSync, SyncRequestOfStorager} -import rep.network.module.cfrd.CFRDActorType -import scala.util.control.Breaks._ -import rep.network.util.NodeHelp -import rep.network.sync.SyncMsg.{BlockDataOfRequest, BlockDataOfResponse} -import rep.log.RepLogger -import rep.log.RepTimeTracer import rep.app.conf.SystemCertList +import rep.log.{RepLogger, RepTimeTracer} import rep.network.autotransaction.Topic +import rep.network.base.ModuleBase +import rep.network.module.cfrd.CFRDActorType +import rep.network.sync.SyncMsg.{StartSync, SyncRequestOfStorager} +import rep.network.util.NodeHelp +import rep.protos.peer.{BlockchainInfo, Event} +import rep.storage.ImpDataAccess +import rep.network.consensus.common.MsgOfConsensus.{BatchStore,BlockRestore} +import scala.util.control.Breaks.{break, breakable} + +/** + * Created by jiangbuyun on 2020/03/19. + * 实现区块存储的抽象的actor + */ -object Storager { - def props(name: String): Props = Props(classOf[Storager], name) - - final case class BlockRestore(blk: Block, SourceOfBlock: Int, blker: ActorRef) - final case object BatchStore +object IStorager{ + def props(name: String): Props = Props(classOf[IStorager], name) case object SourceOfBlock { val CONFIRMED_BLOCK = 1 @@ -58,18 +36,13 @@ object Storager { case 2 => "SYNC_BLOCK" } } - } -class Storager(moduleName: String) extends ModuleBase(moduleName) { +abstract class IStorager (moduleName: String) extends ModuleBase(moduleName) { import context.dispatcher import scala.concurrent.duration._ - import rep.network.persistence.Storager.{ BlockRestore, SourceOfBlock ,BatchStore} + import rep.network.persistence.IStorager.{ SourceOfBlock } - override def preStart(): Unit = { - RepLogger.info(RepLogger.Storager_Logger, this.getLogMsgPrefix( "Storager Start")) - } - val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag) //private var precache: immutable.TreeMap[Long, BlockRestore] = new immutable.TreeMap[Long, BlockRestore]() @@ -77,26 +50,26 @@ class Storager(moduleName: String) extends ModuleBase(moduleName) { private def SaveBlock(blkRestore: BlockRestore): Integer = { var re: Integer = 0 try { - RepTimeTracer.setStartTime(pe.getSysTag, "storage-save", System.currentTimeMillis(),blkRestore.blk.height,blkRestore.blk.transactions.size) + RepTimeTracer.setStartTime(pe.getSysTag, "storage-save", System.currentTimeMillis(),blkRestore.blk.height,blkRestore.blk.transactions.size) RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix( s"PreBlockHash(Before presistence): ${pe.getCurrentBlockHash}" + "~" + selfAddr)) val result = dataaccess.restoreBlock(blkRestore.blk) if (result._1) { RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix( s"Restore blocks success,node number: ${pe.getSysTag},block number=${blkRestore.blk.height}" + "~" + selfAddr)) - + RepTimeTracer.setEndTime(pe.getSysTag, "storage-save", System.currentTimeMillis(),blkRestore.blk.height,blkRestore.blk.transactions.size) - + if(blkRestore.SourceOfBlock == SourceOfBlock.CONFIRMED_BLOCK && pe.getSysTag == pe.getBlocker.blocker && pe.getBlocker.VoteHeight+1 == blkRestore.blk.height){ RepTimeTracer.setEndTime(pe.getSysTag, "Block", System.currentTimeMillis(),blkRestore.blk.height,blkRestore.blk.transactions.size) } - + pe.getTransPoolMgr.removeTrans(blkRestore.blk.transactions,pe.getSysTag) pe.resetSystemCurrentChainStatus(new BlockchainInfo(result._2, result._3, ByteString.copyFromUtf8(result._4), ByteString.copyFromUtf8(result._5),ByteString.copyFromUtf8(result._6))) pe.getBlockCacheMgr.removeFromCache(blkRestore.blk.height) - + if (blkRestore.SourceOfBlock == SourceOfBlock.CONFIRMED_BLOCK && NodeHelp.checkBlocker(selfAddr, akka.serialization.Serialization.serializedActorPath(blkRestore.blker))) { - mediator ! Publish(Topic.Event, new Event(selfAddr, Topic.Block, Event.Action.BLOCK_NEW, Some(blkRestore.blk))) + mediator ! Publish(Topic.Event, new Event(selfAddr, Topic.Block, Event.Action.BLOCK_NEW, Some(blkRestore.blk))) } - + RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix( s"CurrentHash(After presistence): ${pe.getCurrentBlockHash}" + "~" + selfAddr)) RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix( s"save block success,height=${pe.getCurrentHeight},hash=${pe.getCurrentBlockHash}" + "~" + selfAddr)) } else { @@ -111,18 +84,20 @@ class Storager(moduleName: String) extends ModuleBase(moduleName) { re } + protected def sendVoteMessage:Unit + private def NoticeVoteModule = { if (NodeHelp.isCandidateNow(pe.getSysTag, SystemCertList.getSystemCertList)) { if (pe.getBlockCacheMgr.isEmpty ) { RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix("presistence is over,this is startup vote" + "~" + selfAddr)) //通知抽签模块,开始抽签 - pe.getActorRef( CFRDActorType.ActorType.voter) ! VoteOfBlocker + this.sendVoteMessage }else{ RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix( s"presistence is over,cache has data,do not vote,height=${pe.getCurrentHeight} ~" + selfAddr)) } } } - + private def NoticeSyncModule(blker: ActorRef) = { RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix( s"presistence is failed,must start sync ,height=${pe.getCurrentHeight} ~" + selfAddr)) if(!pe.getBlockCacheMgr.isEmpty){ @@ -144,32 +119,32 @@ class Storager(moduleName: String) extends ModuleBase(moduleName) { val minheight = hs(0) val maxheight = hs(hs.length-1) var loop :Long = minheight - + breakable( - while(loop <= maxheight){ - val _blkRestore = pe.getBlockCacheMgr.getBlockFromCache(loop) - if(loop > localchaininfo.height+1){ - //发送同步消息 - if(!pe.isSynching){ - NoticeSyncModule(_blkRestore.blker) - } - break - }else{ - val r = RestoreBlock(_blkRestore) - if(r == 0){ - localchaininfo = pe.getSystemCurrentChainStatus - } + while(loop <= maxheight){ + val _blkRestore = pe.getBlockCacheMgr.getBlockFromCache(loop) + if(loop > localchaininfo.height+1){ + //发送同步消息 + if(!pe.isSynching){ + NoticeSyncModule(_blkRestore.blker) + } + break + }else{ + val r = RestoreBlock(_blkRestore) + if(r == 0){ + localchaininfo = pe.getSystemCurrentChainStatus } - loop += 1l } + loop += 1l + } ) - NoticeVoteModule + NoticeVoteModule }catch{ case e: RuntimeException => RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix( s"Restore blocks error : ${e.getMessage}" + "~" + selfAddr)) } } - + def RestoreBlock(blkRestore: BlockRestore): Integer = { var re: Integer = 1 try { @@ -192,8 +167,8 @@ class Storager(moduleName: String) extends ModuleBase(moduleName) { RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix(s"block restor is failed in persistence module,block prehash error,must restart height:${blkRestore.blk.height}" + "~" + selfAddr)) } } else if (blkRestore.blk.height < (pe.getCurrentHeight + 1)) { - pe.getBlockCacheMgr.removeFromCache(blkRestore.blk.height) - RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix(s"Restore blocks error : current height=${blkRestore.blk.height} less than local height${pe.getCurrentHeight}" + "~" + selfAddr)) + pe.getBlockCacheMgr.removeFromCache(blkRestore.blk.height) + RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix(s"Restore blocks error : current height=${blkRestore.blk.height} less than local height${pe.getCurrentHeight}" + "~" + selfAddr)) } } catch { case e: RuntimeException => @@ -201,7 +176,7 @@ class Storager(moduleName: String) extends ModuleBase(moduleName) { } re } - + override def receive = { case blkRestore: BlockRestore => RepLogger.trace(RepLogger.Storager_Logger, this.getLogMsgPrefix( s"node number:${pe.getSysTag},restore single block,height:${blkRestore.blk.height}" + "~" + selfAddr)) @@ -209,12 +184,11 @@ class Storager(moduleName: String) extends ModuleBase(moduleName) { pe.getBlockCacheMgr.addToCache(blkRestore) Handler RepTimeTracer.setEndTime(pe.getSysTag, "storage-handle", System.currentTimeMillis(),blkRestore.blk.height,blkRestore.blk.transactions.size) - + case BatchStore => - RepTimeTracer.setStartTime(pe.getSysTag, "storage-handle-noarg", System.currentTimeMillis(),pe.getCurrentHeight,120) - Handler - RepTimeTracer.setEndTime(pe.getSysTag, "storage-handle-noarg", System.currentTimeMillis(),pe.getCurrentHeight,120) + RepTimeTracer.setStartTime(pe.getSysTag, "storage-handle-noarg", System.currentTimeMillis(),pe.getCurrentHeight,120) + Handler + RepTimeTracer.setEndTime(pe.getSysTag, "storage-handle-noarg", System.currentTimeMillis(),pe.getCurrentHeight,120) case _ => //ignore } - -} \ No newline at end of file +} diff --git a/src/main/scala/rep/network/persistence/cfrd/StoragerOfCFRD.scala b/src/main/scala/rep/network/persistence/cfrd/StoragerOfCFRD.scala new file mode 100644 index 00000000..1374f645 --- /dev/null +++ b/src/main/scala/rep/network/persistence/cfrd/StoragerOfCFRD.scala @@ -0,0 +1,26 @@ +package rep.network.persistence.cfrd + +import akka.actor.Props +import rep.log.RepLogger +import rep.network.module.cfrd.CFRDActorType +import rep.network.persistence.IStorager +import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker + +/** + * Created by jiangbuyun on 2020/03/19. + * 基于CFRD共识实现的存储actor + */ + +object StoragerOfCFRD{ + def props(name: String): Props = Props(classOf[StoragerOfCFRD], name) +} + +class StoragerOfCFRD (moduleName: String) extends IStorager (moduleName: String){ + override def preStart(): Unit = { + RepLogger.info(RepLogger.Storager_Logger, this.getLogMsgPrefix( "StoragerOfCFRD Start")) + } + + override protected def sendVoteMessage: Unit = { + pe.getActorRef( CFRDActorType.ActorType.voter) ! VoteOfBlocker + } +} diff --git a/src/main/scala/rep/network/persistence/raft/StoragerOfRAFT.scala b/src/main/scala/rep/network/persistence/raft/StoragerOfRAFT.scala new file mode 100644 index 00000000..a13a8ede --- /dev/null +++ b/src/main/scala/rep/network/persistence/raft/StoragerOfRAFT.scala @@ -0,0 +1,26 @@ +package rep.network.persistence.raft + +import akka.actor.Props +import rep.log.RepLogger +import rep.network.module.cfrd.CFRDActorType +import rep.network.persistence.IStorager +import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker + +/** + * Created by jiangbuyun on 2020/03/19. + * 基于RAFT共识实现的存储actor + */ + +object StoragerOfRAFT{ + def props(name: String): Props = Props(classOf[StoragerOfRAFT], name) +} + +class StoragerOfRAFT (moduleName: String) extends IStorager (moduleName: String){ + override def preStart(): Unit = { + RepLogger.info(RepLogger.Storager_Logger, this.getLogMsgPrefix( "StoragerOfCFRD Start")) + } + + override protected def sendVoteMessage: Unit = { + pe.getActorRef( CFRDActorType.ActorType.voter) ! VoteOfBlocker + } +} diff --git a/src/main/scala/rep/network/sync/SyncMsg.scala b/src/main/scala/rep/network/sync/SyncMsg.scala index c79490c3..5079bd5d 100644 --- a/src/main/scala/rep/network/sync/SyncMsg.scala +++ b/src/main/scala/rep/network/sync/SyncMsg.scala @@ -19,6 +19,12 @@ package rep.network.sync import rep.protos.peer._ import akka.actor.{ ActorRef, Props } +/** + * Created by jiangbuyun on 2020/03/19. + * 区块同步的消息以及数据的结构 + */ + + object SyncMsg { case class StartSync(isNoticeModuleMgr:Boolean) diff --git a/src/main/scala/rep/network/sync/SynchronizeRequester4Future.scala b/src/main/scala/rep/network/sync/SynchronizeRequester4Future.scala deleted file mode 100644 index 21135c7b..00000000 --- a/src/main/scala/rep/network/sync/SynchronizeRequester4Future.scala +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package rep.network.sync - -import akka.util.Timeout -import scala.concurrent.duration._ -import akka.pattern.ask -import akka.pattern.AskTimeoutException -import scala.concurrent._ - -import akka.actor.{ ActorRef, Props, Address, ActorSelection } -import akka.cluster.pubsub.DistributedPubSubMediator.Publish -import rep.network.base.ModuleBase -import rep.app.conf.TimePolicy -import rep.network.module.IModuleManager -import rep.storage.ImpDataAccess -import rep.protos.peer._ -import rep.network.persistence.Storager.{ BlockRestore, SourceOfBlock } -import scala.collection._ -import rep.utils.GlobalUtils.{ BlockEvent, EventType, NodeStatus } -import rep.app.conf.SystemProfile -import rep.network.util.NodeHelp -import rep.network.sync.SyncMsg.{ ResponseInfo, StartSync, BlockDataOfRequest, BlockDataOfResponse, SyncRequestOfStorager, ChainInfoOfRequest } -import scala.util.control.Breaks._ -import rep.log.RepLogger -import rep.network.module.ModuleActorType -import scala.collection.mutable.HashMap -import scala.collection.mutable.ArrayBuffer - -object SynchronizeRequester4Future { - def props(name: String): Props = Props(classOf[SynchronizeRequester4Future], name) - -} - -class SynchronizeRequester4Future(moduleName: String) extends ModuleBase(moduleName) { - import context.dispatcher - import scala.concurrent.duration._ - - implicit val timeout = Timeout(TimePolicy.getTimeoutSync.seconds) - private val responseActorName = "/user/modulemanager/synchresponser" - - override def preStart(): Unit = { - RepLogger.info(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("SynchronizeRequester4Future Start")) - } - - private def toAkkaUrl(addr: String, actorName: String): String = { - return addr + "/" + actorName; - } - - private def AsyncGetNodeOfChainInfo(addr: Address, lh: Long): Future[ResponseInfo] = Future { - //println(s"${pe.getSysTag}:entry AsyncGetNodeOfChainInfo") - var result: ResponseInfo = null - - try { - val selection: ActorSelection = context.actorSelection(toAkkaUrl(addr.toString, responseActorName)); - val future1 = selection ? ChainInfoOfRequest(lh) - //logMsg(LogType.INFO, "--------AsyncGetNodeOfChainInfo success") - result = Await.result(future1, timeout.duration).asInstanceOf[ResponseInfo] - } catch { - case e: AskTimeoutException => - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------AsyncGetNodeOfChainInfo timeout")) - null - case te: TimeoutException => - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------AsyncGetNodeOfChainInfo java timeout")) - null - } - - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"entry AsyncGetNodeOfChainInfo after,chaininfo=${result}")) - result - } - - private def AsyncGetNodeOfChainInfos(stablenodes: Set[Address], lh: Long): List[ResponseInfo] = { - //println(s"${pe.getSysTag}:entry AsyncGetNodeOfChainInfos") - //var result = new immutable.TreeMap[String, ResponseInfo]() - val listOfFuture: Seq[Future[ResponseInfo]] = stablenodes.toSeq.map(addr => { - AsyncGetNodeOfChainInfo(addr, lh) - }) - - val futureOfList: Future[List[ResponseInfo]] = Future.sequence(listOfFuture.toList).recover({ - case e: Exception => - null - }) - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AsyncGetNodeOfChainInfos 1")) - try { - val result1 = Await.result(futureOfList, timeout.duration).asInstanceOf[List[ResponseInfo]] - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AsyncGetNodeOfChainInfos 2")) - if (result1 == null) { - List.empty - } else { - result1 - } - } catch { - case te: TimeoutException => - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------AsyncGetNodeOfChainInfo java timeout")) - null - } - } - - private def getBlockData(height: Long, ref: ActorRef): Boolean = { - try { - sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, pe.getNodeMgr.getNodeName4AddrString(NodeHelp.getNodeAddress(ref)), Event.Action.BLOCK_SYNC_DATA) - val selection: ActorSelection = context.actorSelection(toAkkaUrl(NodeHelp.getNodeAddress(ref), responseActorName)); - val future1 = selection ? BlockDataOfRequest(height) - //logMsg(LogType.INFO, "--------AsyncGetNodeOfChainInfo success") - var result = Await.result(future1, timeout.duration).asInstanceOf[BlockDataOfResponse] - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"height=${height}--------getBlockData success")) - pe.getActorRef(ModuleActorType.ActorType.storager) ! BlockRestore(result.data, SourceOfBlock.SYNC_BLOCK, ref) - true - } catch { - case e: AskTimeoutException => - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------getBlockData timeout")) - false - case te: TimeoutException => - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------getBlockData java timeout")) - false - } - } - - private def getBlockDatas(lh: Long, rh: Long, actorref: ActorRef) = { - if (rh > lh) { - var height = lh + 1 - while (height <= rh) { - if (!pe.getBlockCacheMgr.exist(height) && !getBlockData(height, actorref)) { - getBlockData(height, actorref) - } - height += 1 - } - } - } - - private def checkHashAgreement(h: Long, ls: List[ResponseInfo], ns: Int, checkType: Int): (Boolean, String) = { - val hls = ls.filter(_.response.height == h) - var gls: List[(String, Int)] = null - checkType match { - case 1 => - //检查远端的最后一个块的hash的一致性 - gls = hls.groupBy(x => x.response.currentBlockHash.toStringUtf8()).map(x => (x._1, x._2.length)).toList.sortBy(x => -x._2) - case 2 => - //检查远端指定高度块的一致性 - gls = hls.groupBy(x => x.ChainInfoOfSpecifiedHeight.currentBlockHash.toStringUtf8()).map(x => (x._1, x._2.length)).toList.sortBy(x => -x._2) - } - val tmpgHash = gls.head._1 - val tmpgCount = gls.head._2 - if (NodeHelp.ConsensusConditionChecked(tmpgCount, ns)) { - (true, tmpgHash) - } else { - (false, "") - } - } - - private def Handler(isStartupSynch: Boolean): Boolean = { - var rb = true - val lh = pe.getCurrentHeight - val lhash = pe.getCurrentBlockHash - val lprehash = pe.getSystemCurrentChainStatus.previousBlockHash.toStringUtf8() - val nodes = pe.getNodeMgr.getStableNodes - sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, BlockEvent.CHAIN_INFO_SYNC, Event.Action.BLOCK_SYNC) - val res = AsyncGetNodeOfChainInfos(nodes, lh) - - val parser = new SynchResponseInfoAnalyzer(pe.getSysTag, pe.getSystemCurrentChainStatus, pe.getNodeMgr) - if (SystemProfile.getNumberOfEndorsement == 1) { - parser.Parser4One(res) - } else { - parser.Parser(res, isStartupSynch) - } - val result = parser.getResult - val rresult = parser.getRollbackAction - val sresult = parser.getSynchActiob - - if (result.ar == 1) { - if (SystemProfile.getNumberOfEndorsement == 1) { - pe.setStartVoteInfo(parser.getMaxBlockInfo) - } - if (rresult != null) { - val da = ImpDataAccess.GetDataAccess(pe.getSysTag) - if (da.rollbackToheight(rresult.destHeight)) { - if (sresult != null) { - getBlockDatas(sresult.start, sresult.end, sresult.server) - } else { - pe.resetSystemCurrentChainStatus(da.getBlockChainInfo()) - } - } else { - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"回滚块失败,failed height=${rresult.destHeight}")) - } - } else { - if (sresult != null) { - getBlockDatas(sresult.start, sresult.end, sresult.server) - } - } - } else if (result.ar == 2) { - rb = false - } else { - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(result.error)) - } - rb - } - - private def initSystemChainInfo = { - if (pe.getCurrentHeight == 0) { - val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag) - pe.resetSystemCurrentChainStatus(dataaccess.getBlockChainInfo()) - } - } - - override def receive: Receive = { - case StartSync(isNoticeModuleMgr: Boolean) => - schedulerLink = clearSched() - /*if (pe.getSysTag == "121000005l35120456.node1") { - println("node1") - }*/ - var rb = true - initSystemChainInfo - if (pe.getNodeMgr.getStableNodes.size >= SystemProfile.getVoteNoteMin && !pe.isSynching) { - pe.setSynching(true) - try { - if(SystemProfile.getNumberOfEndorsement == 1){ - val ssize = pe.getNodeMgr.getStableNodes.size - if(SystemProfile.getVoteNodeList.size() == ssize){ - rb = Handler(isNoticeModuleMgr) - } - }else{ - rb = Handler(isNoticeModuleMgr) - } - } catch { - case e: Exception => - rb = false - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"request synch excep,msg=${e.getMessage}")) - } - pe.setSynching(false) - if (rb) { - if (isNoticeModuleMgr) - pe.getActorRef(ModuleActorType.ActorType.modulemanager) ! IModuleManager.startup_Consensus - } else { - schedulerLink = scheduler.scheduleOnce(1.second, self, StartSync(isNoticeModuleMgr)) - } - - } else { - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"too few node,min=${SystemProfile.getVoteNoteMin} or synching from actorAddr" + "~" + NodeHelp.getNodePath(sender()))) - } - - case SyncRequestOfStorager(responser, maxHeight) => - //val selection: ActorSelection = context.actorSelection(responser+"/user/modulemanager/synchresponser"); - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"entry blockdata synch,maxheight=${maxHeight},responser=${responser}")) - if (!pe.isSynching) { - pe.setSynching(true) - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"start blockdata synch,currentheight=${pe.getCurrentHeight},maxheight=${maxHeight}")) - //if(pe.getSysTag == "921000006e0012v696.node5"){ - // println("921000006e0012v696.node5") - // } - try { - getBlockDatas(pe.getCurrentHeight, maxHeight, responser) - } catch { - case e: Exception => - pe.setSynching(false) - } - RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"stop blockdata synch,maxheight=${maxHeight}")) - pe.setSynching(false) - //pe.getActorRef(ActorType.modulemanager) ! ModuleManager.startup_Consensus - } - } -} diff --git a/src/main/scala/rep/network/sync/SynchResponseInfoAnalyzer.scala b/src/main/scala/rep/network/sync/parser/ISynchAnalyzer.scala similarity index 52% rename from src/main/scala/rep/network/sync/SynchResponseInfoAnalyzer.scala rename to src/main/scala/rep/network/sync/parser/ISynchAnalyzer.scala index 90d2603a..11b90e43 100644 --- a/src/main/scala/rep/network/sync/SynchResponseInfoAnalyzer.scala +++ b/src/main/scala/rep/network/sync/parser/ISynchAnalyzer.scala @@ -1,35 +1,25 @@ -/* - * Copyright 2019 Blockchain Technology and Application Joint Lab, Linkel Technology Co., Ltd, Beijing, Fintech Research Center of ISCAS. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BA SIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * +package rep.network.sync.parser + +import akka.actor.ActorRef +import rep.log.RepLogger +import rep.network.sync.SyncMsg._ +import rep.network.tools.NodeMgr +import rep.network.util.NodeHelp +import rep.protos.peer.BlockchainInfo +import rep.storage.ImpDataAccess + +import scala.util.control.Breaks.{break, breakable} + +/** + * Created by jiangbuyun on 2020/03/18. + * 同步区块信息分析的抽象类 */ -package rep.network.sync - -import rep.network.sync.SyncMsg.{ ResponseInfo, AnalysisResult, SynchAction, RollbackAction, MaxBlockInfo } -import rep.network.util.NodeHelp -import rep.protos.peer.{ BlockchainInfo, Block } -import rep.log.RepLogger -import akka.actor.{ Address, ActorRef } -import rep.storage.ImpDataAccess -import scala.util.control.Breaks._ -import rep.network.tools.NodeMgr - -class SynchResponseInfoAnalyzer(val systemName: String, val lchaininfo: BlockchainInfo, val nodemgr: NodeMgr) { - private var aresult: AnalysisResult = null - private var saction: SynchAction = null - private var raction: RollbackAction = null - private var maxinfo: MaxBlockInfo = null +abstract class ISynchAnalyzer(val systemName: String, val lchaininfo: BlockchainInfo, val nodemgr: NodeMgr) { + protected var aresult: AnalysisResult = null + protected var saction: SynchAction = null + protected var raction: RollbackAction = null + protected var maxinfo: MaxBlockInfo = null def getResult: AnalysisResult = { this.aresult @@ -47,7 +37,7 @@ class SynchResponseInfoAnalyzer(val systemName: String, val lchaininfo: Blockcha this.maxinfo } - private def checkHashAgreement(h: Long, ls: List[ResponseInfo], ns: Int, checkType: Int): (Boolean, String) = { + protected def checkHashAgreement(h: Long, ls: List[ResponseInfo], ns: Int, checkType: Int): (Boolean, String) = { val hls = ls.filter(_.response.height == h) var gls: List[(String, Int)] = null checkType match { @@ -67,11 +57,11 @@ class SynchResponseInfoAnalyzer(val systemName: String, val lchaininfo: Blockcha } } - private def getLogMsgPrefix(msg: String): String = { + protected def getLogMsgPrefix(msg: String): String = { s"${systemName}~synchronized requester~${msg}~" } - private def greaterThanLocalHeight(reslist: List[ResponseInfo], maxheight: Long, AgreementHash: String) = { + protected def greaterThanLocalHeight(reslist: List[ResponseInfo], maxheight: Long, AgreementHash: String) = { val lh = this.lchaininfo.height val nodes = this.nodemgr.getStableNodes val lhash = this.lchaininfo.currentBlockHash.toStringUtf8() @@ -127,7 +117,7 @@ class SynchResponseInfoAnalyzer(val systemName: String, val lchaininfo: Blockcha } } - private def FindSeedNode(reslist: List[ResponseInfo]): ActorRef = { + protected def FindSeedNode(reslist: List[ResponseInfo]): ActorRef = { var r: ActorRef = null val resinfo = reslist.filter(_.response.height == 1) if (resinfo.nonEmpty) { @@ -143,7 +133,7 @@ class SynchResponseInfoAnalyzer(val systemName: String, val lchaininfo: Blockcha r } - private def equalLocalHeight(reslist: List[ResponseInfo], maxheight: Long, AgreementHash: String) = { + protected def equalLocalHeight(reslist: List[ResponseInfo], maxheight: Long, AgreementHash: String) = { val lh = this.lchaininfo.height val nodes = this.nodemgr.getStableNodes val lhash = this.lchaininfo.currentBlockHash.toStringUtf8() @@ -187,7 +177,7 @@ class SynchResponseInfoAnalyzer(val systemName: String, val lchaininfo: Blockcha } } - private def lessThanLocalHeight(maxheight: Long, AgreementHash: String) = { + protected def lessThanLocalHeight(maxheight: Long, AgreementHash: String) = { val lh = this.lchaininfo.height //待同步高度小于本地高度 @@ -221,117 +211,7 @@ class SynchResponseInfoAnalyzer(val systemName: String, val lchaininfo: Blockcha } } - def Parser(reslist: List[ResponseInfo], isStartupSynch: Boolean) = { - val lh = lchaininfo.height - val nodes = nodemgr.getStableNodes - if (NodeHelp.ConsensusConditionChecked(reslist.length, nodes.size)) { - //获取到到chaininfo信息的数量,得到大多数节点的响应,进一步判断同步的策略 - //获取返回的chaininfo信息中,大多数节点的相同高度的最大值 - val heightStatis = reslist.groupBy(x => x.response.height).map(x => (x._1, x._2.length)).toList.sortBy(x => -x._2) - val maxheight = heightStatis.head._1 - var nodesOfmaxHeight = heightStatis.head._2 + def Parser(reslist: List[ResponseInfo], isStartupSynch: Boolean) - RepLogger.debug(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------Info,获取同步的返回信息,结果=${reslist.mkString("|")}")) - - RepLogger.info(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------Info,获取同步的返回信息,统计结果=${heightStatis.mkString("|")}")) - - if (NodeHelp.ConsensusConditionChecked(nodesOfmaxHeight, nodes.size)) { - //得到了真正大多数节点相同的高度 - val agreementResult = checkHashAgreement(maxheight, reslist, nodes.size, 1) - if (agreementResult._1) { - //当前同步高度的最后高度的块hash一致 - if (maxheight > lh) { - this.greaterThanLocalHeight(reslist, maxheight, agreementResult._2) - } else if (maxheight == lh) { - this.equalLocalHeight(reslist, maxheight, agreementResult._2) - } else { - if (isStartupSynch) { - this.lessThanLocalHeight(maxheight, agreementResult._2) - } else { - this.aresult = AnalysisResult(1, "") - } - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------info,本地高度大于远端高度,停止同步")) - } - } else { - //当前同步高度的最后高度的块hash不一致,输出错误信息,停止同步 - this.aresult = AnalysisResult(0, "当前同步高度的最后高度的块hash不一致,输出错误信息,停止同步") - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------error,当前同步高度的最后高度的块hash不一致,输出错误信息,停止同步")) - } - } else { - //最多数量的高度,达不到共识的要求,输出错误信息停止同步 - this.aresult = AnalysisResult(2, s"最多数量的高度,达不到共识的要求,输出错误信息停止同步 response size=${reslist.size}") - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,最多数量的高度,达不到共识的要求,输出错误信息停止同步 response size=${reslist.size}")) - } - } else { - //获取到到chaininfo信息的数量,没有得到大多数节点的响应,输出错误信息停止同步 - this.aresult = AnalysisResult(0, s"获取到到chaininfo信息的数量,没有得到大多数节点的响应,输出错误信息停止同步 response size=${reslist.size}") - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,获取到到chaininfo信息的数量,没有得到大多数节点的响应,输出错误信息停止同步 response size=${reslist.size}")) - } - } - - def Parser4One(reslist: List[ResponseInfo]) = { - val lh = lchaininfo.height - val lhash = this.lchaininfo.currentBlockHash.toStringUtf8() - val lprehash = this.lchaininfo.previousBlockHash.toStringUtf8() - val nodes = nodemgr.getStableNodes - - /*if (this.systemName == "121000005l35120456.node1") { - println("node1") - }*/ - - //获取到到chaininfo信息的数量,得到大多数节点的响应,进一步判断同步的策略 - //获取返回的chaininfo信息中,大多数节点的相同高度的最大值 - val heightStatis = reslist.groupBy(x => x.response.height).map(x => (x._1, x._2.length)).toList.sortBy(x => -x._1) - val maxheight = heightStatis.head._1 - val maxresponseinfo = reslist.filter(_.response.height == maxheight).head - - RepLogger.debug(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------Info,获取同步的返回信息,结果=${reslist.mkString("|")}")) - RepLogger.info(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------Info,获取同步的返回信息,统计结果=${heightStatis.mkString("|")}")) - - if (maxheight > lh) { - if (lhash == maxresponseinfo.ChainInfoOfSpecifiedHeight.currentBlockHash.toStringUtf8()) { - //本地最后块的hash与远端的前序块hash一致,可以直接进入同步 - this.aresult = AnalysisResult(1, "") - this.maxinfo = MaxBlockInfo(maxresponseinfo.response.height, maxresponseinfo.response.currentBlockHash.toStringUtf8()) - this.saction = SynchAction(lh, maxheight, maxresponseinfo.responser) - } else { - //由于与远端的前序块的hash不一致,需要进一步进入回滚当前块的判断 - if (lprehash == maxresponseinfo.ChainInfoOfSpecifiedHeight.previousBlockHash.toStringUtf8()) { - //本地块的前一块的hash与远端前导块的前一块的hash一致,可以调用块回滚到前一个块,直接调用存储持久化代码,进行块回滚,回滚之后载同步 - this.aresult = AnalysisResult(1, "") - this.raction = RollbackAction(lh - 1) - this.maxinfo = MaxBlockInfo(maxresponseinfo.response.height, maxresponseinfo.response.currentBlockHash.toStringUtf8()) - this.saction = SynchAction(lh - 1, maxheight, maxresponseinfo.responser) - } else { - //本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步 - this.aresult = AnalysisResult(0, s"大于本地高度,本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步,local height=${lh},maxheight=${maxheight}") - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,大于本地高度,本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步,local height=${lh},maxheight=${maxheight}")) - } - } - } else if (maxheight == lh) { - if (lhash == maxresponseinfo.response.currentBlockHash.toStringUtf8()) { - this.aresult = AnalysisResult(1, "") - this.maxinfo = MaxBlockInfo(maxresponseinfo.response.height, maxresponseinfo.response.currentBlockHash.toStringUtf8()) - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,等于本地高度,最后的hash一致,停止同步,local height=${lh},maxheight=${maxheight}")) - } else { - //由于与远端的前序块的hash不一致,需要进一步进入回滚当前块的判断 - if (lprehash == maxresponseinfo.ChainInfoOfSpecifiedHeight.previousBlockHash.toStringUtf8()) { - //本地块的前一块的hash与远端前导块的前一块的hash一致,可以调用块回滚到前一个块,直接调用存储持久化代码,进行块回滚,回滚之后载同步 - this.aresult = AnalysisResult(1, "") - this.raction = RollbackAction(lh - 1) - this.maxinfo = MaxBlockInfo(maxresponseinfo.response.height, maxresponseinfo.response.currentBlockHash.toStringUtf8()) - this.saction = SynchAction(lh - 1, maxheight, maxresponseinfo.responser) - } else { - //本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步 - this.aresult = AnalysisResult(0, s"等于本地高度,本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步,local height=${lh},maxheight=${maxheight}") - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,大于本地高度,本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步,local height=${lh},maxheight=${maxheight}")) - } - } - } else { - this.aresult = AnalysisResult(0, "小于本地高度,不需要同步") - RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------error,小于本地高度,不需要同步,停止同步")) - } - } - -} \ No newline at end of file +} diff --git a/src/main/scala/rep/network/sync/parser/cfrd/ICFRDOfSynchAnalyzer.scala b/src/main/scala/rep/network/sync/parser/cfrd/ICFRDOfSynchAnalyzer.scala new file mode 100644 index 00000000..7c217e98 --- /dev/null +++ b/src/main/scala/rep/network/sync/parser/cfrd/ICFRDOfSynchAnalyzer.scala @@ -0,0 +1,67 @@ +package rep.network.sync.parser.cfrd + +import rep.log.RepLogger +import rep.network.sync.SyncMsg.AnalysisResult +import rep.network.sync.SyncMsg +import rep.network.sync.parser.ISynchAnalyzer +import rep.network.tools.NodeMgr +import rep.network.util.NodeHelp +import rep.protos.peer.BlockchainInfo + +/** + * Created by jiangbuyun on 2020/03/18. + * 基于CFRD共识协议的同步区块信息分析的实现类 + */ + +class ICFRDOfSynchAnalyzer(systemName: String, lchaininfo: BlockchainInfo, nodemgr: NodeMgr) extends ISynchAnalyzer( systemName, lchaininfo, nodemgr) { + + override def Parser(reslist: List[SyncMsg.ResponseInfo], isStartupSynch: Boolean): Unit = { + val lh = lchaininfo.height + val nodes = nodemgr.getStableNodes + + if (NodeHelp.ConsensusConditionChecked(reslist.length, nodes.size)) { + //获取到到chaininfo信息的数量,得到大多数节点的响应,进一步判断同步的策略 + //获取返回的chaininfo信息中,大多数节点的相同高度的最大值 + val heightStatis = reslist.groupBy(x => x.response.height).map(x => (x._1, x._2.length)).toList.sortBy(x => -x._2) + val maxheight = heightStatis.head._1 + var nodesOfmaxHeight = heightStatis.head._2 + + RepLogger.debug(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------Info,获取同步的返回信息,结果=${reslist.mkString("|")}")) + + RepLogger.info(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------Info,获取同步的返回信息,统计结果=${heightStatis.mkString("|")}")) + + if (NodeHelp.ConsensusConditionChecked(nodesOfmaxHeight, nodes.size)) { + //得到了真正大多数节点相同的高度 + val agreementResult = checkHashAgreement(maxheight, reslist, nodes.size, 1) + if (agreementResult._1) { + //当前同步高度的最后高度的块hash一致 + if (maxheight > lh) { + this.greaterThanLocalHeight(reslist, maxheight, agreementResult._2) + } else if (maxheight == lh) { + this.equalLocalHeight(reslist, maxheight, agreementResult._2) + } else { + if (isStartupSynch) { + this.lessThanLocalHeight(maxheight, agreementResult._2) + } else { + this.aresult = AnalysisResult(1, "") + } + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------info,本地高度大于远端高度,停止同步")) + } + } else { + //当前同步高度的最后高度的块hash不一致,输出错误信息,停止同步 + this.aresult = AnalysisResult(0, "当前同步高度的最后高度的块hash不一致,输出错误信息,停止同步") + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------error,当前同步高度的最后高度的块hash不一致,输出错误信息,停止同步")) + } + } else { + //最多数量的高度,达不到共识的要求,输出错误信息停止同步 + this.aresult = AnalysisResult(2, s"最多数量的高度,达不到共识的要求,输出错误信息停止同步 response size=${reslist.size}") + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,最多数量的高度,达不到共识的要求,输出错误信息停止同步 response size=${reslist.size}")) + } + } else { + //获取到到chaininfo信息的数量,没有得到大多数节点的响应,输出错误信息停止同步 + this.aresult = AnalysisResult(0, s"获取到到chaininfo信息的数量,没有得到大多数节点的响应,输出错误信息停止同步 response size=${reslist.size}") + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,获取到到chaininfo信息的数量,没有得到大多数节点的响应,输出错误信息停止同步 response size=${reslist.size}")) + } + } + +} diff --git a/src/main/scala/rep/network/sync/parser/raft/IRAFTSynchAnalyzer.scala b/src/main/scala/rep/network/sync/parser/raft/IRAFTSynchAnalyzer.scala new file mode 100644 index 00000000..ca81dbed --- /dev/null +++ b/src/main/scala/rep/network/sync/parser/raft/IRAFTSynchAnalyzer.scala @@ -0,0 +1,75 @@ +package rep.network.sync.parser.raft + +import rep.log.RepLogger +import rep.network.sync.SyncMsg.{AnalysisResult, MaxBlockInfo, RollbackAction, SynchAction} +import rep.network.sync.SyncMsg +import rep.network.sync.parser.ISynchAnalyzer +import rep.network.tools.NodeMgr +import rep.protos.peer.BlockchainInfo + +/** + * Created by jiangbuyun on 2020/03/18. + * 基于RAFT共识协议的同步区块信息分析的实现类 + */ + +class IRAFTSynchAnalyzer(systemName: String, lchaininfo: BlockchainInfo, nodemgr: NodeMgr) extends ISynchAnalyzer( systemName, lchaininfo, nodemgr) { + override def Parser(reslist: List[SyncMsg.ResponseInfo], isStartupSynch: Boolean): Unit = { + val lh = lchaininfo.height + val lhash = this.lchaininfo.currentBlockHash.toStringUtf8() + val lprehash = this.lchaininfo.previousBlockHash.toStringUtf8() + val nodes = nodemgr.getStableNodes + + //获取到到chaininfo信息的数量,得到大多数节点的响应,进一步判断同步的策略 + //获取返回的chaininfo信息中,大多数节点的相同高度的最大值 + val heightStatis = reslist.groupBy(x => x.response.height).map(x => (x._1, x._2.length)).toList.sortBy(x => -x._1) + val maxheight = heightStatis.head._1 + val maxresponseinfo = reslist.filter(_.response.height == maxheight).head + + RepLogger.debug(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------Info,获取同步的返回信息,结果=${reslist.mkString("|")}")) + RepLogger.info(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------Info,获取同步的返回信息,统计结果=${heightStatis.mkString("|")}")) + + if (maxheight > lh) { + if (lhash == maxresponseinfo.ChainInfoOfSpecifiedHeight.currentBlockHash.toStringUtf8()) { + //本地最后块的hash与远端的前序块hash一致,可以直接进入同步 + this.aresult = AnalysisResult(1, "") + this.maxinfo = MaxBlockInfo(maxresponseinfo.response.height, maxresponseinfo.response.currentBlockHash.toStringUtf8()) + this.saction = SynchAction(lh, maxheight, maxresponseinfo.responser) + } else { + //由于与远端的前序块的hash不一致,需要进一步进入回滚当前块的判断 + if (lprehash == maxresponseinfo.ChainInfoOfSpecifiedHeight.previousBlockHash.toStringUtf8()) { + //本地块的前一块的hash与远端前导块的前一块的hash一致,可以调用块回滚到前一个块,直接调用存储持久化代码,进行块回滚,回滚之后载同步 + this.aresult = AnalysisResult(1, "") + this.raction = RollbackAction(lh - 1) + this.maxinfo = MaxBlockInfo(maxresponseinfo.response.height, maxresponseinfo.response.currentBlockHash.toStringUtf8()) + this.saction = SynchAction(lh - 1, maxheight, maxresponseinfo.responser) + } else { + //本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步 + this.aresult = AnalysisResult(0, s"大于本地高度,本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步,local height=${lh},maxheight=${maxheight}") + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,大于本地高度,本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步,local height=${lh},maxheight=${maxheight}")) + } + } + } else if (maxheight == lh) { + if (lhash == maxresponseinfo.response.currentBlockHash.toStringUtf8()) { + this.aresult = AnalysisResult(1, "") + this.maxinfo = MaxBlockInfo(maxresponseinfo.response.height, maxresponseinfo.response.currentBlockHash.toStringUtf8()) + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,等于本地高度,最后的hash一致,停止同步,local height=${lh},maxheight=${maxheight}")) + } else { + //由于与远端的前序块的hash不一致,需要进一步进入回滚当前块的判断 + if (lprehash == maxresponseinfo.ChainInfoOfSpecifiedHeight.previousBlockHash.toStringUtf8()) { + //本地块的前一块的hash与远端前导块的前一块的hash一致,可以调用块回滚到前一个块,直接调用存储持久化代码,进行块回滚,回滚之后载同步 + this.aresult = AnalysisResult(1, "") + this.raction = RollbackAction(lh - 1) + this.maxinfo = MaxBlockInfo(maxresponseinfo.response.height, maxresponseinfo.response.currentBlockHash.toStringUtf8()) + this.saction = SynchAction(lh - 1, maxheight, maxresponseinfo.responser) + } else { + //本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步 + this.aresult = AnalysisResult(0, s"等于本地高度,本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步,local height=${lh},maxheight=${maxheight}") + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"--------error,大于本地高度,本地块的前一块的hash与远端前导块的前一块的hash不一致,输出错误,停止同步,local height=${lh},maxheight=${maxheight}")) + } + } + } else { + this.aresult = AnalysisResult(0, "小于本地高度,不需要同步") + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------error,小于本地高度,不需要同步,停止同步")) + } + } +} diff --git a/src/main/scala/rep/network/sync/request/ISynchRequester.scala b/src/main/scala/rep/network/sync/request/ISynchRequester.scala new file mode 100644 index 00000000..3ad382b4 --- /dev/null +++ b/src/main/scala/rep/network/sync/request/ISynchRequester.scala @@ -0,0 +1,194 @@ +package rep.network.sync.request + +import akka.actor.{ActorRef, ActorSelection, Address, Props} +import akka.pattern.{AskTimeoutException, ask} +import akka.util.Timeout +import rep.app.conf.{SystemProfile, TimePolicy} +import rep.log.RepLogger +import rep.network.base.ModuleBase +import rep.network.module.ModuleActorType +import rep.network.persistence.IStorager.SourceOfBlock +import rep.network.sync.SyncMsg.{BlockDataOfRequest, BlockDataOfResponse, ChainInfoOfRequest, MaxBlockInfo, ResponseInfo} +import rep.network.util.NodeHelp +import rep.protos.peer.Event +import rep.utils.GlobalUtils.{BlockEvent, EventType} +import rep.network.consensus.common.MsgOfConsensus.BlockRestore + +import scala.collection.{Seq, Set} +import scala.concurrent.{Await, Future, TimeoutException} +import rep.network.sync.parser.ISynchAnalyzer +import rep.storage.ImpDataAccess + +/** + * Created by jiangbuyun on 2020/03/18. + * 基于同步请求actor的抽象类 + */ + +object ISynchRequester{ + def props(name: String): Props = Props(classOf[ISynchRequester], name) +} + +abstract class ISynchRequester(moduleName: String) extends ModuleBase(moduleName) { + import context.dispatcher + import scala.concurrent.duration._ + + implicit val timeout = Timeout(TimePolicy.getTimeoutSync.seconds) + protected val responseActorName = "/user/modulemanager/synchresponser" + + + protected def toAkkaUrl(addr: String, actorName: String): String = { + return addr + "/" + actorName; + } + + protected def AsyncGetNodeOfChainInfo(addr: Address, lh: Long): Future[ResponseInfo] = Future { + var result: ResponseInfo = null + + try { + val selection: ActorSelection = context.actorSelection(toAkkaUrl(addr.toString, responseActorName)); + val future1 = selection ? ChainInfoOfRequest(lh) + result = Await.result(future1, timeout.duration).asInstanceOf[ResponseInfo] + } catch { + case e: AskTimeoutException => + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------AsyncGetNodeOfChainInfo timeout")) + null + case te: TimeoutException => + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------AsyncGetNodeOfChainInfo java timeout")) + null + } + + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"entry AsyncGetNodeOfChainInfo after,chaininfo=${result}")) + result + } + + protected def AsyncGetNodeOfChainInfos(stablenodes: Set[Address], lh: Long): List[ResponseInfo] = { + val listOfFuture: Seq[Future[ResponseInfo]] = stablenodes.toSeq.map(addr => { + AsyncGetNodeOfChainInfo(addr, lh) + }) + + val futureOfList: Future[List[ResponseInfo]] = Future.sequence(listOfFuture.toList).recover({ + case e: Exception => + null + }) + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AsyncGetNodeOfChainInfos 1")) + try { + val result1 = Await.result(futureOfList, timeout.duration).asInstanceOf[List[ResponseInfo]] + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AsyncGetNodeOfChainInfos 2")) + if (result1 == null) { + List.empty + } else { + result1 + } + } catch { + case te: TimeoutException => + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------AsyncGetNodeOfChainInfo java timeout")) + null + } + } + + protected def getBlockData(height: Long, ref: ActorRef): Boolean = { + try { + sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, pe.getNodeMgr.getNodeName4AddrString(NodeHelp.getNodeAddress(ref)), Event.Action.BLOCK_SYNC_DATA) + val selection: ActorSelection = context.actorSelection(toAkkaUrl(NodeHelp.getNodeAddress(ref), responseActorName)); + val future1 = selection ? BlockDataOfRequest(height) + //logMsg(LogType.INFO, "--------AsyncGetNodeOfChainInfo success") + var result = Await.result(future1, timeout.duration).asInstanceOf[BlockDataOfResponse] + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"height=${height}--------getBlockData success")) + pe.getActorRef(ModuleActorType.ActorType.storager) ! BlockRestore(result.data, SourceOfBlock.SYNC_BLOCK, ref) + true + } catch { + case e: AskTimeoutException => + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------getBlockData timeout")) + false + case te: TimeoutException => + RepLogger.error(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix("--------getBlockData java timeout")) + false + } + } + + protected def getBlockDatas(lh: Long, rh: Long, actorref: ActorRef) = { + if (rh > lh) { + var height = lh + 1 + while (height <= rh) { + if (!pe.getBlockCacheMgr.exist(height) && !getBlockData(height, actorref)) { + getBlockData(height, actorref) + } + height += 1 + } + } + } + + protected def checkHashAgreement(h: Long, ls: List[ResponseInfo], ns: Int, checkType: Int): (Boolean, String) = { + val hls = ls.filter(_.response.height == h) + var gls: List[(String, Int)] = null + checkType match { + case 1 => + //检查远端的最后一个块的hash的一致性 + gls = hls.groupBy(x => x.response.currentBlockHash.toStringUtf8()).map(x => (x._1, x._2.length)).toList.sortBy(x => -x._2) + case 2 => + //检查远端指定高度块的一致性 + gls = hls.groupBy(x => x.ChainInfoOfSpecifiedHeight.currentBlockHash.toStringUtf8()).map(x => (x._1, x._2.length)).toList.sortBy(x => -x._2) + } + val tmpgHash = gls.head._1 + val tmpgCount = gls.head._2 + if (NodeHelp.ConsensusConditionChecked(tmpgCount, ns)) { + (true, tmpgHash) + } else { + (false, "") + } + } + + protected def getAnalyzerInSynch : ISynchAnalyzer + protected def setStartVoteInfo(maxblockinfo:MaxBlockInfo):Unit + + protected def Handler(isStartupSynch: Boolean): Boolean = { + var rb = true + val lh = pe.getCurrentHeight + val lhash = pe.getCurrentBlockHash + val lprehash = pe.getSystemCurrentChainStatus.previousBlockHash.toStringUtf8() + val nodes = pe.getNodeMgr.getStableNodes + sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, BlockEvent.CHAIN_INFO_SYNC, Event.Action.BLOCK_SYNC) + val res = AsyncGetNodeOfChainInfos(nodes, lh) + + var analyzerInSynch = getAnalyzerInSynch + analyzerInSynch.Parser(res,isStartupSynch) + + val result = analyzerInSynch.getResult + val rresult = analyzerInSynch.getRollbackAction + val sresult = analyzerInSynch.getSynchActiob + + if (result.ar == 1) { + + setStartVoteInfo(analyzerInSynch.getMaxBlockInfo) + + if (rresult != null) { + val da = ImpDataAccess.GetDataAccess(pe.getSysTag) + if (da.rollbackToheight(rresult.destHeight)) { + if (sresult != null) { + getBlockDatas(sresult.start, sresult.end, sresult.server) + } else { + pe.resetSystemCurrentChainStatus(da.getBlockChainInfo()) + } + } else { + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"回滚块失败,failed height=${rresult.destHeight}")) + } + } else { + if (sresult != null) { + getBlockDatas(sresult.start, sresult.end, sresult.server) + } + } + } else if (result.ar == 2) { + rb = false + } else { + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(result.error)) + } + rb + } + + protected def initSystemChainInfo = { + if (pe.getCurrentHeight == 0) { + val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag) + pe.resetSystemCurrentChainStatus(dataaccess.getBlockChainInfo()) + } + } + +} diff --git a/src/main/scala/rep/network/sync/request/cfrd/SynchRequesterOfCFRD.scala b/src/main/scala/rep/network/sync/request/cfrd/SynchRequesterOfCFRD.scala new file mode 100644 index 00000000..0a27b3d6 --- /dev/null +++ b/src/main/scala/rep/network/sync/request/cfrd/SynchRequesterOfCFRD.scala @@ -0,0 +1,75 @@ +package rep.network.sync.request.cfrd + + +import akka.actor.Props +import rep.app.conf.SystemProfile +import rep.log.RepLogger +import rep.network.module.{IModuleManager, ModuleActorType} +import rep.network.sync.SyncMsg.{MaxBlockInfo, StartSync, SyncRequestOfStorager} +import rep.network.sync.parser.ISynchAnalyzer +import rep.network.sync.request.ISynchRequester +import rep.network.sync.parser.cfrd.ICFRDOfSynchAnalyzer +import rep.network.util.NodeHelp + +import scala.concurrent.duration._ + +/** + * Created by jiangbuyun on 2020/03/18. + * 基于CFRD共识协议的同步actor的实现类 + */ + +object SynchRequesterOfCFRD{ + def props(name: String): Props = Props(classOf[SynchRequesterOfCFRD], name) +} + +class SynchRequesterOfCFRD(moduleName: String) extends ISynchRequester(moduleName: String) { + import context.dispatcher + + override protected def getAnalyzerInSynch: ISynchAnalyzer = { + new ICFRDOfSynchAnalyzer(pe.getSysTag, pe.getSystemCurrentChainStatus, pe.getNodeMgr) + } + + override def receive: Receive = { + case StartSync(isNoticeModuleMgr: Boolean) => + schedulerLink = clearSched() + var rb = true + initSystemChainInfo + if (pe.getNodeMgr.getStableNodes.size >= SystemProfile.getVoteNoteMin && !pe.isSynching) { + pe.setSynching(true) + try { + rb = Handler(isNoticeModuleMgr) + } catch { + case e: Exception => + rb = false + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"request synch excep,msg=${e.getMessage}")) + } + pe.setSynching(false) + if (rb) { + if (isNoticeModuleMgr) + pe.getActorRef(ModuleActorType.ActorType.modulemanager) ! IModuleManager.startup_Consensus + } else { + schedulerLink = scheduler.scheduleOnce(1.second, self, StartSync(isNoticeModuleMgr)) + } + + } else { + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"too few node,min=${SystemProfile.getVoteNoteMin} or synching from actorAddr" + "~" + NodeHelp.getNodePath(sender()))) + } + + case SyncRequestOfStorager(responser, maxHeight) => + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"entry blockdata synch,maxheight=${maxHeight},responser=${responser}")) + if (!pe.isSynching) { + pe.setSynching(true) + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"start blockdata synch,currentheight=${pe.getCurrentHeight},maxheight=${maxHeight}")) + try { + getBlockDatas(pe.getCurrentHeight, maxHeight, responser) + } catch { + case e: Exception => + pe.setSynching(false) + } + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"stop blockdata synch,maxheight=${maxHeight}")) + pe.setSynching(false) + } + } + + override protected def setStartVoteInfo(maxblockinfo:MaxBlockInfo): Unit = {} +} diff --git a/src/main/scala/rep/network/sync/request/raft/SynchRequesterOfRAFT.scala b/src/main/scala/rep/network/sync/request/raft/SynchRequesterOfRAFT.scala new file mode 100644 index 00000000..d56bb6c2 --- /dev/null +++ b/src/main/scala/rep/network/sync/request/raft/SynchRequesterOfRAFT.scala @@ -0,0 +1,79 @@ +package rep.network.sync.request.raft + +import akka.actor.Props +import rep.app.conf.SystemProfile +import rep.log.RepLogger +import rep.network.module.{IModuleManager, ModuleActorType} +import rep.network.sync.SyncMsg.{MaxBlockInfo, StartSync, SyncRequestOfStorager} +import rep.network.sync.parser.ISynchAnalyzer +import rep.network.sync.parser.raft.IRAFTSynchAnalyzer +import rep.network.sync.request.ISynchRequester +import rep.network.util.NodeHelp + +import scala.concurrent.duration._ + +/** + * Created by jiangbuyun on 2020/03/18. + * 基于RAFT共识协议的同步actor的实现类 + */ + +object SynchRequesterOfRAFT{ + def props(name: String): Props = Props(classOf[SynchRequesterOfRAFT], name) +} + +class SynchRequesterOfRAFT (moduleName: String) extends ISynchRequester(moduleName: String) { + import context.dispatcher + + override protected def getAnalyzerInSynch: ISynchAnalyzer = { + new IRAFTSynchAnalyzer(pe.getSysTag, pe.getSystemCurrentChainStatus, pe.getNodeMgr) + } + + override def receive: Receive = { + case StartSync(isNoticeModuleMgr: Boolean) => + schedulerLink = clearSched() + var rb = true + initSystemChainInfo + if (pe.getNodeMgr.getStableNodes.size >= SystemProfile.getVoteNoteMin && !pe.isSynching) { + pe.setSynching(true) + try { + val ssize = pe.getNodeMgr.getStableNodes.size + if(SystemProfile.getVoteNodeList.size() == ssize){ + rb = Handler(isNoticeModuleMgr) + } + } catch { + case e: Exception => + rb = false + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"request synch excep,msg=${e.getMessage}")) + } + pe.setSynching(false) + if (rb) { + if (isNoticeModuleMgr) + pe.getActorRef(ModuleActorType.ActorType.modulemanager) ! IModuleManager.startup_Consensus + } else { + schedulerLink = scheduler.scheduleOnce(1.second, self, StartSync(isNoticeModuleMgr)) + } + + } else { + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"too few node,min=${SystemProfile.getVoteNoteMin} or synching from actorAddr" + "~" + NodeHelp.getNodePath(sender()))) + } + + case SyncRequestOfStorager(responser, maxHeight) => + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"entry blockdata synch,maxheight=${maxHeight},responser=${responser}")) + if (!pe.isSynching) { + pe.setSynching(true) + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"start blockdata synch,currentheight=${pe.getCurrentHeight},maxheight=${maxHeight}")) + try { + getBlockDatas(pe.getCurrentHeight, maxHeight, responser) + } catch { + case e: Exception => + pe.setSynching(false) + } + RepLogger.trace(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix(s"stop blockdata synch,maxheight=${maxHeight}")) + pe.setSynching(false) + } + } + + override protected def setStartVoteInfo(maxblockinfo:MaxBlockInfo): Unit = { + pe.setStartVoteInfo(maxblockinfo) + } +} diff --git a/src/main/scala/rep/network/sync/SynchronizeResponser.scala b/src/main/scala/rep/network/sync/response/SynchronizeResponser.scala similarity index 88% rename from src/main/scala/rep/network/sync/SynchronizeResponser.scala rename to src/main/scala/rep/network/sync/response/SynchronizeResponser.scala index b19643e0..74a95a5b 100644 --- a/src/main/scala/rep/network/sync/SynchronizeResponser.scala +++ b/src/main/scala/rep/network/sync/response/SynchronizeResponser.scala @@ -14,17 +14,23 @@ * */ -package rep.network.sync +package rep.network.sync.response -import akka.actor.{ ActorRef, Props } -import akka.cluster.pubsub.DistributedPubSubMediator.Publish -import rep.network.base.ModuleBase -import rep.utils.GlobalUtils.{ BlockEvent, EventType } -import rep.storage.ImpDataAccess -import rep.protos.peer._ -import rep.network.util.NodeHelp -import rep.network.sync.SyncMsg.{ResponseInfo,BlockDataOfResponse,ChainInfoOfRequest,BlockDataOfRequest} +import akka.actor.Props import rep.log.RepLogger +import rep.network.base.ModuleBase +import rep.network.sync.SyncMsg +import rep.network.sync.SyncMsg.{BlockDataOfRequest, ChainInfoOfRequest, ResponseInfo} +import rep.network.util.NodeHelp +import rep.protos.peer._ +import rep.storage.ImpDataAccess +import rep.utils.GlobalUtils.{BlockEvent, EventType} + + +/** + * Created by jiangbuyun on 2020/03/19. + * 区块同步时,接收请求区块信息的actor + */ object SynchronizeResponser { def props(name: String): Props = Props(classOf[SynchronizeResponser], name) @@ -32,12 +38,7 @@ object SynchronizeResponser { class SynchronizeResponser(moduleName: String) extends ModuleBase(moduleName) { - import context.dispatcher - import scala.concurrent.duration._ - import scala.util.control.Breaks._ - override def preStart(): Unit = { - //SubscribeTopic(mediator, self, selfAddr, BlockEvent.CHAIN_INFO_SYNC, true) RepLogger.info(RepLogger.BlockSyncher_Logger, this.getLogMsgPrefix( "SynchronizeResponse start")) } diff --git a/src/main/scala/rep/network/tools/NodeMgr.scala b/src/main/scala/rep/network/tools/NodeMgr.scala index b194876e..2cce88ec 100644 --- a/src/main/scala/rep/network/tools/NodeMgr.scala +++ b/src/main/scala/rep/network/tools/NodeMgr.scala @@ -22,6 +22,12 @@ import java.util.concurrent.ConcurrentHashMap //import scala.jdk.CollectionConverters._ import scala.collection.JavaConverters._ +/** + * Created by jiangbuyun on 2018/03/19. + * 共识节点管理与存储类 + */ + + class NodeMgr { //private val nodesLock: Lock = new ReentrantLock(); //private val nodesStableLock: Lock = new ReentrantLock(); diff --git a/src/main/scala/rep/network/tools/transpool/TransactionPoolMgr.scala b/src/main/scala/rep/network/tools/transpool/TransactionPoolMgr.scala index e2ccbde6..32af2aa1 100644 --- a/src/main/scala/rep/network/tools/transpool/TransactionPoolMgr.scala +++ b/src/main/scala/rep/network/tools/transpool/TransactionPoolMgr.scala @@ -169,4 +169,8 @@ class TransactionPoolMgr { transactions.size //this.transNumber.get } + + def isEmpty:Boolean={ + transactions.isEmpty + } } \ No newline at end of file diff --git a/src/main/scala/rep/network/transaction/DispatchOfPreload.scala b/src/main/scala/rep/network/transaction/DispatchOfPreload.scala index a2d48c72..ed8e6c3b 100644 --- a/src/main/scala/rep/network/transaction/DispatchOfPreload.scala +++ b/src/main/scala/rep/network/transaction/DispatchOfPreload.scala @@ -21,7 +21,12 @@ import akka.routing._ import rep.app.conf.SystemProfile import rep.log.RepLogger import rep.network.base.ModuleBase -import rep.network.consensus.cfrd.block.Blocker.PreTransBlock +import rep.network.consensus.common.MsgOfConsensus.PreTransBlock + +/** + * Created by jiangbuyun on 2018/03/19. + * 分派预执行actor + */ object DispatchOfPreload { diff --git a/src/main/scala/rep/network/transaction/PreloaderForTransaction.scala b/src/main/scala/rep/network/transaction/PreloaderForTransaction.scala index 26ee0afc..74cae030 100644 --- a/src/main/scala/rep/network/transaction/PreloaderForTransaction.scala +++ b/src/main/scala/rep/network/transaction/PreloaderForTransaction.scala @@ -24,7 +24,7 @@ import rep.app.conf.TimePolicy import rep.crypto.Sha256 import rep.log.RepLogger import rep.network.base.ModuleBase -import rep.network.consensus.cfrd.block.Blocker.{PreTransBlock, PreTransBlockResult} +import rep.network.consensus.common.MsgOfConsensus.{PreTransBlock, PreTransBlockResult} import rep.protos.peer._ import rep.sc.Sandbox.DoTransactionResult import rep.sc.SandboxDispatcher.DoTransaction @@ -32,10 +32,15 @@ import rep.sc.TypeOfSender import rep.storage.ImpDataPreloadMgr import rep.network.module.ModuleActorType import rep.utils._ - import scala.collection.mutable import scala.concurrent._ +/** + * Created by jiangbuyun on 2018/03/19. + * 执行预执行actor + */ + + object PreloaderForTransaction { def props(name: String): Props = Props(classOf[PreloaderForTransaction], name) } diff --git a/src/main/scala/rep/sc/TransactionDispatcher.scala b/src/main/scala/rep/sc/TransactionDispatcher.scala index cbf71afb..ae3853fc 100644 --- a/src/main/scala/rep/sc/TransactionDispatcher.scala +++ b/src/main/scala/rep/sc/TransactionDispatcher.scala @@ -1,40 +1,16 @@ package rep.sc -import akka.util.Timeout -import scala.concurrent.duration._ -import akka.pattern.ask -import akka.pattern.AskTimeoutException - -import scala.concurrent._ -import akka.actor.{Actor, ActorRef, Props} -import com.google.protobuf.ByteString -import com.google.protobuf.timestamp.Timestamp -import rep.app.conf.{SystemProfile, TimePolicy} +import akka.actor.{ ActorRef, Props} import rep.network.base.ModuleBase -import rep.network.consensus.cfrd.block.Blocker.{PreTransBlock, PreTransBlockResult} -import rep.network.tools.PeerExtension -import rep.protos.peer._ -import rep.sc.Sandbox.DoTransactionResult import rep.sc.SandboxDispatcher.DoTransaction -import rep.storage.ImpDataPreloadMgr - -import rep.utils._ - -import scala.collection.mutable -import akka.pattern.AskTimeoutException -import rep.crypto.Sha256 import rep.log.RepLogger -import akka.routing._ -import rep.network.autotransaction.Topic; object TransactionDispatcher { def props(name: String): Props = Props(classOf[TransactionDispatcher], name) } class TransactionDispatcher(moduleName: String) extends ModuleBase(moduleName) { - import context.dispatcher - import scala.concurrent.duration._ import scala.collection.immutable._ import rep.utils.IdTool diff --git a/src/test/scala/rep/sc/BlockStubActor.scala b/src/test/scala/rep/sc/BlockStubActor.scala index 8854f16b..2fbc6bff 100644 --- a/src/test/scala/rep/sc/BlockStubActor.scala +++ b/src/test/scala/rep/sc/BlockStubActor.scala @@ -12,9 +12,10 @@ import com.google.protobuf.ByteString import com.google.protobuf.timestamp.Timestamp import rep.app.conf.{SystemProfile, TimePolicy} import rep.network.base.ModuleBase -import rep.network.consensus.cfrd.block.Blocker.{PreTransBlock, PreTransBlockResult} +import rep.network.consensus.common.MsgOfConsensus.{PreTransBlock, PreTransBlockResult} import rep.network.tools.PeerExtension import rep.protos.peer._ +import rep.network.consensus.common.MsgOfConsensus.BlockRestore import rep.sc.SandboxDispatcher.DoTransaction import rep.sc.Sandbox.DoTransactionResult import rep.storage.ImpDataPreloadMgr @@ -44,9 +45,9 @@ class BlockStubActor(moduleName: String) extends ModuleBase(moduleName) { import scala.concurrent.duration._ import rep.utils.IdTool import rep.sc.BlockStubActor._ - import rep.network.consensus.cfrd.block.Blocker + import rep.network.consensus.cfrd.block.BlockerOfCFRD import rep.network.consensus.util.BlockHelp - import rep.network.persistence.Storager.{SourceOfBlock, BlockRestore} + import rep.network.persistence.IStorager.{SourceOfBlock} implicit val timeout = Timeout(6.seconds) @@ -55,7 +56,7 @@ class BlockStubActor(moduleName: String) extends ModuleBase(moduleName) { //val ref = pe.getActorRef(ActorType.preloaderoftransaction) val ref = pe.getActorRef(ModuleActorType.ActorType.dispatchofpreload) //val ref1 = this.transpreload - val future = ref ? Blocker.PreTransBlock(block, "preload") + val future = ref ? PreTransBlock(block, "preload") val result = Await.result(future, timeout.duration).asInstanceOf[PreTransBlockResult] if (result.result) { result.blc