修改目标:共识抽象,达到共识切换。

完成共识层的接口抽象,并实现了cfrd、raft协议。
This commit is contained in:
wuwei1972 2020-03-20 00:44:08 +08:00
parent 37e8acd8ed
commit 6f220dc1c3
55 changed files with 1881 additions and 1523 deletions

View File

@ -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
}

View File

@ -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{

View File

@ -31,6 +31,7 @@ trait BaseActor extends Actor {
var schedulerLink: akka.actor.Cancellable = null
//implicit
def scheduler = context.system.scheduler
/**

View File

@ -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)) {

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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 {
//错误没有符合大多人背书要求
}
}
}
}

View File

@ -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)
}
}
}

View File

@ -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共识消息结束/////////////////////////
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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}"))

View File

@ -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)
}
}

View File

@ -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]
}

View File

@ -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)
}
}

View File

@ -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的相关消息结束//////////////////////////////
}

View File

@ -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]
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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,

View File

@ -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))

View File

@ -1,5 +1,9 @@
package rep.network.module
/**
* Created by jiangbuyun on 2020/03/15.
* 模块管理的接口
*/
trait IModule {
def startupConsensus: Unit
def loadConsensusModule:Unit

View File

@ -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 = ???

View File

@ -1,5 +1,10 @@
package rep.network.module
/**
* Created by jiangbuyun on 2020/03/15.
* 共识模块中管理的公共的actor
*/
object ModuleActorType {
//系统的actor类型的注册关键字以10开头

View File

@ -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{

View File

@ -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"))
}

View File

@ -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"))
}
}

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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)

View File

@ -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
}
}
}

View File

@ -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,小于本地高度,不需要同步,停止同步"))
}
}
}
}

View File

@ -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}"))
}
}
}

View File

@ -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,小于本地高度,不需要同步,停止同步"))
}
}
}

View File

@ -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())
}
}
}

View File

@ -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 = {}
}

View File

@ -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)
}
}

View File

@ -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"))
}

View File

@ -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();

View File

@ -169,4 +169,8 @@ class TransactionPoolMgr {
transactions.size
//this.transNumber.get
}
def isEmpty:Boolean={
transactions.isEmpty
}
}

View File

@ -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 {

View File

@ -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)
}

View File

@ -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

View File

@ -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