mirror of
https://gitee.com/BTAJL/repchain.git
synced 2024-12-02 03:38:08 +08:00
修改目标:共识抽象,达到共识切换。
完成共识层的接口抽象,并实现了cfrd、raft协议。
This commit is contained in:
parent
37e8acd8ed
commit
6f220dc1c3
@ -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
|
||||
}
|
||||
|
||||
|
@ -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{
|
||||
|
@ -31,6 +31,7 @@ trait BaseActor extends Actor {
|
||||
|
||||
var schedulerLink: akka.actor.Cancellable = null
|
||||
|
||||
//implicit
|
||||
def scheduler = context.system.scheduler
|
||||
|
||||
/**
|
||||
|
@ -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)) {
|
22
src/main/scala/rep/network/cache/cfrd/TransactionPoolOfCFRD.scala
vendored
Normal file
22
src/main/scala/rep/network/cache/cfrd/TransactionPoolOfCFRD.scala
vendored
Normal 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
|
||||
}
|
||||
}
|
22
src/main/scala/rep/network/cache/raft/TransactionPoolOfRAFT.scala
vendored
Normal file
22
src/main/scala/rep/network/cache/raft/TransactionPoolOfRAFT.scala
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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 {
|
||||
//错误,没有符合大多人背书要求。
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
56
src/main/scala/rep/network/consensus/cfrd/MsgOfCFRD.scala
Normal file
56
src/main/scala/rep/network/consensus/cfrd/MsgOfCFRD.scala
Normal 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(共识)消息,结束/////////////////////////
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
||||
}
|
@ -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}"))
|
||||
|
@ -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)
|
||||
|
||||
}
|
||||
}
|
@ -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]
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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的相关消息,结束//////////////////////////////
|
||||
}
|
@ -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]
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
141
src/main/scala/rep/network/consensus/common/block/IBlocker.scala
Normal file
141
src/main/scala/rep/network/consensus/common/block/IBlocker.scala
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
106
src/main/scala/rep/network/consensus/raft/vote/VoterOfRAFT.scala
Normal file
106
src/main/scala/rep/network/consensus/raft/vote/VoterOfRAFT.scala
Normal 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)
|
||||
}
|
||||
|
||||
}
|
@ -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,
|
||||
|
@ -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))
|
@ -1,5 +1,9 @@
|
||||
package rep.network.module
|
||||
|
||||
/**
|
||||
* Created by jiangbuyun on 2020/03/15.
|
||||
* 模块管理的接口
|
||||
*/
|
||||
trait IModule {
|
||||
def startupConsensus: Unit
|
||||
def loadConsensusModule:Unit
|
||||
|
@ -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 = ???
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
package rep.network.module
|
||||
|
||||
|
||||
/**
|
||||
* Created by jiangbuyun on 2020/03/15.
|
||||
* 共识模块中管理的公共的actor
|
||||
*/
|
||||
object ModuleActorType {
|
||||
|
||||
//系统的actor类型的注册,关键字以10开头
|
||||
|
@ -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{
|
||||
|
@ -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"))
|
||||
}
|
||||
|
||||
|
@ -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"))
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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,小于本地高度,不需要同步,停止同步"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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}"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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,小于本地高度,不需要同步,停止同步"))
|
||||
}
|
||||
}
|
||||
}
|
194
src/main/scala/rep/network/sync/request/ISynchRequester.scala
Normal file
194
src/main/scala/rep/network/sync/request/ISynchRequester.scala
Normal 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())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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 = {}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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"))
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -169,4 +169,8 @@ class TransactionPoolMgr {
|
||||
transactions.size
|
||||
//this.transNumber.get
|
||||
}
|
||||
|
||||
def isEmpty:Boolean={
|
||||
transactions.isEmpty
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user