Merge remote-tracking branch 'origin/RepChain_1.1.0_RC'

# Conflicts:
#	README.md
This commit is contained in:
brightestboy 2020-11-01 17:29:55 +08:00
commit bbcb252aa5
187 changed files with 11024 additions and 5961 deletions

View File

@ -14,11 +14,11 @@
- [java security](http://docs.oracle.com/javase/8/docs/technotes/guides/security/index.html)——hash、签名、密钥对及证书管理均采用jdk内置方法
## 安装
- install [jdk8+](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
- install [zuluJdk11+](https://www.azul.com/downloads/zulu-community/?&architecture=x86-64-bit&package=jdk)
- install [Python](http://www.python.org/downloads/)
- install [Scala](https://www.scala-lang.org/download/)
- install [SBT](http://www.scala-sbt.org/release/docs/Setup.html)
- install [Scala IDE](http://scala-ide.org/)
- install [Idea IDE](https://www.jetbrains.com/idea/download/#section=windows)
- install [keystore-explorer](http://keystore-explorer.org/) ——用于生成密钥对的工具,非必须
- install [protobuf editor](https://github.com/Enide/polyglot-maven-editors)——编辑protobuf定义工具非必须
@ -32,16 +32,12 @@
- 监控层:在区块链网络中收集事件/日志,并将其以Protocol Buffers的格式推送至Web端,以H5图形技术进行实时状态的可视化展示和日志回放
## 运行
- `git clone https://gitee.com/BTAJL/repchain.git`
下载项目到本地
- `sbt`
在项目的根目录下下载项目依赖项,可以配置仓库或者使用阿里镜像
- `compile`
编译成Protocol Buffer Scala类
- `eclipse`
生成eclipse工程文件
- 打开 Scala IDE, File->Import->Existing Projects,导入项目
- 右键单击 rep.app.Repchain.scala,Run As->Scala Application(单机组网4个节点)
- ` 下载项目到本地`
- git clone https://gitee.com/BTAJL/repchain.git
- `导入`
- 打开Idea IDEFile->New->Project or Project from VersionControl
- 使用Idea的sbt插件导入
- 右键单击 rep.app.Repchain.scalaRun 'RepChain'(单机组网4个节点)
- 运行配置VM参数 -Dlogback.configurationFile=conf/logback.xml (使logback配置生效)
- 查看实时图 http://localhost:8081/web/g1.html
![实时状态图](https://images.gitee.com/uploads/images/2020/0114/174424_b02748a4_1598833.gif)
@ -55,7 +51,7 @@
## 打包
- assembly
打包成jar包进行分布式部署
- 打包成jar包进行分布式部署
## 示范应用
- [BAR](https://gitee.com/linkel/bar)(Base App of RepChain):提供了通用的基础功能实现,区块链应用实施者既可以直接复用其提供的功能, 也可以在其源代码的基础上进行开发快速开发自己的DAppp

View File

@ -1,17 +1,18 @@
name := """RepChain"""
version := "0.9"
version := "1.0"
scalaVersion := "2.12.8"
scalaVersion := "2.12.10"
lazy val akkaVersion = "2.6.1"
val akkaHttpVersion = "10.1.11"
lazy val akkaVersion = "2.5.22"
val akkaHttpVersion = "10.1.8"
dependencyOverrides ++= Seq(
"org.json4s" % "json4s-jackson_2.12" % "3.6.5",
"org.json4s" % "json4s-jackson" % "3.6.7",
"com.google.guava" % "guava" % "21.0",
"com.thesamet.scalapb" % "scalapb-runtime_2.12" % "0.7.0",
"org.scala-lang.modules" % "scala-xml_2.12" % "1.1.1"
"com.thesamet.scalapb" % "scalapb-runtime" % "0.10.0-M2",
"org.scala-lang.modules" % "scala-xml" % "2.0.0-M1"
)
libraryDependencies ++= Seq(
@ -22,7 +23,7 @@ libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-slf4j" % akkaVersion,
"com.typesafe.akka" %% "akka-persistence" % akkaVersion,
"com.typesafe.akka" %% "akka-distributed-data" % akkaVersion
)
)
libraryDependencies += "com.typesafe.akka" %% "akka-http-xml" % akkaHttpVersion
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
@ -30,44 +31,51 @@ libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2"
libraryDependencies += "com.thesamet.scalapb" %% "scalapb-json4s" % "0.7.0"
libraryDependencies += "com.thesamet.scalapb" %% "scalapb-json4s" % "0.10.1-M1"
libraryDependencies += "org.iq80.leveldb" % "leveldb" % "0.11"
libraryDependencies += "org.iq80.leveldb" % "leveldb" % "0.12"
libraryDependencies += "org.fusesource.leveldbjni" % "leveldbjni-all" % "1.8"
libraryDependencies += "org.rocksdb" % "rocksdbjni" % "6.4.6"
libraryDependencies += "org.mapdb" % "mapdb" % "3.0.7"
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.14.0" % "test"
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.7"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.7" % "test"
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.8"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test"
libraryDependencies += "org.javadelight" % "delight-nashorn-sandbox" % "0.1.22"
libraryDependencies += "org.javadelight" % "delight-nashorn-sandbox" % "0.1.27"
libraryDependencies += "io.spray" %% "spray-json" % "1.3.5"
libraryDependencies += "com.gilt" %% "gfc-timeuuid" % "0.0.8"
//libraryDependencies += "com.gilt" %% "gfc-timeuuid" % "0.0.8"
libraryDependencies += "io.netty" % "netty" % "3.10.6.Final"
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
libraryDependencies += "org.codehaus.janino" % "janino" % "3.0.12"
libraryDependencies += "org.bouncycastle" % "bcprov-jdk15on" % "1.61"
libraryDependencies += "javax.xml.bind" % "jaxb-api" % "2.3.1"
libraryDependencies ++= Seq(
"io.swagger" % "swagger-jaxrs" % "1.5.18",
"com.github.swagger-akka-http" %% "swagger-akka-http" % "1.0.0",
"io.swagger" % "swagger-jaxrs" % "1.6.0",
"com.github.swagger-akka-http" %% "swagger-akka-http" % "1.1.1",
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
"org.json4s" %% "json4s-native" % "3.6.5",
"org.json4s" %% "json4s-jackson" % "3.6.5",
"org.json4s" %% "json4s-native" % "3.6.7",
"org.json4s" %% "json4s-jackson" % "3.6.7",
"ch.megard" %% "akka-http-cors" % "0.4.0",
"de.heikoseeberger" % "akka-http-json4s_2.12" % "1.25.2",
"com.twitter" %% "chill-akka" % "0.9.3",
"com.twitter" % "chill-bijection_2.12" % "0.9.3"
)
"de.heikoseeberger" % "akka-http-json4s_2.12" % "1.26.0",
"com.twitter" %% "chill-akka" % "0.9.4",
"com.twitter" % "chill-bijection_2.12" % "0.9.4"
)
javacOptions ++= Seq("-encoding", "UTF-8")
@ -75,13 +83,15 @@ PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
)
libraryDependencies += "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"
addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1.17")
scalacOptions += "-P:linter:disable:UseIfExpression+VariableAssignedUnusedValue+UseGetOrElseNotPatMatch"
scapegoatVersion in ThisBuild := "1.3.3"
scapegoatDisabledInspections := Seq("OptionGet", "AsInstanceOf","MethodReturningAny")
//addCompilerPlugin("org.psywerx.hairyfotr" %% "linter" % "0.1.17")
//scalacOptions += "-P:linter:disable:UseIfExpression+VariableAssignedUnusedValue+UseGetOrElseNotPatMatch"
//scapegoatVersion in ThisBuild := "1.3.3"
//scapegoatDisabledInspections := Seq("OptionGet", "AsInstanceOf","MethodReturningAny")
assemblyMergeStrategy in assembly := {
case PathList("org", "iq80", "leveldb", xs @ _*) => MergeStrategy.first
case PathList("module-info.class") => MergeStrategy.discard
case PathList("google", "protobuf", "field_mask.proto") => MergeStrategy.discard
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)

View File

@ -227,6 +227,27 @@
</encoder>
</appender>
<appender name="APIAccess_Appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/RepChain-APIAccess-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- each file should be at most 100MB, keep 30 days worth of history, but at most 3GB -->
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>TRACE</level>
</filter>
<immediateFlush>false</immediateFlush>
<append>false</append>
<encoder charset="UTF-8">
<pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<!--level过滤器简化版-->
@ -281,6 +302,10 @@
<logger name="TransLifeCycle_Logger" additivity="false" level="TRACE">
<appender-ref ref="TransLifeCycle_Appender"/>
</logger>
<logger name="APIAccess_Logger" additivity="false" level="TRACE">
<appender-ref ref="APIAccess_Appender"/>
</logger>
<root level="DEBUG">
<appender-ref ref="STDOUT" additivity="false"/>

View File

@ -1,174 +1,203 @@
akka {
actor {
warn-about-java-serializer-usage = off//关闭Java序列化来序列化消息时的警告建议不要开启。如果开启开启值=on
default-mailbox {
//akka默认邮箱的选择默认配置是akka.dispatch.SingleConsumerOnlyUnboundedMailbox这是一个多生产者单消费者队列。建议不要修改此参数
mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
}
default-dispatcher{
//akka dispatcher 配置采用akka的默认的fork-join-executor建议不要修改。
parallelism-min =80 //最小的线程数
parallelism-factor = 3.0 //并行因子配置
parallelism-max = 200 //最大的线程数
throughput = 10
}
}
// cluster {
// //种子节点的配置,在单机单节点的情况下需要配置种子节点的信息
// seed-nodes = ["akka.ssl.tcp://Repchain@192.168.100.93:8082"]
// }
#remote.netty.tcp.port=0
// remote.netty.ssl.port = 0
remote {
//远程相关的配置
netty.ssl {
//在单机单节点的情况下配置机器ip
// hostname=192.168.100.93
//在单机单节点的情况下需要配置具体的端口在单机多节点的情况下直接配置为0
port = 0
// port=8082//0automatic assign
//internal (bind) hostname
// bind-hostname=192.168.1.129
// bind-port=8082
}
netty.ssl.security {
//基础路径,证书的存放路径,建议不要修改
base-path = "jks/"
//名称前缀,证书的名称前缀,不要修改
base-name = ""
//证书的别名,需要跟节点的名称要保持一致
alias = "121000005l35120456.node1"
//用户ca文件密码
key-store-password = "123"
//用户证书密码
key-password = "123"
}
}
}
akka.http {
//akka 与http服务相关的配置
idle-timeout = 100s//一个空闲连接超时时间配置,当空闲连接超时之后,将被自动关闭
server {
server-header = akka-http/${akka.http.version}//http服务头建议不要修改
idle-timeout = 100s//空闲连接超时时间,超时将自动关闭连接
request-timeout = 100s //请求对超时时间
max-connections = 1024//最大对连接数
}
client {
idle-timeout = 100s //空闲连接超时时间,超时将自动关闭
connecting-timeout = 100s//建立连接对超时时间
}
}
system {
//创世节点的名称,在系统初始化时,将根据该节点是否是创世节点进行创世块的建立
genesis_node_name="121000005l35120456.node1"
//api是否开启
//如果是单机多节点测试模式Repchain则选择0默认节点1会开启
ws_enable = 1//api 0,不开启;1,开启
//交易生产方式
trans_create_type = 1 //0,手动;1,自动
//是否进行TPS测试
statistic_enable = 1 // 0,unable;able
//实时图的事件是否发送,如果不发送,前端实时图将收不到任何消息。
realtimegraph_enable = 1//0 unable;1 enable; default 1
httpServicePort = 8081//http服务的端口号默认为8081
checkCertValidate = 0//设置是否检查证书的有效性默认为0 0=不校验1=校验
contractOperationMode = 0//设置合约的运行方式0=debug方式1=deploy默认为debug方式如果发布部署必须使用deploy方式。
number_of_transProcessor = 10//
block {
//块内交易的最大数量
trans_num_limit = 80
//块内交易标准最小数量
trans_num_min = 1
//交易数量不足,重试次数
retry_time = 10
//区块的最大长度,不能大于传输的消息的最大长度,单位是字节
block_length = 120000
}
vote {
//最低投票人数量
vote_note_min = 4
//参与共识的节点别名
vote_node_list = ["121000005l35120456.node1","12110107bi45jh675g.node2",
"122000002n00123567.node3","921000005k36123789.node4","921000006e0012v696.node5"]
}
account{
chaincodename = "ContractCert"//账户管理合约的名称
chaincodeversion = 1
//证书状态改变函数名
CertStatusChangeFunction="UpdateCertStatus"
}
diskspaceManager{
diskspacealarm = 5000//磁盘最少空间大小单位M ,小于这个值系统将不能启动。
}
transaction {
//辅助自动创建交易的间隔
tran_create_dur = 50 //millis
//最大交易缓存量
max_cache_num = 60000
}
cluster {
//节点入网稳定时间
node_stable_delay = 5000 //millis
}
storage{
dbpath="/repchaindata/data/leveldbdata"
blockpath="/repchaindata/data/blockdata"
filemax=200000000//单位为字节
}
time {
//通用稳定延迟
stable_time_dur = 5000 //millis确保block模块能够接收到confirm的块数据
block {
//投票选举重试间隔
vote_retry_delay = 200
//投票重试无果后等待时间
//waiting_delay = 3600000
waiting_delay = 360
}
//超时策略1,手动0自动
timeout_policy_type = 1
timeout {
//Unit : Second 以下的超时时间一般采用默认配置
//For auto 自动采用的超时时间
//base_preload = 30//交易预执行的超时时间单位是s
//base_vote = 20//内部消息传递速度快,抽签的超时时间
//base_sync = 20//没有耗时操作,没有大块传输的情况下
//base_addition = 0//冗余量,不用配置
//For config manually 手工设置超时时间,系统主动采用手工设置的时间,可以不用设置
block = 90//出块的超时时间
endorse = 3//背书超时时间,单位为秒
transaction_preload = 30
sync_chain = 15//链同步的超时时间
transcation_waiting = 900//交易在交易池中等待入块到的超时时间,单位是秒
}
}
consensus {
//共识类型,目前只支持一种
type = "CRFD"
}
akka {
actor {
warn-about-java-serializer-usage = off#关闭Java序列化来序列化消息时的警告建议不要开启。如果开启开启值=on
default-mailbox {
#akka默认邮箱的选择默认配置是akka.dispatch.SingleConsumerOnlyUnboundedMailbox这是一个多生产者单消费者队列。建议不要修改此参数
mailbox-type = "akka.dispatch.SingleConsumerOnlyUnboundedMailbox"
}
default-dispatcher {
#akka dispatcher 配置采用akka的默认的fork-join-executor建议不要修改。
parallelism-min = 10 #最小的线程数
parallelism-factor = 4.0 #并行因子配置
parallelism-max = 100 #最大的线程数
throughput = 80
}
}
remote {
#classic模式下的配置
classic {
netty.tcp {
//在单机单节点的情况下配置机器ip
#hostname=192.168.10.155
#hostname = 192.168.31.155
hostname = 127.0.0.1
//在单机单节点的情况下需要配置具体的端口在单机多节点的情况下直接配置为0
//port = 0
//port=8082//0automatic assign
//internal (bind) hostname
//bind-hostname=192.168.1.129
//bind-port=8082
}
netty.ssl.security {
//基础路径,证书的存放路径,建议不要修改
base-path = "jks/"
//名称前缀,证书的名称前缀,不要修改
base-name = ""
//证书的别名,需要跟节点的名称要保持一致
alias = "121000005l35120456.node1"
//用户ca文件密码
key-store-password = "123"
//用户证书密码
key-password = "123"
}
}
#artery模式下的配置
artery {
#canonical.hostname = "192.168.10.155"
#canonical.hostname = "192.168.31.155"
canonical.hostname = "127.0.0.1"
canonical.port = 22526
}
}
cluster {
#种子节点的配置在单机单节点的情况下需要配置种子节点的信息akka://
#classic模式下的配置
#seed-nodes = ["akka.tcp://Repchain@192.168.10.155:22522","akka.tcp://Repchain@192.168.10.155:22523","akka.tcp://Repchain@192.168.10.155:22524"]
#seed-nodes = ["akka.ssl.tcp://Repchain@192.168.31.155:22522","akka.ssl.tcp://Repchain@192.168.31.155:22523","akka.ssl.tcp://Repchain@192.168.31.155:22524"]
#artery模式下的配置
#seed-nodes = ["akka://Repchain@192.168.10.155:22522","akka://Repchain@192.168.10.155:22523","akka://Repchain@192.168.10.155:22524"]
#seed-nodes = ["akka://Repchain@192.168.31.155:22522", "akka://Repchain@192.168.31.155:22523", "akka://Repchain@192.168.31.155:22526"]
seed-nodes = ["akka://Repchain@127.0.0.1:22522", "akka://Repchain@127.0.0.1:22523", "akka://Repchain@127.0.0.1:22526"]
}
}
akka.http {
#akka 与http服务相关的配置
idle-timeout = 100s#一个空闲连接超时时间配置,当空闲连接超时之后,将被自动关闭
server {
server-header = akka-http/${akka.http.version}#http服务头建议不要修改
idle-timeout = 100s#空闲连接超时时间,超时将自动关闭连接
request-timeout = 100s #请求对超时时间
max-connections = 1024#最大对连接数
}
client {
idle-timeout = 100s #空闲连接超时时间,超时将自动关闭
connecting-timeout = 100s#建立连接对超时时间
}
}
system {
#创世节点的名称,在系统初始化时,将根据该节点是否是创世节点进行创世块的建立
genesis_node_name = "121000005l35120456.node1"
#api是否开启
#如果是单机多节点测试模式Repchain则选择0默认节点1会开启
ws_enable = 1#api 0,不开启;1,开启
#交易生产方式
trans_create_type = 0 #0,手动;1,自动
#是否进行TPS测试
statistic_enable = 1 # 0,unable;able
#实时图的事件是否发送,如果不发送,前端实时图将收不到任何消息。
realtimegraph_enable = 1#0 unable;1 enable; default 1
httpServicePort = 8081#http服务的端口号默认为8081
checkCertValidate = 0#设置是否检查证书的有效性默认为0 0=不校验1=校验
contractOperationMode = 0#设置合约的运行方式0=debug方式1=deploy默认为debug方式如果发布部署必须使用deploy方式。
number_of_transProcessor = 10#
has_preload_trans_of_api = true#API接收交易时是否做交易的预执行检查。默认值true
is_verify_of_endorsement = true#在出块时背书节点是否验证交易默认值true
number_of_endorsement = 2#该参数确认背书比例可选值123如果等于1 表示有一个出块签名就可以了如果等于2表示达成共识需要大于节点的1/2如果等于3表示达成共识需要大于节点的2/3默认值是2.
block {
#块内交易的最大数量
trans_num_limit = 80
#块内交易标准最小数量
trans_num_min = 1
#交易数量不足,重试次数
retry_time = 10
#区块的最大长度,不能大于传输的消息的最大长度,单位是字节
block_length = 240000
}
vote {
#最低投票人数量
vote_node_min = 4
#参与共识的节点别名
vote_node_list = ["121000005l35120456.node1", "12110107bi45jh675g.node2",
"122000002n00123567.node3", "921000005k36123789.node4"
#]
, "921000006e0012v696.node5"]
}
account {
chaincodename = "ContractCert"#账户管理合约的名称
chaincodeversion = 1
#证书状态改变函数名
CertStatusChangeFunction = "UpdateCertStatus"
}
diskspaceManager {
diskspacealarm = 5000#磁盘最少空间大小单位M ,小于这个值系统将不能启动。
}
transaction {
#辅助自动创建交易的间隔
tran_create_dur = 50 #millis
#最大交易缓存量
max_cache_num = 60000
}
cluster {
#节点入网稳定时间
node_stable_delay = 5000 #millis
}
storage {
dbpath = "/Users/jiangbuyun/repchaindata/data/leveldbdata"
blockpath = "/Users/jiangbuyun/repchaindata/data/blockdata"
filemax = 200000000#单位为字节
}
time {
#通用稳定延迟
stable_time_dur = 5000 #millis确保block模块能够接收到confirm的块数据
block {
#投票选举重试间隔
vote_retry_delay = 200
#投票重试无果后等待时间
#waiting_delay = 3600000
waiting_delay = 360
}
#超时策略1,手动0自动
timeout_policy_type = 1
timeout {
#Unit : Second 以下的超时时间一般采用默认配置
#For auto 自动采用的超时时间
#base_preload = 30#交易预执行的超时时间单位是s
#base_vote = 20#内部消息传递速度快,抽签的超时时间
#base_sync = 20#没有耗时操作,没有大块传输的情况下
#base_addition = 0#冗余量,不用配置
#For config manually 手工设置超时时间,系统主动采用手工设置的时间,可以不用设置
block = 90#出块的超时时间
endorse = 4#背书超时时间,单位为秒
transaction_preload = 2
sync_chain = 15#链同步的超时时间
transcation_waiting = 900#交易在交易池中等待入块到的超时时间,单位是秒
}
}
consensus {
#共识类型,目前只支持一种
type = "CFRD"//内置三种共识协议CFRD、RAFT、PBFT
blocknumberofraft = 100
}
}

View File

@ -1,11 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIBmjCCAT+gAwIBAgIEXIn07TAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATEwHhcNMTkwMzE0MDYzMDA1WhcNMjAwMzEz
MDYzMDA1WjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATEw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAASlh+oDBPdwHEkpQT4/g4RX9ubP7jMM2Qod
iFtsnv+ObQ3dxfQN/S515ePssn3HjPCwfzR3S1KY4O9vFtH1Jql9MAoGCCqGSM49
BAMCA0kAMEYCIQCG2NFkYx06oWahUDflmXDkoXyTBIvjnA/M2yJlou3RIQIhAJcA
1X1djf5oGPc+6GYh9g4YhQ59HxV3p6kAEuRI13PP
MIIBTDCB9KADAgECAgRd7wBCMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBMTAeFw0xOTEyMTAwMjE3Mzha
Fw0yMDEyMDkwMjE3MzhaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJu7PT4Z
s5hqqNha9SrP60TecIDVYGry0v6ayV5lP8w5FJ2UtRECrpUxuoO2pfaHfxyYIXCZ
A8w7YaZU0s4CEfcwCgYIKoZIzj0EAwIDRwAwRAIgcAxkxmiNexPx8CF+DvII7168
eeVcfsJwoMcFFLKCWrECICSIkc9vC6Vwze3s2UwBuIiSlwNxZ0YDJcdlbcmESWHy
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -1,11 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBmTCCAT+gAwIBAgIEXIn2LzAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATIwHhcNMTkwMzE0MDYzNTI3WhcNMjAwMzEz
MDYzNTI3WjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATIw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAAQbGHprzZj8UABd4LFvAoFVPFc/xDkWybEJ
oF3iey/BvIVvBrB92xskV8ULlOt+qjQGIz0SdRiCrqs+YacCAo/xMAoGCCqGSM49
BAMCA0gAMEUCIDdarnwrREWGu3YQMvcFItU3e5X9J7kwgVw3uvZg77r0AiEAgIhG
TTVwdvjjewyeOXoVT/emsGz314jZJTYbtzoZiv8=
MIIBTTCB9KADAgECAgRd7wDfMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBMjAeFw0xOTEyMTAwMjIwMTVa
Fw0yMDEyMDkwMjIwMTVaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBMjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIqbpyaG
r7ST/JsS86YBzlG/S3WqyXBCk00OvUfGcynwJt8m0vUnj8Z5QxNtsTUtMilzVayn
B7dVpeM1rFB/bGEwCgYIKoZIzj0EAwIDSAAwRQIhAKzfA6yHLF57HoEk+aVRCVpv
vAvvQZuHKkYdzS7/TeXjAiBCtWh8sRO4kXjn9e8H0GHxmt+zQPHTr5UJt0b47BDB
lg==
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -1,11 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIBmTCCAT+gAwIBAgIEXIn6vTAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATMwHhcNMTkwMzE0MDY1NDUzWhcNMjAwMzEz
MDY1NDUzWjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATMw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAASdBDKlL7mW1NEfYDDb63d6O3/MueUT0Czr
bzcmLhrDvRyIO2fHl/zR/qrNy76cuRi7EednNO/G7qTemnJQqC9oMAoGCCqGSM49
BAMCA0gAMEUCIEXfvQcCZsnBiCWEPV0gWmxnhBbRRXE9oirBwb4J0Tu+AiEAk7Z8
3MRWR022p7AYeshwIXpaDlIu3N4VxatMHh3rs5I=
MIIBTDCB9KADAgECAgRd7wElMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBMzAeFw0xOTEyMTAwMjIxMjVa
Fw0yMDEyMDkwMjIxMjVaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHemUcIh
MpmOiWcbw5BBorqD+0LHaBzYVyKeYj2Sk3HR1M/JIb3R40xHEQbJPdb3SrgClSt6
LBiYiNENQBBJLw0wCgYIKoZIzj0EAwIDRwAwRAIgHX8epaHLqyPcNEj+fdD9zn/u
j8juebSZq42IRBAYTm0CICy+hKIZyVkNxPjV3tR+k+DjaWrDFSio57VuBbD8Cwvx
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -1,11 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBmjCCAT+gAwIBAgIEXIn75TAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATQwHhcNMTkwMzE0MDY1OTQ5WhcNMjAwMzEz
MDY1OTQ5WjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATQw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAAQy8jrMgX4TF/iuA42wEpYr82qIzBVFZmoJ
dyQTu2Pu5Ot4Jfg1sa/ibY4fxXX/Rc2bN8U0+88A7JiEqa0pRAQUMAoGCCqGSM49
BAMCA0kAMEYCIQDLBrE3v62ztcucfxZ27M0JqcgKWKT1Cow3JyCLZnhAQwIhANaQ
Iv1SgKX7fnhR3lga4IKdaFK6bpW/9YnDUsQ22kFL
MIIBTTCB9KADAgECAgRd7wFdMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBNDAeFw0xOTEyMTAwMjIyMjFa
Fw0yMDEyMDkwMjIyMjFaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBNDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAjzZaK8
UAvLLIpYgH3IVoezCK/sOz+BG1vb19BEdhbPJA/r1xBuDKG1DK9qIVSbAvfHrioH
NiceJs6Mym9TgYcwCgYIKoZIzj0EAwIDSAAwRQIgcaGwPxUC//H+yQFRq16m9aZp
aYwh+NwRs1SQ9USC170CIQCgTXpMxcTbfsKWiPY7QsTGCHn/c0+XS3nVIR2FWno5
Bg==
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -1,11 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBmTCCAT+gAwIBAgIEXIn8QzAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATUwHhcNMTkwMzE0MDcwMTIzWhcNMjAwMzEz
MDcwMTIzWjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATUw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAASRkmXqNawcVmoRYCRbxxuGMEhBkNi7mB6E
THeC+CzOw/G7spOXst4AEEcZwNwnu4yBsTI61O59+wWWoVzJMCfHMAoGCCqGSM49
BAMCA0gAMEUCIDUg9XvYS5gYplD2XpQIs2yYyG9yC3CYDVU3oHEbAhmgAiEA0857
jWV0BsnABl2+s/P/WYEuZWixQuO2YNGpwVG/u7g=
MIIBTTCB9KADAgECAgRd7wGTMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBNTAeFw0xOTEyMTAwMjIzMTVa
Fw0yMDEyMDkwMjIzMTVaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBNTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNVDTgfE
OQaHL8uQd6Zb4VqQQOuuz/f12zIKQ9QcMaRs87H1o3JBoydjUHSV6e60tXtHt1Ty
vaswF9EfMooKpaYwCgYIKoZIzj0EAwIDSAAwRQIhAIHfXVE5IuR73YubAG2gvtZS
BHb0TBNri/dYEiCTYP6JAiBBpr0Ssf468NQo74ZjpZmnPBQ88fQApE9RA5WGPAY0
iA==
-----END CERTIFICATE-----

Binary file not shown.

View File

@ -1,12 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBrjCCAVOgAwIBAgIEXIn9HTAKBggqhkjOPQQDAjBgMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxFDASBgNVBAMMC3N1cGVyX2FkbWluMB4XDTE5MDMxNDA3MDUw
MVoXDTIwMDMxMzA3MDUwMVowYDELMAkGA1UEBhMCY24xCzAJBgNVBAgMAmJqMQsw
CQYDVQQHDAJiajERMA8GA1UECgwIcmVwY2hhaW4xDjAMBgNVBAsMBWlzY2FzMRQw
EgYDVQQDDAtzdXBlcl9hZG1pbjBWMBAGByqGSM49AgEGBSuBBAAKA0IABBLsxfk6
B86BFI3ij2YJylNGzxXNRQb45mZPNfVAkQf0hImHJMP+EgCK7UfJqa1U970ZslSC
VTDxNyrb5wfLOIMwCgYIKoZIzj0EAwIDSQAwRgIhANUOIZN0YmYxbtmUlJeMaeEe
b2STEd2Z07l1WBUN+mN9AiEAqKXR2Z/F+t0lWELgO4I+fxHiw+GIBYYLlsRVy4zZ
vvU=
MIIBYzCCAQigAwIBAgIEXe8B6zAKBggqhkjOPQQDAjA5MREwDwYDVQQKDAhyZXBj
aGFpbjEOMAwGA1UECwwFaXNjYXMxFDASBgNVBAMMC3N1cGVyX2FkbWluMB4XDTE5
MTIxMDAyMjQ0M1oXDTIwMTIwOTAyMjQ0M1owOTERMA8GA1UECgwIcmVwY2hhaW4x
DjAMBgNVBAsMBWlzY2FzMRQwEgYDVQQDDAtzdXBlcl9hZG1pbjBZMBMGByqGSM49
AgEGCCqGSM49AwEHA0IABK9m+cb8jaYQ+ts/hK4INuQbOwAwoIhVa3uaRxsOsgoR
+QaPuwcZAIbGWSa9bn8oGjSBDQutmE5XONbdiDwPRtwwCgYIKoZIzj0EAwIDSQAw
RgIhAKZto+39OFced9YDaXYkOLrLcKD+8RbF57vzHpJrnFd1AiEAhNEK8MOsAlhM
eRZmlXsq4KsvQFs+Wav9N9qJ+GGRpCs=
-----END CERTIFICATE-----

View File

@ -1,11 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIBmjCCAT+gAwIBAgIEXIn07TAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATEwHhcNMTkwMzE0MDYzMDA1WhcNMjAwMzEz
MDYzMDA1WjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATEw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAASlh+oDBPdwHEkpQT4/g4RX9ubP7jMM2Qod
iFtsnv+ObQ3dxfQN/S515ePssn3HjPCwfzR3S1KY4O9vFtH1Jql9MAoGCCqGSM49
BAMCA0kAMEYCIQCG2NFkYx06oWahUDflmXDkoXyTBIvjnA/M2yJlou3RIQIhAJcA
1X1djf5oGPc+6GYh9g4YhQ59HxV3p6kAEuRI13PP
MIIBTDCB9KADAgECAgRd7wBCMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBMTAeFw0xOTEyMTAwMjE3Mzha
Fw0yMDEyMDkwMjE3MzhaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJu7PT4Z
s5hqqNha9SrP60TecIDVYGry0v6ayV5lP8w5FJ2UtRECrpUxuoO2pfaHfxyYIXCZ
A8w7YaZU0s4CEfcwCgYIKoZIzj0EAwIDRwAwRAIgcAxkxmiNexPx8CF+DvII7168
eeVcfsJwoMcFFLKCWrECICSIkc9vC6Vwze3s2UwBuIiSlwNxZ0YDJcdlbcmESWHy
-----END CERTIFICATE-----

View File

@ -1,11 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBmTCCAT+gAwIBAgIEXIn2LzAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATIwHhcNMTkwMzE0MDYzNTI3WhcNMjAwMzEz
MDYzNTI3WjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATIw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAAQbGHprzZj8UABd4LFvAoFVPFc/xDkWybEJ
oF3iey/BvIVvBrB92xskV8ULlOt+qjQGIz0SdRiCrqs+YacCAo/xMAoGCCqGSM49
BAMCA0gAMEUCIDdarnwrREWGu3YQMvcFItU3e5X9J7kwgVw3uvZg77r0AiEAgIhG
TTVwdvjjewyeOXoVT/emsGz314jZJTYbtzoZiv8=
MIIBTTCB9KADAgECAgRd7wDfMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBMjAeFw0xOTEyMTAwMjIwMTVa
Fw0yMDEyMDkwMjIwMTVaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBMjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIqbpyaG
r7ST/JsS86YBzlG/S3WqyXBCk00OvUfGcynwJt8m0vUnj8Z5QxNtsTUtMilzVayn
B7dVpeM1rFB/bGEwCgYIKoZIzj0EAwIDSAAwRQIhAKzfA6yHLF57HoEk+aVRCVpv
vAvvQZuHKkYdzS7/TeXjAiBCtWh8sRO4kXjn9e8H0GHxmt+zQPHTr5UJt0b47BDB
lg==
-----END CERTIFICATE-----

View File

@ -1,11 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIBmTCCAT+gAwIBAgIEXIn6vTAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATMwHhcNMTkwMzE0MDY1NDUzWhcNMjAwMzEz
MDY1NDUzWjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATMw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAASdBDKlL7mW1NEfYDDb63d6O3/MueUT0Czr
bzcmLhrDvRyIO2fHl/zR/qrNy76cuRi7EednNO/G7qTemnJQqC9oMAoGCCqGSM49
BAMCA0gAMEUCIEXfvQcCZsnBiCWEPV0gWmxnhBbRRXE9oirBwb4J0Tu+AiEAk7Z8
3MRWR022p7AYeshwIXpaDlIu3N4VxatMHh3rs5I=
MIIBTDCB9KADAgECAgRd7wElMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBMzAeFw0xOTEyMTAwMjIxMjVa
Fw0yMDEyMDkwMjIxMjVaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHemUcIh
MpmOiWcbw5BBorqD+0LHaBzYVyKeYj2Sk3HR1M/JIb3R40xHEQbJPdb3SrgClSt6
LBiYiNENQBBJLw0wCgYIKoZIzj0EAwIDRwAwRAIgHX8epaHLqyPcNEj+fdD9zn/u
j8juebSZq42IRBAYTm0CICy+hKIZyVkNxPjV3tR+k+DjaWrDFSio57VuBbD8Cwvx
-----END CERTIFICATE-----

View File

@ -1,11 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBmjCCAT+gAwIBAgIEXIn75TAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATQwHhcNMTkwMzE0MDY1OTQ5WhcNMjAwMzEz
MDY1OTQ5WjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATQw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAAQy8jrMgX4TF/iuA42wEpYr82qIzBVFZmoJ
dyQTu2Pu5Ot4Jfg1sa/ibY4fxXX/Rc2bN8U0+88A7JiEqa0pRAQUMAoGCCqGSM49
BAMCA0kAMEYCIQDLBrE3v62ztcucfxZ27M0JqcgKWKT1Cow3JyCLZnhAQwIhANaQ
Iv1SgKX7fnhR3lga4IKdaFK6bpW/9YnDUsQ22kFL
MIIBTTCB9KADAgECAgRd7wFdMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBNDAeFw0xOTEyMTAwMjIyMjFa
Fw0yMDEyMDkwMjIyMjFaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBNDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAjzZaK8
UAvLLIpYgH3IVoezCK/sOz+BG1vb19BEdhbPJA/r1xBuDKG1DK9qIVSbAvfHrioH
NiceJs6Mym9TgYcwCgYIKoZIzj0EAwIDSAAwRQIgcaGwPxUC//H+yQFRq16m9aZp
aYwh+NwRs1SQ9USC170CIQCgTXpMxcTbfsKWiPY7QsTGCHn/c0+XS3nVIR2FWno5
Bg==
-----END CERTIFICATE-----

View File

@ -1,11 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBmTCCAT+gAwIBAgIEXIn8QzAKBggqhkjOPQQDAjBWMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxCjAIBgNVBAMMATUwHhcNMTkwMzE0MDcwMTIzWhcNMjAwMzEz
MDcwMTIzWjBWMQswCQYDVQQGEwJjbjELMAkGA1UECAwCYmoxCzAJBgNVBAcMAmJq
MREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UECwwFaXNjYXMxCjAIBgNVBAMMATUw
VjAQBgcqhkjOPQIBBgUrgQQACgNCAASRkmXqNawcVmoRYCRbxxuGMEhBkNi7mB6E
THeC+CzOw/G7spOXst4AEEcZwNwnu4yBsTI61O59+wWWoVzJMCfHMAoGCCqGSM49
BAMCA0gAMEUCIDUg9XvYS5gYplD2XpQIs2yYyG9yC3CYDVU3oHEbAhmgAiEA0857
jWV0BsnABl2+s/P/WYEuZWixQuO2YNGpwVG/u7g=
MIIBTTCB9KADAgECAgRd7wGTMAoGCCqGSM49BAMCMC8xETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEKMAgGA1UEAwwBNTAeFw0xOTEyMTAwMjIzMTVa
Fw0yMDEyMDkwMjIzMTVaMC8xETAPBgNVBAoMCHJlcGNoYWluMQ4wDAYDVQQLDAVp
c2NhczEKMAgGA1UEAwwBNTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNVDTgfE
OQaHL8uQd6Zb4VqQQOuuz/f12zIKQ9QcMaRs87H1o3JBoydjUHSV6e60tXtHt1Ty
vaswF9EfMooKpaYwCgYIKoZIzj0EAwIDSAAwRQIhAIHfXVE5IuR73YubAG2gvtZS
BHb0TBNri/dYEiCTYP6JAiBBpr0Ssf468NQo74ZjpZmnPBQ88fQApE9RA5WGPAY0
iA==
-----END CERTIFICATE-----

View File

@ -1,12 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBrjCCAVOgAwIBAgIEXIn9HTAKBggqhkjOPQQDAjBgMQswCQYDVQQGEwJjbjEL
MAkGA1UECAwCYmoxCzAJBgNVBAcMAmJqMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwG
A1UECwwFaXNjYXMxFDASBgNVBAMMC3N1cGVyX2FkbWluMB4XDTE5MDMxNDA3MDUw
MVoXDTIwMDMxMzA3MDUwMVowYDELMAkGA1UEBhMCY24xCzAJBgNVBAgMAmJqMQsw
CQYDVQQHDAJiajERMA8GA1UECgwIcmVwY2hhaW4xDjAMBgNVBAsMBWlzY2FzMRQw
EgYDVQQDDAtzdXBlcl9hZG1pbjBWMBAGByqGSM49AgEGBSuBBAAKA0IABBLsxfk6
B86BFI3ij2YJylNGzxXNRQb45mZPNfVAkQf0hImHJMP+EgCK7UfJqa1U970ZslSC
VTDxNyrb5wfLOIMwCgYIKoZIzj0EAwIDSQAwRgIhANUOIZN0YmYxbtmUlJeMaeEe
b2STEd2Z07l1WBUN+mN9AiEAqKXR2Z/F+t0lWELgO4I+fxHiw+GIBYYLlsRVy4zZ
vvU=
MIIBYzCCAQigAwIBAgIEXe8B6zAKBggqhkjOPQQDAjA5MREwDwYDVQQKDAhyZXBj
aGFpbjEOMAwGA1UECwwFaXNjYXMxFDASBgNVBAMMC3N1cGVyX2FkbWluMB4XDTE5
MTIxMDAyMjQ0M1oXDTIwMTIwOTAyMjQ0M1owOTERMA8GA1UECgwIcmVwY2hhaW4x
DjAMBgNVBAsMBWlzY2FzMRQwEgYDVQQDDAtzdXBlcl9hZG1pbjBZMBMGByqGSM49
AgEGCCqGSM49AwEHA0IABK9m+cb8jaYQ+ts/hK4INuQbOwAwoIhVa3uaRxsOsgoR
+QaPuwcZAIbGWSa9bn8oGjSBDQutmE5XONbdiDwPRtwwCgYIKoZIzj0EAwIDSQAw
RgIhAKZto+39OFced9YDaXYkOLrLcKD+8RbF57vzHpJrnFd1AiEAhNEK8MOsAlhM
eRZmlXsq4KsvQFs+Wav9N9qJ+GGRpCs=
-----END CERTIFICATE-----

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
jks_ca/cacerts Normal file

Binary file not shown.

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIBVjCB/KADAgECAgRd8FknMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI0
OTExWhcNMjAxMjEwMDI0OTExWjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBW5vZGUxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEqLo9CXvQ/ZbpuA/M644S3sfnPtsg0IttOa1yGyEyxPHwuO3X9J2MOhO1DEq/
CSgwof8iuQ2RHnA798Ix7SQIZzAKBggqhkjOPQQDAgNJADBGAiEAw8UB0hqesZKW
NCqZ51kbGq2nxI4jvGYgij1E/Jm4+fUCIQDbTXWRf0TpjYnnCcAhyxSCGlrjnoIj
oldevvXCFhh9eg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBVTCB/KADAgECAgRd8FjlMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI0
ODA1WhcNMjAxMjEwMDI0ODA1WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBXRydXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEnWb6C7xEIwgDEm8TVP94eyeDkykKRnC27rrRSd+k7+M3aDUPYzDvgOQplThX
l0cHeiWNULwVnfJjNqUyVBN3WTAKBggqhkjOPQQDAgNIADBFAiALUEUiEUySNBh/
M8Yy9MZhLE/xBHY8Q0d3erPeFwX7zwIhAOZublAk8sSS5037mzQcFjm6f4pIAb29
4gEWsQQocHGV
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIBVjCB/KADAgECAgRd8Fq+MAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI1
NTU4WhcNMjAxMjEwMDI1NTU4WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBW5vZGUyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAE1UF23vURqGh/I/qF2Nu1JZTPsAMqZXtRrMeAfZ3HAA5EEtrvN9XDX8dWzVvI
cnFDVENEAmmhBY+TnD0p0JkXGDAKBggqhkjOPQQDAgNJADBGAiEAmQYrNxTszBRK
PnSI+BXyrnzDlWxcUEObDh7YglgiPo8CIQCXrVIV+Vib1aQuPxxkdZ5gDAj1BZzL
eXCyawEcEoyBTw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBVTCB/KADAgECAgRd8FjlMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI0
ODA1WhcNMjAxMjEwMDI0ODA1WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBXRydXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEnWb6C7xEIwgDEm8TVP94eyeDkykKRnC27rrRSd+k7+M3aDUPYzDvgOQplThX
l0cHeiWNULwVnfJjNqUyVBN3WTAKBggqhkjOPQQDAgNIADBFAiALUEUiEUySNBh/
M8Yy9MZhLE/xBHY8Q0d3erPeFwX7zwIhAOZublAk8sSS5037mzQcFjm6f4pIAb29
4gEWsQQocHGV
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIBVDCB/KADAgECAgRd8FrnMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI1
NjM5WhcNMjAxMjEwMDI1NjM5WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBW5vZGUzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAE7u1fRVED7v3mdvHiaAZbf/HcYPwRw6EB0qnl4GDj0l5WFoetrn+rV9oR3iw9
HNghSWiTmWdlUHY9Yp3q+GcnjzAKBggqhkjOPQQDAgNHADBEAiALZejrggAz0n7Y
YxKYjkF5BWBNOjVsrYfDYehSDahb+gIgWiEKqNgEwXKUpQXt30N80Yb2ZeufGJZO
bfQ+7mv+c1M=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBVTCB/KADAgECAgRd8FjlMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI0
ODA1WhcNMjAxMjEwMDI0ODA1WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBXRydXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEnWb6C7xEIwgDEm8TVP94eyeDkykKRnC27rrRSd+k7+M3aDUPYzDvgOQplThX
l0cHeiWNULwVnfJjNqUyVBN3WTAKBggqhkjOPQQDAgNIADBFAiALUEUiEUySNBh/
M8Yy9MZhLE/xBHY8Q0d3erPeFwX7zwIhAOZublAk8sSS5037mzQcFjm6f4pIAb29
4gEWsQQocHGV
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIBVjCB/KADAgECAgRd8FsPMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI1
NzE5WhcNMjAxMjEwMDI1NzE5WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBW5vZGU0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAETTaKhd0mdSXfrtYKYlyHmrnxE/eTQqpNUrFxhyXplqhp0rpjYbSM0kpZSSM5
5a4e4fCcZSLrx7qBGJrpQbnb/zAKBggqhkjOPQQDAgNJADBGAiEApUjqEWj+02vM
WC0t44OXrKbqBHOhxR6k+BPyBM8sCzgCIQCWaOY4aZEWkYtsLczWp8wR+xqM9kqD
vRpty2kdQVps+g==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBVTCB/KADAgECAgRd8FjlMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI0
ODA1WhcNMjAxMjEwMDI0ODA1WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBXRydXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEnWb6C7xEIwgDEm8TVP94eyeDkykKRnC27rrRSd+k7+M3aDUPYzDvgOQplThX
l0cHeiWNULwVnfJjNqUyVBN3WTAKBggqhkjOPQQDAgNIADBFAiALUEUiEUySNBh/
M8Yy9MZhLE/xBHY8Q0d3erPeFwX7zwIhAOZublAk8sSS5037mzQcFjm6f4pIAb29
4gEWsQQocHGV
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIBVTCB/KADAgECAgRd8FtYMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI1
ODMyWhcNMjAxMjEwMDI1ODMyWjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBW5vZGU1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEASPMg3T5RxEmclptDZP1I24rQKENZjAZdjjptu2+q9HAIyEhg5wWEsUYEFLj
Kc8cPZTjt//x6IeaW8cMMcKwfTAKBggqhkjOPQQDAgNIADBFAiAomWGLt0Bzo37N
PljL4BEpL8ty+DQ2sh3kH9ZlIP9msAIhAI7q7vvc28LKK8OsSBVYdmFHmZxfJLfo
D0vrJlaP5naM
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBVTCB/KADAgECAgRd8FjlMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI0
ODA1WhcNMjAxMjEwMDI0ODA1WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBXRydXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEnWb6C7xEIwgDEm8TVP94eyeDkykKRnC27rrRSd+k7+M3aDUPYzDvgOQplThX
l0cHeiWNULwVnfJjNqUyVBN3WTAKBggqhkjOPQQDAgNIADBFAiALUEUiEUySNBh/
M8Yy9MZhLE/xBHY8Q0d3erPeFwX7zwIhAOZublAk8sSS5037mzQcFjm6f4pIAb29
4gEWsQQocHGV
-----END CERTIFICATE-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIBXDCCAQKgAwIBAgIEXfBnhDAKBggqhkjOPQQDAjAzMREwDwYDVQQKDAhyZXBj
aGFpbjEOMAwGA1UECwwFaXNjYXMxDjAMBgNVBAMMBXRydXN0MB4XDTE5MTIxMTAz
NTAyOFoXDTIwMTIxMDAzNTAyOFowOTERMA8GA1UECgwIcmVwY2hhaW4xDjAMBgNV
BAsMBWlzY2FzMRQwEgYDVQQDDAtzdXBlcl9hZG1pbjBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABD63wpu3DEYo4EQN1p+IqCO3H2zaskh3gxaOWQM6hvQnyRpuQD4a
lV3eUouAooTO1YJyTNe/SIYCTVnHRv49lZowCgYIKoZIzj0EAwIDSAAwRQIhAJUs
C3pHUuMN2yRfpvjeKPgsPYxo+vzk56lIoP/qb8g0AiACuPOGx0tchoM7kBJo5el1
gZsvDnRy59oHebbpN04qrw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBVTCB/KADAgECAgRd8FjlMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI0
ODA1WhcNMjAxMjEwMDI0ODA1WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBXRydXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEnWb6C7xEIwgDEm8TVP94eyeDkykKRnC27rrRSd+k7+M3aDUPYzDvgOQplThX
l0cHeiWNULwVnfJjNqUyVBN3WTAKBggqhkjOPQQDAgNIADBFAiALUEUiEUySNBh/
M8Yy9MZhLE/xBHY8Q0d3erPeFwX7zwIhAOZublAk8sSS5037mzQcFjm6f4pIAb29
4gEWsQQocHGV
-----END CERTIFICATE-----

10
jks_ca/certs/trust.cer Normal file
View File

@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBVTCB/KADAgECAgRd8FjlMAoGCCqGSM49BAMCMDMxETAPBgNVBAoMCHJlcGNo
YWluMQ4wDAYDVQQLDAVpc2NhczEOMAwGA1UEAwwFdHJ1c3QwHhcNMTkxMjExMDI0
ODA1WhcNMjAxMjEwMDI0ODA1WjAzMREwDwYDVQQKDAhyZXBjaGFpbjEOMAwGA1UE
CwwFaXNjYXMxDjAMBgNVBAMMBXRydXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
QgAEnWb6C7xEIwgDEm8TVP94eyeDkykKRnC27rrRSd+k7+M3aDUPYzDvgOQplThX
l0cHeiWNULwVnfJjNqUyVBN3WTAKBggqhkjOPQQDAgNIADBFAiALUEUiEUySNBh/
M8Yy9MZhLE/xBHY8Q0d3erPeFwX7zwIhAOZublAk8sSS5037mzQcFjm6f4pIAb29
4gEWsQQocHGV
-----END CERTIFICATE-----

BIN
jks_ca/mytrust Normal file

Binary file not shown.

BIN
jks_ca/mytruststore.jks Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
jks_ca/p12s/super_admin.p12 Normal file

Binary file not shown.

BIN
jks_ca/p12s/trust.p12 Normal file

Binary file not shown.

BIN
jks_ca/trust Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
#Activator-generated Properties
#Fri May 05 17:07:13 CST 2017
template.uuid=eee3cc9c-3a01-4d07-9582-35d1adc10093
sbt.version=1.1.6
sbt.version=1.3.5

View File

@ -1,3 +1,3 @@
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5")
addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.9")
//addSbtPlugin("com.sksamuel.scapegoat" %% "sbt-scapegoat" % "1.0.9")
resolvers += Resolver.url("bintray-sbt-plugins", url("http://dl.bintray.com/sbt/sbt-plugin-releases"))(Resolver.ivyStylePatterns)

View File

@ -2,5 +2,5 @@ resolvers += "Sonatype snapshots" at "https://oss.sonatype.org/content/repositor
//addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.7.0-SNAPSHOT")
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.4")
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.20")
libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.8.4"
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.25")
libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.10.0-M2"

View File

@ -15,4 +15,4 @@ config_log="logback.xml"
#::=== execute
#-Dconfig.resourse=$config_base/$config_app
java -D$logger_name.configurationFile=$config_base/$config_log -jar $app_name
java -Dlogback.configurationFile=conf/logback.xml -jar $app_name

View File

@ -1,177 +1,194 @@
/*
* 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.
*
*/
syntax = "proto3";
package rep.protos;
option java_package = "rep.protos";
import "google/protobuf/timestamp.proto";
/*
*/
//Event
message Event {
//addr
string from = 1;
//addr广
string to = 2;
//event事件
enum Action {
SUBSCRIBE_TOPIC = 0;
TRANSACTION = 1;
BLOCK_NEW = 2;
BLOCK_ENDORSEMENT = 3;
ENDORSEMENT = 4;
MEMBER_UP = 5;
MEMBER_DOWN = 6;
CANDIDATOR = 7;
GENESIS_BLOCK = 8;
BLOCK_SYNC = 9;
BLOCK_SYNC_DATA = 10;
BLOCK_SYNC_SUC = 11;
}
Action action = 3;
Block blk = 4;
}
//
message Signer{
string name = 1; //,
string credit_code = 2; //,
string mobile = 3; // ,
repeated string cert_names = 4;//便
//map<string, Certificate> certs = 4; //
}
//
message CertId {
string credit_code = 1;
string cert_name = 2;//
}
//
message Certificate {
string certificate = 1; //
string alg_type = 2;//:ECDSA下的SHA1withECDSA,SHA512withECDSA等
bool cert_valid = 3;//true false protobuf默认该值为false
google.protobuf.Timestamp reg_Time = 4; //
google.protobuf.Timestamp unreg_Time = 5; //
}
//Transaction和Block
message Signature {
//
CertId cert_id = 1;
google.protobuf.Timestamp tm_local = 2; //
//
bytes signature = 3;
}
//
message ChaincodeInput {
string function = 1;
repeated string args = 2;
}
//,
message ChaincodeId {
string chaincodeName = 1;
int32 version = 2;
}
// ,/
message ChaincodeDeploy {
//Type only support javascript
int32 timeout = 1;
//
string code_package = 2;
//
string legal_prose =3;
enum CodeType {
CODE_UNDEFINED = 0;
CODE_JAVASCRIPT = 1;
CODE_SCALA = 2;
CODE_SCALA_PARALLEL = 3;
}
CodeType ctype = 4;
}
/*
*
*/
message Transaction {
string id = 1;
enum Type {
UNDEFINED = 0;
// deploy a chaincode to the network and call `Init` function
CHAINCODE_DEPLOY = 1;
// call a chaincode `Invoke` function as a transaction
CHAINCODE_INVOKE = 2;
CHAINCODE_SET_STATE = 3;
}
Type type = 2;
//store ChaincodeID as bytes so its encrypted value can be stored
ChaincodeId cid = 3;
oneof para {
ChaincodeDeploy spec = 4;
ChaincodeInput ipt = 5;
bool state = 6;
}
Signature signature = 7;
}
message Block {
// version - ,便
uint32 version = 1;
// , 1
uint64 height = 2;
//
repeated Transaction transactions = 3;
//
repeated TransactionResult transactionResults = 4;
//hashhash的时候hash
bytes hashOfBlock = 5;
// previousBlockHash - The hash of the previous block in the chain.
bytes previousBlockHash = 6;
//,
repeated Signature endorsements=7;
bytes stateHash = 8;
}
//
message OperLog{
string key =1;
bytes oldValue =2;
bytes newValue=3;
}
message ActionResult{
int32 code = 1;
string reason = 2;
}
//()
//block中的各个交易
message TransactionResult {
//Transaction
string txId = 1;
repeated OperLog ol = 2;
ActionResult result = 3;
}
message BlockchainInfo {
uint64 height = 1;
uint64 totalTransactions = 2;
bytes currentBlockHash = 3;
bytes previousBlockHash = 4;
bytes currentStateHash = 5;
}
/*
* 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.
*
*/
syntax = "proto3";
package rep.protos;
option java_package = "rep.protos";
import "google/protobuf/timestamp.proto";
/*
*/
//Event
message Event {
//addr
string from = 1;
//addr广
string to = 2;
//event事件
enum Action {
SUBSCRIBE_TOPIC = 0;
TRANSACTION = 1;
BLOCK_NEW = 2;
BLOCK_ENDORSEMENT = 3;
ENDORSEMENT = 4;
MEMBER_UP = 5;
MEMBER_DOWN = 6;
CANDIDATOR = 7;
GENESIS_BLOCK = 8;
BLOCK_SYNC = 9;
BLOCK_SYNC_DATA = 10;
BLOCK_SYNC_SUC = 11;
}
Action action = 3;
Block blk = 4;
}
//
message Signer {
string name = 1; //
string credit_code = 2; //DID使DID
string mobile = 3; // ,
repeated string cert_names = 4; //便did_certname
//map<string, Certificate> certs = 4; //
}
//
message CertId {
string credit_code = 1;
string cert_name = 2;//
}
//
message Certificate {
string certificate = 1; //
string alg_type = 2;//:ECDSA下的SHA1withECDSA,SHA512withECDSA等
bool cert_valid = 3;//true false protobuf默认该值为false
google.protobuf.Timestamp reg_Time = 4; //
google.protobuf.Timestamp unreg_Time = 5; //
}
//Transaction和Block
message Signature {
//
CertId cert_id = 1;
google.protobuf.Timestamp tm_local = 2; //
//
bytes signature = 3;
}
//
message ChaincodeInput {
string function = 1;
repeated string args = 2;
}
//,
message ChaincodeId {
string chaincodeName = 1;
int32 version = 2;
}
// ,/
message ChaincodeDeploy {
//Type only support javascript
int32 timeout = 1;
//
string code_package = 2;
//
string legal_prose =3;
enum CodeType {
CODE_UNDEFINED = 0;
CODE_JAVASCRIPT = 1;
CODE_SCALA = 2;
CODE_SCALA_PARALLEL = 3;
}
CodeType ctype = 4;
}
/*
*
*/
message Transaction {
string id = 1;
enum Type {
UNDEFINED = 0;
// deploy a chaincode to the network and call `Init` function
CHAINCODE_DEPLOY = 1;
// call a chaincode `Invoke` function as a transaction
CHAINCODE_INVOKE = 2;
CHAINCODE_SET_STATE = 3;
}
Type type = 2;
//store ChaincodeID as bytes so its encrypted value can be stored
ChaincodeId cid = 3;
oneof para {
ChaincodeDeploy spec = 4;
ChaincodeInput ipt = 5;
bool state = 6;
}
Signature signature = 7;
}
message Block {
// version - ,便
uint32 version = 1;
// , 1
uint64 height = 2;
//
repeated Transaction transactions = 3;
//
repeated TransactionResult transactionResults = 4;
//hashhash的时候hash
bytes hashOfBlock = 5;
// previousBlockHash - The hash of the previous block in the chain.
bytes previousBlockHash = 6;
//,
repeated Signature endorsements=7;
bytes stateHash = 8;
}
//
message OperLog{
string key =1;
bytes oldValue =2;
bytes newValue=3;
}
message ActionResult{
int32 code = 1;
string reason = 2;
}
//()
//block中的各个交易
message TransactionResult {
//Transaction
string txId = 1;
repeated OperLog ol = 2;
ActionResult result = 3;
}
message BlockchainInfo {
uint64 height = 1;
uint64 totalTransactions = 2;
bytes currentBlockHash = 3;
bytes previousBlockHash = 4;
bytes currentStateHash = 5;
}
//zhj
message MPbftPrepare {
Signature signature = 1;
}
//zhj
message MPbftCommit {
repeated MPbftPrepare prepares = 1;
Signature signature = 2;
}
//zhj
message MPbftReply {
repeated MPbftCommit commits = 1;
Signature signature = 2;
}

View File

@ -1,62 +1,183 @@
akka {
loggers = ["akka.event.slf4j.Slf4jLogger"]
# Options: ERROR, WARNING, INFO, DEBUG
loglevel = "INFO"
logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
// stdout-loglevel = "INFO"
// cluster.metrics.enabled = off
actor {
serialize-messages = on
serialize-creators = off
enable-additional-serialization-bindings = on
allow-java-serialization = off
provider = "akka.cluster.ClusterActorRefProvider"
serializers {
kryo = "com.twitter.chill.akka.AkkaSerializer"
java = "akka.serialization.JavaSerializer"
proto = "akka.remote.serialization.ProtobufSerializer"
}
serialization-bindings {
"java.lang.String" = java
"java.io.Serializable" = kryo
"com.google.protobuf.Message" = proto
"scalapb.GeneratedMessage" = proto
}
}
#remote.netty.tcp.port=0
remote.netty.ssl.port = 0
remote {
#mesage传输块大小配置
send-buffer-size = 2048000b
receive-buffer-size = 2048000b
maximum-frame-size = 1024000b
enabled-transports = [akka.remote.netty.ssl]
netty.ssl.security {
key-store = "jks/121000005l35120456.node1.jks"
trust-store = "jks/mytruststore.jks"
key-store-password = "123"
key-password = "123"
trust-store-password = "changeme"
protocol = "TLSv1.2"
enabled-algorithms = [TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256]
random-number-generator = "AES128CounterSecureRNG"
}
}
//创世块
genesisblock {
creationBlockTime = 1495451252086
}
}
akka {
loggers = ["akka.event.slf4j.Slf4jLogger"]
# Options: ERROR, WARNING, INFO, DEBUG
loglevel = "INFO"
logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
cluster {
akka.cluster.log-info = on
log-info-verbose = on
#jmx.enabled = on
#jmx.multi-mbeans-in-same-jvm = on
#min-nr-of-members = 4
}
actor {
serialize-messages = off
serialize-creators = off
enable-additional-serialization-bindings = on
allow-java-serialization = off
#provider = "akka.cluster.ClusterActorRefProvider"
provider = "cluster"
serializers {
kryo = "com.twitter.chill.akka.AkkaSerializer"
java = "akka.serialization.JavaSerializer"
proto = "akka.remote.serialization.ProtobufSerializer"
}
serialization-bindings {
"java.lang.String" = java
"java.io.Serializable" = kryo
"com.google.protobuf.Message" = proto
"scalapb.GeneratedMessage" = proto
}
}
remote {
classic {
netty.tcp {
transport-class = "akka.remote.transport.netty.NettyTransport"
#mesage传输块大小配置
send-buffer-size = 2048000b
receive-buffer-size = 2048000b
maximum-frame-size = 1024000b
enable-ssl = true
ssl-engine-provider = akka.remote.transport.netty.ConfigSSLEngineProvider
security {
key-store = "jks/121000005l35120456.node1.jks"
trust-store = "jks/mytruststore.jks" // 加载信任列表证书用的_tls1.3
#trust-store = "jks/mytrust" // ssl用的_ca
trust-store-mm = "jks/mytruststore.jks" // 加载信任列表证书用的_origin
key-store-password = "123"
key-password = "123"
trust-store-password = "changeme" // 加载信任列表证书用的_tls1.3
#trust-store-password = "changeit" // ssl用的_ca
trust-store-password-mm = "changeme" // 加载信任列表证书用的_origin
protocol = "TLSv1.3"
enabled-algorithms = [TLS_AES_128_GCM_SHA256]
require-mutual-authentication = on
random-number-generator = "SecureRandom"
}
}
netty.ssl.security {
key-store = "jks/121000005l35120456.node1.jks"
trust-store = "jks/mytruststore.jks" // 加载信任列表证书用的_tls1.3
#trust-store = "jks/mytrust" // ssl用的_ca
trust-store-mm = "jks/mytruststore.jks" // 加载信任列表证书用的_origin
key-store-password = "123"
key-password = "123"
trust-store-password = "changeme" // 加载信任列表证书用的_tls1.3
#trust-store-password = "changeit" // ssl用的_ca
trust-store-password-mm = "changeme" // 加载信任列表证书用的_origin
protocol = "TLSv1.3"
enabled-algorithms = [TLS_AES_128_GCM_SHA256]
require-mutual-authentication = on
random-number-generator = "SecureRandom"
}
}
artery {
# Disable artery with this flag
enabled = on
# Select the underlying transport implementation.
# Possible values: aeron-udp, tcp, tls-tcp
transport = tls-tcp
#log-received-messages = on
#log-sent-messages = on
advanced {
# Maximum serialized message size, including header data.
maximum-frame-size = 1024 KiB
# Direct byte buffers are reused in a pool with this maximum size.
# Each buffer has the size of 'maximum-frame-size'.
# This is not a hard upper limit on number of created buffers. Additional
# buffers will be created if needed, e.g. when using many outbound
# associations at the same time. Such additional buffers will be garbage
# collected, which is not as efficient as reusing buffers in the pool.
buffer-pool-size = 512
# Maximum serialized message size for the large messages, including header data.
# It is currently restricted to 1/8th the size of a term buffer that can be
# configured by setting the 'aeron.term.buffer.length' system property.
# See 'large-message-destinations'.
maximum-large-frame-size = 4 MiB
# Direct byte buffers for the large messages are reused in a pool with this maximum size.
# Each buffer has the size of 'maximum-large-frame-size'.
# See 'large-message-destinations'.
# This is not a hard upper limit on number of created buffers. Additional
# buffers will be created if needed, e.g. when using many outbound
# associations at the same time. Such additional buffers will be garbage
# collected, which is not as efficient as reusing buffers in the pool.
large-buffer-pool-size = 64
outbound-message-queue-size = 30720
#inbound-lanes = 1
#outbound-lanes = 1
}
# SSL configuration that is used when transport=tls-tcp.
ssl {
# Factory of SSLEngine.
# Must implement akka.remote.artery.tcp.SSLEngineProvider and have a public
# constructor with an ActorSystem parameter.
# The default ConfigSSLEngineProvider is configured by properties in section
# akka.remote.artery.ssl.config-ssl-engine
ssl-engine-provider = akka.remote.artery.tcp.ConfigSSLEngineProvider
# Config of akka.remote.artery.tcp.ConfigSSLEngineProvider
config-ssl-engine {
base-path = "jks/"
key-store = "jks/121000005l35120456.node1.jks"
trust-store = "jks/mytruststore.jks" // 加载信任列表证书用的_tls1.3
#trust-store = "jks/mytrust" // ssl用的_ca
trust-store-mm = "jks/mytruststore.jks" // 加载信任列表证书用的_origin
key-store-password = "123"
key-password = "123"
trust-store-password = "changeme" // 加载信任列表证书用的_tls1.3
#trust-store-password = "changeit" // ssl用的_ca
trust-store-password-mm = "changeme" // 加载信任列表证书用的_origin
protocol = "TLSv1.2"
#enabled-algorithms = [TLS_AES_128_GCM_SHA256]
enabled-algorithms = [TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256]
#require-mutual-authentication = on
random-number-generator = "SecureRandom"
# Require mutual authentication between TLS peers
#
# Without mutual authentication only the peer that actively establishes a connection (TLS client side)
# checks if the passive side (TLS server side) sends over a trusted certificate. With the flag turned on,
# the passive side will also request and verify a certificate from the connecting peer.
#
# To prevent man-in-the-middle attacks this setting is enabled by default.
require-mutual-authentication = on
# Set this to `on` to verify hostnames with sun.security.util.HostnameChecker
hostname-verification = off
}
}
}
}
//创世块
genesisblock {
creationBlockTime = 1495451252086
}
}

View File

@ -26,12 +26,11 @@ import io.swagger.models.{ExternalDocs, Scheme, Swagger, Tag}
import io.swagger.models.auth.BasicAuthDefinition
/**集成Swagger到AKKA HTTP
* @author c4w
* @constructor 创建提供Swagger文档服务的实例
* @param system 传入的AKKA系统实例
* @author zyf
* @since 1.0
*
* @author c4w
* @constructor 创建提供Swagger文档服务的实例
* @author zyf
* @since 1.0
*
*/
object SwaggerDocService extends SwaggerHttpService {
override val apiClasses: Set[Class[_]] = Set(
@ -45,9 +44,9 @@ object SwaggerDocService extends SwaggerHttpService {
title = "RepChain",
license = Some(License("Apache 2.0","http://www.apache.org/licenses/LICENSE-2.0.html")))
/**
* 重写swaggerConfig加上tag描述信息
* @author zyf
*/
* 重写swaggerConfig加上tag描述信息
* @author zyf
*/
val tagList = new ArrayList[Tag]()
tagList.add(new Tag().name("logmgr").description("日志信息管理"))
tagList.add(new Tag().name("chaininfo").description("获得当前区块链信息"))
@ -56,7 +55,7 @@ object SwaggerDocService extends SwaggerHttpService {
override val externalDocs = Some(new ExternalDocs("Developers Guide", "https://repchaindoc.readthedocs.io/zh/latest/index.html"))
override val securitySchemeDefinitions = Map("basicAuth" -> new BasicAuthDefinition())
override val swaggerConfig = super.swaggerConfig.tags(tagList)
// new Swagger().basePath(prependSlashIfNecessary(basePath)).info(info)
// .scheme(Scheme.HTTP).tags(tagList).securityDefinition("basicAuth", new BasicAuthDefinition())
// .externalDocs(new ExternalDocs("Developers Guide", "https://repchaindoc.readthedocs.io/zh/latest/index.html"))
// new Swagger().basePath(prependSlashIfNecessary(basePath)).info(info)
// .scheme(Scheme.HTTP).tags(tagList).securityDefinition("basicAuth", new BasicAuthDefinition())
// .externalDocs(new ExternalDocs("Developers Guide", "https://repchaindoc.readthedocs.io/zh/latest/index.html"))
}

View File

@ -17,7 +17,6 @@
package rep.api.rest
import akka.actor.Actor
import akka.util.Timeout
import rep.network._
@ -28,7 +27,7 @@ import scala.concurrent._
import rep.protos.peer._
import rep.crypto._
import rep.sc.Shim._
import rep.network.PeerHelper._
import rep.network.autotransaction.PeerHelper._
import rep.storage._
import spray.json._
import scalapb.json4s.JsonFormat
@ -37,36 +36,51 @@ import org.json4s._
import org.json4s.jackson.JsonMethods
import rep.network.tools.PeerExtension
import rep.network.base.ModuleBase
import rep.utils.GlobalUtils.ActorType
import rep.network.module.ModuleActorType
import akka.actor.Props
import rep.crypto.cert.SignTool
import rep.protos.peer.ActionResult
import rep.app.conf.SystemProfile
import rep.log.RepLogger
import rep.network.autotransaction.PeerHelper
import rep.network.base.ModuleBase
import rep.network.consensus.byzantium.ConsensusCondition
import rep.sc.TypeOfSender
import rep.sc.SandboxDispatcher.DoTransaction
import rep.sc.Sandbox.DoTransactionResult
import rep.utils.GlobalUtils.EventType
/**
* RestActor伴生object包含可接受的传入消息定义以及处理的返回结果定义
* 以及用于建立Tranaction检索Tranaction的静态方法
* @author c4w created
*
*/
* RestActor伴生object包含可接受的传入消息定义以及处理的返回结果定义
* 以及用于建立Tranaction检索Tranaction的静态方法
* @author c4w created
*
*/
object RestActor {
def props(name: String): Props = Props(classOf[RestActor], name)
val contractOperationMode = SystemProfile.getContractOperationMode
case object ChainInfo
case object NodeNumber
case object TransNumber
case object AcceptedTransNumber
case class SystemStart(cout: Int)
case class SystemStop(from: Int, to: Int)
case class BlockId(bid: String)
case class BlockHeight(h: Int)
case class BlockTime(createTime: String, createTimeUtc: String)
case class BlockTimeForHeight(h: Long)
case class BlockTimeForTxid(txid: String)
case class BlockHeightStream(h: Int)
case class TransactionId(txid: String)
case class TransactionStreamId(txid: String)
case class TranInfoAndHeightId(txid: String)
case class TranInfoHeight(tranInfo: JValue, height: Long)
case class TransNumberOfBlock(height: Long)
case object LoadBlockInfo
case object IsLoadBlockInfo
case class PostResult(txid: String, result: Option[ActionResult], err: Option[String])
case class QueryResult(result: Option[JValue])
@ -77,41 +91,41 @@ object RestActor {
iptFunc: String, iptArgs: Seq[String], timeout: Int,
secureContext: String, code: String, ctype: Int) */
case class CSpec(stype: Int, chaincodename: String, chaincodeversion: Int,
iptFunc: String, iptArgs: Seq[String], timeout: Int,legal_prose:String,
iptFunc: String, iptArgs: Seq[String], timeout: Int, legal_prose: String,
code: String, ctype: Int, state: Boolean)
case class tranSign(tran: String)
/**
* 根据节点名称和chainCode定义建立交易实例
* @param nodeName 节点名称
* @param c chainCode定义
*/
* 根据节点名称和chainCode定义建立交易实例
* @param nodeName 节点名称
* @param c chainCode定义
*/
def buildTranaction(nodeName: String, c: CSpec): Transaction = {
val stype = c.stype match {
case 1 =>
Transaction.Type.CHAINCODE_DEPLOY
case 2 =>
Transaction.Type.CHAINCODE_INVOKE
case 3=>
case 3 =>
Transaction.Type.CHAINCODE_SET_STATE
case _ =>
Transaction.Type.UNDEFINED
}
val ctype = c.ctype match{
val ctype = c.ctype match {
case 2 =>
rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA
case 3 =>
case 3 =>
rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA_PARALLEL
case _ =>
rep.protos.peer.ChaincodeDeploy.CodeType.CODE_JAVASCRIPT
}
val chaincodeId = new ChaincodeId(c.chaincodename,c.chaincodeversion)
if(stype==Transaction.Type.CHAINCODE_DEPLOY){
val chaincodeId = new ChaincodeId(c.chaincodename, c.chaincodeversion)
if (stype == Transaction.Type.CHAINCODE_DEPLOY) {
PeerHelper.createTransaction4Deploy(nodeName, chaincodeId, c.code, c.legal_prose, c.timeout, ctype)
}else if(stype==Transaction.Type.CHAINCODE_INVOKE){
} else if (stype == Transaction.Type.CHAINCODE_INVOKE) {
PeerHelper.createTransaction4Invoke(nodeName, chaincodeId, c.iptFunc, c.iptArgs)
}else if (stype == Transaction.Type.CHAINCODE_SET_STATE){
} else if (stype == Transaction.Type.CHAINCODE_SET_STATE) {
PeerHelper.createTransaction4State(nodeName, chaincodeId, c.state)
} else {
null
@ -121,84 +135,142 @@ object RestActor {
}
/**
* RestActor负责处理rest api请求
*
*/
class RestActor(moduleName: String) extends ModuleBase(moduleName) {
* RestActor负责处理rest api请求
*
*/
class RestActor(moduleName: String) extends ModuleBase(moduleName) {
import RestActor._
import spray.json._
import akka.http.scaladsl.model.{HttpResponse, MediaTypes,HttpEntity}
import akka.http.scaladsl.model.{ HttpResponse, MediaTypes, HttpEntity }
import rep.network.autotransaction.Topic
import akka.cluster.pubsub.DistributedPubSubMediator.Publish
//import rep.utils.JsonFormat.AnyJsonFormat
implicit val timeout = Timeout(1000.seconds)
val sr: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag)
// 先检查交易大小然后再检查交易是否已存在再去验证签名如果没有问题则广播
def preTransaction(t:Transaction) : Unit ={
val tranLimitSize = SystemProfile.getBlockLength/3
/*def preTransaction(t: Transaction): Unit = {
val tranLimitSize = SystemProfile.getBlockLength / 3
if (t.toByteArray.length > tranLimitSize) {
sender ! PostResult(t.id, None, Option(s"交易大小超出限制: ${tranLimitSize},请重新检查"))
}
val sig = t.signature.get.signature.toByteArray
val tOutSig = t.clearSignature
val certId = t.signature.get.certId.get
try{
sr.getTransDataByTxId(t.id) match {
case st: Some[Transaction] =>
sender ! PostResult(t.id, None, Option(s"transactionId is exists, the transaction is \n ${JsonFormat.toJson(st.get)}"))
case None =>
if (SignTool.verify(sig, tOutSig.toByteArray, certId,pe.getSysTag)) {
val future = pe.getActorRef(ActorType.transactiondispatcher) ? DoTransaction(t, "api_" + t.id,TypeOfSender.FromAPI)
val result = Await.result(future, timeout.duration).asInstanceOf[DoTransactionResult]
val rv = result
// 释放存储实例
ImpDataPreloadMgr.Free(pe.getSysTag,t.id)
rv.err match {
case None =>
//预执行正常,提交并广播交易
pe.getActorRef(ActorType.transactionpool) ! t // 给交易池发送消息 =告知getActorRef
if (rv.r == null)
sender ! PostResult(t.id, None, None)
else
sender ! PostResult(t.id, Some(rv.r), None) // legal_prose need
case Some(err) =>
//预执行异常,废弃交易向api调用者发送异常
sender ! PostResult(t.id, None, Option(err.cause.getMessage))
}
if (ConsensusCondition.CheckWorkConditionOfSystem(pe.getNodeMgr.getStableNodes.size)) {
sender ! PostResult(t.id, None, Option("共识节点数目太少,暂时无法处理交易"))
}
/*if (pe.getTransPoolMgr.findTrans(t.id) || sr.isExistTrans4Txid(t.id)) {
sender ! PostResult(t.id, None, Option(s"transactionId is exists, the transaction is \n ${t.id}"))
}*/
try {
if (SystemProfile.getHasPreloadTransOfApi) {
val sig = t.signature.get.signature.toByteArray
val tOutSig = t.clearSignature
val certId = t.signature.get.certId.get
if (pe.getTransPoolMgr.findTrans(t.id) || sr.isExistTrans4Txid(t.id)) {
sender ! PostResult(t.id, None, Option(s"transactionId is exists, the transaction is \n ${t.id}"))
} else {
if (SignTool.verify(sig, tOutSig.toByteArray, certId, pe.getSysTag)) {
// RepLogger.info(RepLogger.Business_Logger, s"验证签名成功txid: ${t.id},creditCode: ${t.signature.get.getCertId.creditCode}, certName: ${t.signature.get.getCertId.certName}")
val future = pe.getActorRef(ModuleActorType.ActorType.transactiondispatcher) ? DoTransaction(t, "api_" + t.id, TypeOfSender.FromAPI)
val result = Await.result(future, timeout.duration).asInstanceOf[DoTransactionResult]
val rv = result
// 释放存储实例
rv.err match {
case None =>
//预执行正常,提交并广播交易
pe.getActorRef(ModuleActorType.ActorType.transactionpool) ! t // 给交易池发送消息 =告知getActorRef
if (rv.r == null)
sender ! PostResult(t.id, None, None)
else
sender ! PostResult(t.id, Some(rv.r), None) // legal_prose need
case Some(err) =>
//预执行异常,废弃交易向api调用者发送异常
sender ! PostResult(t.id, None, Option(err.cause.getMessage))
}
} else {
sender ! PostResult(t.id, None, Option("验证签名出错"))
}
}
} else {
pe.getActorRef(ModuleActorType.ActorType.transactionpool) ! t // 给交易池发送消息 =告知getActorRef
sender ! PostResult(t.id, None, None)
}
}catch{
case e : RuntimeException =>
} catch {
case e: RuntimeException =>
sender ! PostResult(t.id, None, Option(e.getMessage))
} finally {
ImpDataPreloadMgr.Free(pe.getSysTag, "api_" + t.id)
}
}*/
// 先检查交易大小然后再检查交易是否已存在再去验证签名如果没有问题则广播
def preTransaction(t: Transaction): Unit = {
val tranLimitSize = SystemProfile.getBlockLength / 3
if (t.toByteArray.length > tranLimitSize) {
sender ! PostResult(t.id, None, Option(s"交易大小超出限制: ${tranLimitSize},请重新检查"))
} else if (!ConsensusCondition.CheckWorkConditionOfSystem(pe.getNodeMgr.getStableNodes.size)) {
sender ! PostResult(t.id, None, Option("共识节点数目太少,暂时无法处理交易"))
} else {
try {
if (SystemProfile.getHasPreloadTransOfApi) {
val sig = t.signature.get.signature.toByteArray
val tOutSig = t.clearSignature
val certId = t.signature.get.certId.get
if (SignTool.verify(sig, tOutSig.toByteArray, certId, pe.getSysTag)) {
mediator ! Publish(Topic.Transaction, t)
//广播发送交易事件
sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION)
sender ! PostResult(t.id, None, None)
} else {
sender ! PostResult(t.id, None, Option("验证签名出错"))
}
} else {
mediator ! Publish(Topic.Transaction, t) // 给交易池发送消息 =告知getActorRef
//广播发送交易事件
sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION)
sender ! PostResult(t.id, None, None)
}
} catch {
case e: RuntimeException =>
sender ! PostResult(t.id, None, Option(e.getMessage))
} finally {
ImpDataPreloadMgr.Free(pe.getSysTag, "api_" + t.id)
}
}
}
def receive: Receive = {
case tranSign(tr: String) =>
val tmpstart = System.currentTimeMillis()
val tr1 = BytesHex.hex2bytes(tr) // 解析交易编码后的16进制字符串,进行解码16进制反解码decode
var txr = Transaction.defaultInstance
try {
txr = Transaction.parseFrom(tr1)
preTransaction(txr)
} catch {
case e:Exception =>
case e: Exception =>
sender ! PostResult(txr.id, None, Option(s"transaction parser error! + ${e.getMessage}"))
}
val tmpend = System.currentTimeMillis()
RepLogger.trace(RepLogger.OutputTime_Logger, this.getLogMsgPrefix(s"API recv trans time,thread-id=${Thread.currentThread().getName + "-" + Thread.currentThread().getId},spent time=${(tmpend - tmpstart)}" + "~" + selfAddr))
//处理post CSpec构造交易的请求
case c: CSpec =>
var txr = Transaction.defaultInstance
//debug状态才动用节点密钥签名
if(contractOperationMode==0){
if (contractOperationMode == 0) {
//构建transaction并通过peer预执行广播
txr = buildTranaction(pe.getSysTag, c)
preTransaction(txr)
}else
} else
sender ! PostResult(txr.id, None, Option("非Debug状态下此调用无效"))
// 流式提交交易
@ -223,9 +295,6 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
}
sender ! r
// 根据高度检索块
case BlockHeight(h) =>
val bb = sr.getBlockByHeight(h)
@ -237,11 +306,29 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
}
sender ! r
case BlockTimeForHeight(h) =>
val bb = sr.getBlockTimeOfHeight(h)
val r = bb match {
case null => QueryResult(None)
case _ =>
QueryResult(Option(JsonMethods.parse(bb)))
}
sender ! r
case BlockTimeForTxid(txid) =>
val bb = sr.getBlockTimeOfTxid(txid)
val r = bb match {
case null => QueryResult(None)
case _ =>
QueryResult(Option(JsonMethods.parse(bb)))
}
sender ! r
// 根据高度检索块的子节流
case BlockHeightStream(h) =>
val bb = sr.getBlockByHeight(h)
if (bb == null) {
sender ! HttpResponse(entity = HttpEntity.Strict(MediaTypes.`application/octet-stream`,akka.util.ByteString.empty))
sender ! HttpResponse(entity = HttpEntity.Strict(MediaTypes.`application/octet-stream`, akka.util.ByteString.empty))
} else {
val body = akka.util.ByteString(bb)
val entity = HttpEntity.Strict(MediaTypes.`application/octet-stream`, body)
@ -262,7 +349,7 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
// 根据txid检索交易
case TransactionId(txId) =>
var r = sr.getTransDataByTxId( txId) match {
var r = sr.getTransDataByTxId(txId) match {
case None =>
QueryResult(None)
case t: Some[Transaction] =>
@ -270,12 +357,11 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
}
sender ! r
// 根据txid检索交易字节流
case TransactionStreamId(txId) =>
val r = sr.getTransDataByTxId( txId)
val r = sr.getTransDataByTxId(txId)
if (r.isEmpty) {
sender ! HttpResponse(entity = HttpEntity.Strict(MediaTypes.`application/octet-stream`,akka.util.ByteString.empty))
sender ! HttpResponse(entity = HttpEntity.Strict(MediaTypes.`application/octet-stream`, akka.util.ByteString.empty))
} else {
val t = r.get
val body = akka.util.ByteString(t.toByteArray)
@ -284,10 +370,51 @@ class RestActor(moduleName: String) extends ModuleBase(moduleName) {
sender ! httpResponse
}
case TranInfoAndHeightId(txId) =>
implicit val fomats = DefaultFormats
var r = sr.getTransDataByTxId(txId) match {
case None =>
QueryResult(None)
case t: Some[Transaction] =>
val txr = t.get
val tranInfoHeight = TranInfoHeight(JsonFormat.toJson(txr), sr.getBlockIdxByTxid(txr.id).getBlockHeight())
QueryResult(Option(Extraction.decompose(tranInfoHeight)))
}
sender ! r
// 获取链信息
case ChainInfo =>
val cij = JsonFormat.toJson(sr.getBlockChainInfo)
sender ! QueryResult(Option(cij))
case NodeNumber =>
val stablenode = pe.getNodeMgr.getStableNodes.size
val snode = pe.getNodeMgr.getNodes.size
val rs = "{\"consensusnodes\":\"" + stablenode + "\",\"nodes\":\"" + snode + "\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
case TransNumber =>
val num = pe.getTransPoolMgr.getTransLength()
val rs = "{\"numberofcache\":\"" + num + "\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
case AcceptedTransNumber =>
val num = sr.getBlockChainInfo.totalTransactions + pe.getTransPoolMgr.getTransLength()
val rs = "{\"acceptedNumber\":\"" + num + "\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
case TransNumberOfBlock(h) =>
val num = sr.getNumberOfTransInBlockByHeight(h)
val rs = "{\"transnumberofblock\":\"" + num + "\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
case LoadBlockInfo =>
sr.loadBlockInfoToCache
val rs = "{\"startup\":\"" + "true" + "\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
case IsLoadBlockInfo =>
val num = sr.isFinish
val rs = "{\"isfinish\":\"" + num + "\"}"
sender ! QueryResult(Option(JsonMethods.parse(string2JsonInput(rs))))
}
}

View File

@ -0,0 +1,25 @@
package rep.api.rest
import java.util.concurrent.atomic.AtomicLong
import akka.actor.{ActorRef, ActorSystem}
class RestRouter(ActorNumber:Int,system: ActorSystem) {
private var ras: Array[ActorRef] = new Array[ActorRef](ActorNumber)
private val nextActor : AtomicLong = new AtomicLong(0)
CreateActor
private def CreateActor={
for (i <- 0 to ActorNumber - 1) {
var ra = system.actorOf(RestActor.props("api_" + i), "api_"+i)
ras(i) = ra
}
}
def getRestActor:ActorRef={
val size = ras.length
val index = (nextActor.getAndIncrement % size).asInstanceOf[Int]
ras(if (index < 0) size + index else index)
}
}

View File

@ -1,279 +1,488 @@
/*
* 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.api.rest
import scala.concurrent.{ ExecutionContext, Future }
import akka.actor.{ ActorRef, ActorSelection }
import akka.util.Timeout
import akka.http.scaladsl.model.Uri.Path.Segment
import akka.http.scaladsl.server.Directives
import io.swagger.annotations._
import javax.ws.rs.Path
import akka.http.scaladsl.model._
import akka.http.scaladsl.server._
import StatusCodes._
import Directives._
import rep.sc.Sandbox.SandboxException
import rep.sc.Sandbox._
import rep.sc.Shim._
import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import rep.protos.peer._
import rep.api.rest.RestActor._
import spray.json.DefaultJsonProtocol._
import org.json4s.{ DefaultFormats, Formats, jackson }
import akka.http.scaladsl.server.Directives
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json._
import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport
import akka.http.scaladsl.model.{ContentTypes, HttpCharsets, MediaTypes}
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import scala.xml.NodeSeq
/** 获得区块链的概要信息
* @author c4w
*/
@Api(value = "/chaininfo", description = "获得当前区块链信息", produces = "application/json")
@Path("chaininfo")
class ChainService(ra: ActorRef)(implicit executionContext: ExecutionContext)
extends Directives {
import akka.pattern.ask
import scala.concurrent.duration._
import Json4sSupport._
implicit val serialization = jackson.Serialization // or native.Serialization
implicit val formats = DefaultFormats
implicit val timeout = Timeout(20.seconds)
val route = getBlockChainInfo
@ApiOperation(value = "返回块链信息", notes = "", nickname = "getChainInfo", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回块链信息", response = classOf[QueryResult])))
def getBlockChainInfo =
path("chaininfo") {
get {
complete { (ra ? ChainInfo).mapTo[QueryResult] }
}
}
}
/** 获得指定区块的详细信息
* @author c4w
*/
@Api(value = "/block", description = "获得区块数据", produces = "application/json")
@Path("block")
class BlockService(ra: ActorRef)(implicit executionContext: ExecutionContext)
extends Directives {
import akka.pattern.ask
import scala.concurrent.duration._
implicit val timeout = Timeout(20.seconds)
import Json4sSupport._
implicit val serialization = jackson.Serialization // or native.Serialization
implicit val formats = DefaultFormats
val route = getBlockById ~ getBlockByHeight ~ getBlockStreamByHeight
@Path("/hash/{blockId}")
@ApiOperation(value = "返回指定id的区块", notes = "", nickname = "getBlockById", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "blockId", value = "区块id", required = true, dataType = "string", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回区块json内容", response = classOf[QueryResult])))
def getBlockById =
path("block" / "hash" / Segment) { blockId =>
get {
complete { (ra ? BlockId(blockId)).mapTo[QueryResult] }
}
}
@Path("/{blockHeight}")
@ApiOperation(value = "返回指定高度的区块", notes = "", nickname = "getBlockByHeight", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "blockHeight", value = "区块高度", required = true, dataType = "int", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回区块json内容", response = classOf[QueryResult])))
def getBlockByHeight =
path("block" / Segment) { blockHeight =>
get {
complete { (ra ? BlockHeight(blockHeight.toInt)).mapTo[QueryResult] }
}
}
@Path("/stream/{blockHeight}")
@ApiOperation(value = "返回指定高度的区块字节流", notes = "", nickname = "getBlockStreamByHeight", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "blockHeight", value = "区块高度", required = true, dataType = "int", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "blockbytes")))
def getBlockStreamByHeight =
path("block" / "stream" /Segment) { blockHeight =>
get {
complete( (ra ? BlockHeightStream(blockHeight.toInt)).mapTo[HttpResponse])
}
}
}
/** 获得指定交易的详细信息,提交签名交易
* @author c4w
*/
@Api(value = "/transaction", description = "获得交易数据", consumes = "application/json,application/xml", produces = "application/json,application/xml")
@Path("transaction")
class TransactionService(ra: ActorRef)(implicit executionContext: ExecutionContext)
extends Directives {
import akka.pattern.ask
import scala.concurrent.duration._
import java.io.FileInputStream
implicit val timeout = Timeout(20.seconds)
import Json4sSupport._
import ScalaXmlSupport._
import akka.stream.scaladsl.FileIO
import akka.util.ByteString
import java.nio.file.{Paths, Files}
import akka.stream.scaladsl.Framing
implicit val serialization = jackson.Serialization // or native.Serialization
implicit val formats = DefaultFormats
implicit val specFormat = jsonFormat10(CSpec)
implicit val specUnmarshaller: FromEntityUnmarshaller[CSpec] = Unmarshaller.firstOf(
//只能处理application/xml
nodeSeqUnmarshaller(MediaTypes.`application/xml` withCharset HttpCharsets.`UTF-8`) map {
case NodeSeq.Empty =>
throw Unmarshaller.NoContentException
case x =>
CSpec(
(x \ "stype").text.toInt,
(x \ "chaincodename").text,
(x \ "chaincodeversion").text.toInt,
(x \ "iptFunc").text,
Seq((x \ "iptArgs").text),
(x \ "timeout").text.toInt,
(x \ "legal_prose").text,
(x \ "code").text,
(x \ "ctype").text.toInt,
(x \ "state").text.toBoolean
)
},
//只能处理application/json
unmarshaller[CSpec].forContentTypes(MediaTypes.`application/json`)
)
val route = getTransaction ~ getTransactionStream ~ postSignTransaction ~ postTransaction ~ postSignTransactionStream
@Path("/{transactionId}")
@ApiOperation(value = "返回指定id的交易", notes = "", nickname = "getTransaction", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "transactionId", value = "交易id", required = false, dataType = "string", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易json内容", response = classOf[QueryResult])))
def getTransaction =
path("transaction" / Segment) { transactionId =>
get {
complete { (ra ? TransactionId(transactionId)).mapTo[QueryResult] }
}
}
@Path("/stream/{transactionId}")
@ApiOperation(value = "返回指定id的交易字节流", notes = "", nickname = "getTransactionStream", httpMethod = "GET", produces = "application/octet-stream")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "transactionId", value = "交易id", required = false, dataType = "string", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易字节流", response = classOf[QueryResult])))
def getTransactionStream =
path("transaction" /"stream"/ Segment) { transactionId =>
get {
complete( (ra ? TransactionStreamId(transactionId)).mapTo[HttpResponse])
}
}
//以十六进制字符串提交签名交易
@Path("/postTranByString")
@ApiOperation(value = "提交带签名的交易", notes = "", nickname = "postSignTransaction", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "body", value = "交易内容", required = true, dataType = "string", paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易id以及执行结果", response = classOf[PostResult]),
new ApiResponse(code = 202, message = "处理存在异常", response = classOf[PostResult])))
def postSignTransaction =
path("transaction" / "postTranByString") {
post {
entity(as[String]) { trans =>
complete { (ra ? tranSign(trans)).mapTo[PostResult] }
}
}
}
//以字节流提交签名交易
@Path("/postTranStream")
@ApiOperation(value = "提交带签名的交易字节流", notes = "", consumes = "multipart/form-data", nickname = "postSignTransactionStream", httpMethod = "POST")
@ApiImplicitParams(Array(
// new ApiImplicitParam(name = "signer", value = "签名者", required = true, dataType = "string", paramType = "formData"),
new ApiImplicitParam(name = "signedTrans", value = "交易内容", required = true, dataType = "file", paramType = "formData")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易id以及执行结果", response = classOf[PostResult]),
new ApiResponse(code = 202, message = "处理存在异常", response = classOf[PostResult])))
def postSignTransactionStream =
path("transaction" / "postTranStream") {
post {
extractRequestContext { ctx =>
implicit val materializer = ctx.materializer
fileUpload("signedTrans") {
case (fileInfo, fileStream) =>
val fp = Paths.get("/tmp") resolve fileInfo.fileName
val sink = FileIO.toPath(fp)
val writeResult = fileStream.runWith(sink)
onSuccess(writeResult) { result =>
//TODO protobuf 反序列化字节流及后续处理
complete(s"Successfully written ${result.count} bytes")
complete { (ra ? Transaction.parseFrom(new FileInputStream(fp.toFile()))).mapTo[PostResult] }
}
}
}
}
}
@Path("/postTran")
@ApiOperation(value = "提交交易", notes = "", nickname = "postTransaction", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "body", value = "交易内容", required = true,
dataTypeClass = classOf[CSpec], paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易id以及执行结果", response = classOf[PostResult]),
new ApiResponse(code = 202, message = "处理存在异常", response = classOf[PostResult])))
def postTransaction =
path("transaction" / "postTran") {
post {
import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._
entity(as[CSpec]) { request =>
complete { (ra ? request).mapTo[PostResult] }
}
}
}
/*
* 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.api.rest
import java.util.concurrent.atomic.{AtomicInteger, AtomicLong}
import scala.concurrent.{ExecutionContext, Future}
import akka.actor.{ActorRef, ActorSelection}
import akka.util.Timeout
import akka.http.scaladsl.model.Uri.Path.Segment
import akka.http.scaladsl.server.Directives
import io.swagger.annotations._
import javax.ws.rs.Path
import akka.http.scaladsl.model._
import akka.http.scaladsl.server._
import StatusCodes._
import Directives._
import rep.sc.Sandbox.SandboxException
import rep.sc.Sandbox._
import rep.sc.Shim._
import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import rep.protos.peer._
import rep.api.rest.RestActor._
import spray.json.DefaultJsonProtocol._
import org.json4s.{DefaultFormats, Formats, jackson}
import akka.http.scaladsl.server.Directives
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json._
import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport
import akka.http.scaladsl.model.{ContentTypes, HttpCharsets, MediaTypes}
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import akka.stream.scaladsl.StreamConverters
import scala.xml.NodeSeq
import rep.log.RepLogger
/**
* 获得区块链的概要信息
*
* @author c4w
*/
@Api(value = "/chaininfo", description = "获得当前区块链信息", produces = "application/json")
@Path("chaininfo")
class ChainService(ra: RestRouter)(implicit executionContext: ExecutionContext)
extends Directives {
import akka.pattern.ask
import scala.concurrent.duration._
import Json4sSupport._
implicit val serialization = jackson.Serialization // or native.Serialization
implicit val formats = DefaultFormats
implicit val timeout = Timeout(20.seconds)
val route = getBlockChainInfo ~ getNodeNumber ~ getCacheTransNumber ~ getAcceptedTransNumber ~ loadBlockInfoToCache ~ IsLoadBlockInfoToCache
@ApiOperation(value = "返回块链信息", notes = "", nickname = "getChainInfo", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回块链信息", response = classOf[QueryResult])))
def getBlockChainInfo =
path("chaininfo") {
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get chaininfo")
complete { (ra.getRestActor ? ChainInfo).mapTo[QueryResult] }
}
}
}
@Path("/node")
@ApiOperation(value = "返回组网节点数量", notes = "", nickname = "getNodeNumber", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回组网节点数量", response = classOf[QueryResult])))
def getNodeNumber =
path("chaininfo" / "node") {
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get node number")
complete { (ra.getRestActor ? NodeNumber).mapTo[QueryResult] }
}
}
}
@Path("/loadBlockInfoToCache")
@ApiOperation(value = "初始化装载区块索引到缓存", notes = "", nickname = "loadBlockInfoToCache", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "初始化装载区块索引到缓存量", response = classOf[QueryResult])))
def loadBlockInfoToCache =
path("chaininfo" / "loadBlockInfoToCache") {
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get loadBlockInfoToCache")
complete { (ra.getRestActor ? LoadBlockInfo).mapTo[QueryResult] }
}
}
}
@Path("/IsLoadBlockInfoToCache")
@ApiOperation(value = "是否完成始化装载区块索引到缓存", notes = "", nickname = "IsLoadBlockInfoToCache", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "是否完成初始化装载区块索引到缓存量", response = classOf[QueryResult])))
def IsLoadBlockInfoToCache =
path("chaininfo" / "IsLoadBlockInfoToCache") {
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get IsLoadBlockInfoToCache")
complete { (ra.getRestActor ? IsLoadBlockInfo).mapTo[QueryResult] }
}
}
}
@Path("/getcachetransnumber")
@ApiOperation(value = "返回系统缓存交易数量", notes = "", nickname = "getCacheTransNumber", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回系统缓存交易数量", response = classOf[QueryResult])))
def getCacheTransNumber =
path("chaininfo" / "getcachetransnumber") {
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get number of cache")
complete { (ra.getRestActor ? TransNumber).mapTo[QueryResult] }
}
}
}
@Path("/getAcceptedTransNumber")
@ApiOperation(value = "返回系统接收到的交易数量", notes = "", nickname = "getAcceptedTransNumber", httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回系统接收到的交易数量", response = classOf[QueryResult])))
def getAcceptedTransNumber =
path("chaininfo" / "getAcceptedTransNumber") {
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get number of accepted")
complete {
(ra.getRestActor ? AcceptedTransNumber).mapTo[QueryResult]
}
}
}
}
}
/**
* 获得指定区块的详细信息
*
* @author c4w
*/
@Api(value = "/block", description = "获得区块数据", produces = "application/json")
@Path("block")
class BlockService(ra: RestRouter)(implicit executionContext: ExecutionContext)
extends Directives {
import akka.pattern.ask
import scala.concurrent.duration._
implicit val timeout = Timeout(20.seconds)
import Json4sSupport._
implicit val serialization = jackson.Serialization // or native.Serialization
implicit val formats = DefaultFormats
val route = getBlockById ~ getBlockByHeight ~ getBlockByHeightToo ~ getTransNumberOfBlock ~ getBlockStreamByHeight ~ getBlockTimeOfCreate ~ getBlockTimeOfTxrByTxid ~ getBlockTimeOfTransaction
@Path("/hash/{blockId}")
@ApiOperation(value = "返回指定id的区块", notes = "", nickname = "getBlockById", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "blockId", value = "区块id", required = true, dataType = "string", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回区块json内容", response = classOf[QueryResult])))
def getBlockById =
path("block" / "hash" / Segment) { blockId =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get block for id,block id=${blockId}")
complete { (ra.getRestActor ? BlockId(blockId)).mapTo[QueryResult] }
}
}
}
@Path("/{blockHeight}")
@ApiOperation(value = "返回指定高度的区块", notes = "", nickname = "getBlockByHeight", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "blockHeight", value = "区块高度", required = true, dataType = "int", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回区块json内容", response = classOf[QueryResult])))
def getBlockByHeightToo =
path("block" / Segment) { blockHeight =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get block for Height,block height=${blockHeight}")
complete { (ra.getRestActor ? BlockHeight(blockHeight.toInt)).mapTo[QueryResult] }
}
//complete { (ra ? BlockHeight(blockHeight.toInt)).mapTo[QueryResult] }
}
}
@Path("/blockHeight")
@ApiOperation(value = "返回指定高度的区块", notes = "", nickname = "getBlockByHeight", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "height", value = "区块高度", required = true, dataType = "String", paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回区块json内容", response = classOf[QueryResult])))
def getBlockByHeight =
path("block" / "blockHeight") {
post {
entity(as[Map[String, Int]]) { blockQuery =>
complete {
(ra.getRestActor ? BlockHeight(blockQuery("height"))).mapTo[QueryResult]
}
}
}
}
@Path("/getTransNumberOfBlock")
@ApiOperation(value = "返回指定高度区块包含的交易数", notes = "", nickname = "getTransNumberOfBlock", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "height", value = "区块高度", required = true, dataType = "String", paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回指定高度区块包含的交易数", response = classOf[QueryResult])))
def getTransNumberOfBlock =
path("block" / "getTransNumberOfBlock") {
post {
entity(as[Map[String, Long]]) { blockQuery =>
complete {
(ra.getRestActor ? TransNumberOfBlock(blockQuery("height"))).mapTo[QueryResult]
}
}
}
}
@Path("/blocktime/{blockHeight}")
@ApiOperation(value = "返回指定高度的区块的出块时间", notes = "", nickname = "getBlockTimeOfCreate", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "blockHeight", value = "区块高度", required = true, dataType = "long", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回指定高度的区块的出块时间", response = classOf[QueryResult])))
def getBlockTimeOfCreate =
path("block" / "blocktime" / Segment) { blockHeight =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get block time for Height,block height=${blockHeight}")
complete { (ra.getRestActor ? BlockTimeForHeight(blockHeight.toLong)).mapTo[QueryResult] }
}
//complete { (ra ? BlockHeight(blockHeight.toInt)).mapTo[QueryResult] }
}
}
@Path("/blocktimeoftran/{transid}")
@ApiOperation(value = "返回指定交易的入块时间", notes = "", nickname = "getBlockTimeOfTransaction", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "transid", value = "交易id", required = true, dataType = "String", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回指定交易的入块时间", response = classOf[QueryResult])))
def getBlockTimeOfTransaction =
path("block" / "blocktimeoftran" / Segment) { transid =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get block time for txid,txid=${transid}")
complete { (ra.getRestActor ? BlockTimeForTxid(transid)).mapTo[QueryResult] }
}
//complete { (ra ? BlockHeight(blockHeight.toInt)).mapTo[QueryResult] }
}
}
@Path("/blocktimeoftran")
@ApiOperation(value = "返回指定交易的入块时间", notes = "", nickname = "getBlockTimeOfTransaction", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "txid", value = "交易id", required = true, dataType = "String", paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回指定交易的入块时间", response = classOf[QueryResult])))
def getBlockTimeOfTxrByTxid =
path("block" / "blocktimeoftran") {
post {
entity(as[Map[String, String]]) { trans =>
complete { (ra.getRestActor ? BlockTimeForTxid(trans("txid"))).mapTo[QueryResult] }
}
}
}
@Path("/stream/{blockHeight}")
@ApiOperation(value = "返回指定高度的区块字节流", notes = "", nickname = "getBlockStreamByHeight", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "blockHeight", value = "区块高度", required = true, dataType = "int", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "blockbytes")))
def getBlockStreamByHeight =
path("block" / "stream" / Segment) { blockHeight =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get block stream for Height,block height=${blockHeight}")
complete((ra.getRestActor ? BlockHeightStream(blockHeight.toInt)).mapTo[HttpResponse])
}
}
}
}
/**
* 获得指定交易的详细信息提交签名交易
*
* @author c4w
*/
@Api(value = "/transaction", description = "获得交易数据", consumes = "application/json,application/xml", produces = "application/json,application/xml")
@Path("transaction")
class TransactionService(ra: RestRouter)(implicit executionContext: ExecutionContext)
extends Directives {
import akka.pattern.ask
import scala.concurrent.duration._
import java.io.FileInputStream
implicit val timeout = Timeout(20.seconds)
import Json4sSupport._
import ScalaXmlSupport._
import akka.stream.scaladsl.FileIO
import akka.util.ByteString
import java.nio.file.{ Paths, Files }
import akka.stream.scaladsl.Framing
implicit val serialization = jackson.Serialization // or native.Serialization
implicit val formats = DefaultFormats
implicit val specFormat = jsonFormat10(CSpec)
implicit val specUnmarshaller: FromEntityUnmarshaller[CSpec] = Unmarshaller.firstOf(
//只能处理application/xml
nodeSeqUnmarshaller(MediaTypes.`application/xml` withCharset HttpCharsets.`UTF-8`) map {
case NodeSeq.Empty =>
throw Unmarshaller.NoContentException
case x =>
CSpec(
(x \ "stype").text.toInt,
(x \ "chaincodename").text,
(x \ "chaincodeversion").text.toInt,
(x \ "iptFunc").text,
Seq((x \ "iptArgs").text),
(x \ "timeout").text.toInt,
(x \ "legal_prose").text,
(x \ "code").text,
(x \ "ctype").text.toInt,
(x \ "state").text.toBoolean)
},
//只能处理application/json
unmarshaller[CSpec].forContentTypes(MediaTypes.`application/json`))
val route = getTransaction ~ getTransactionStream ~ tranInfoAndHeightOfTranId ~ postSignTransaction ~ postTransaction ~ postSignTransactionStream
@Path("/{transactionId}")
@ApiOperation(value = "返回指定id的交易", notes = "", nickname = "getTransaction", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "transactionId", value = "交易id", required = false, dataType = "string", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易json内容", response = classOf[QueryResult])))
def getTransaction =
path("transaction" / Segment) { transactionId =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get transaction for txid,txid=${transactionId}")
complete { (ra.getRestActor ? TransactionId(transactionId)).mapTo[QueryResult] }
}
}
}
@Path("/stream/{transactionId}")
@ApiOperation(value = "返回指定id的交易字节流", notes = "", nickname = "getTransactionStream", httpMethod = "GET", produces = "application/octet-stream")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "transactionId", value = "交易id", required = false, dataType = "string", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易字节流", response = classOf[QueryResult])))
def getTransactionStream =
path("transaction" / "stream" / Segment) { transactionId =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get transaction stream for txid,txid=${transactionId}")
complete((ra.getRestActor ? TransactionStreamId(transactionId)).mapTo[HttpResponse])
}
}
}
@Path("/tranInfoAndHeight/{transactionId}")
@ApiOperation(value = "返回指定id的交易信息及所在区块高度", notes = "", nickname = "tranInfoAndHeightOfTranId", httpMethod = "GET")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "transactionId", value = "交易id", required = false, dataType = "string", paramType = "path")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回指定id的交易信息及所在区块高度", response = classOf[QueryResult])))
def tranInfoAndHeightOfTranId =
path("transaction"/"tranInfoAndHeight"/Segment) { transactionId =>
get {
extractClientIP { ip =>
RepLogger.debug(RepLogger.APIAccess_Logger, s"remoteAddr=${ip} get transactionInfo and blockHeight for txid,txid=${transactionId}")
complete((ra.getRestActor ? TranInfoAndHeightId(transactionId)).mapTo[QueryResult])
}
}
}
//以十六进制字符串提交签名交易
@Path("/postTranByString")
@ApiOperation(value = "提交带签名的交易", notes = "", nickname = "postSignTransaction", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "body", value = "交易内容", required = true, dataType = "string", paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易id以及执行结果", response = classOf[PostResult]),
new ApiResponse(code = 202, message = "处理存在异常", response = classOf[PostResult])))
def postSignTransaction =
path("transaction" / "postTranByString") {
post {
entity(as[String]) { trans =>
complete { (ra.getRestActor ? tranSign(trans)).mapTo[PostResult] }
}
}
}
//以字节流提交签名交易
@Path("/postTranStream")
@ApiOperation(value = "提交带签名的交易字节流", notes = "", consumes = "multipart/form-data", nickname = "postSignTransactionStream", httpMethod = "POST")
@ApiImplicitParams(Array(
// new ApiImplicitParam(name = "signer", value = "签名者", required = true, dataType = "string", paramType = "formData"),
new ApiImplicitParam(name = "signedTrans", value = "交易内容", required = true, dataType = "file", paramType = "formData")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易id以及执行结果", response = classOf[PostResult]),
new ApiResponse(code = 202, message = "处理存在异常", response = classOf[PostResult])))
def postSignTransactionStream =
path("transaction" / "postTranStream") {
post {
extractRequestContext { ctx =>
implicit val materializer = ctx.materializer
fileUpload("signedTrans") {
case (fileInfo, fileStream) =>
val sink = StreamConverters.asInputStream()
val inputStream = fileStream.runWith(sink)
complete { (ra.getRestActor ? Transaction.parseFrom(inputStream)).mapTo[PostResult] }
// val fp = Paths.get("/tmp") resolve fileInfo.fileName
// val sink = FileIO.toPath(fp)
// val writeResult = fileStream.runWith(sink)
// onSuccess(writeResult) { result =>
// //TODO protobuf 反序列化字节流及后续处理
// complete(s"Successfully written ${result.count} bytes")
// complete { (ra.getRestActor ? Transaction.parseFrom(new FileInputStream(fp.toFile()))).mapTo[PostResult] }
// }
}
}
}
}
@Path("/postTran")
@ApiOperation(value = "提交交易", notes = "", nickname = "postTransaction", httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "body", value = "交易内容", required = true,
dataTypeClass = classOf[CSpec], paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "返回交易id以及执行结果", response = classOf[PostResult]),
new ApiResponse(code = 202, message = "处理存在异常", response = classOf[PostResult])))
def postTransaction =
path("transaction" / "postTran") {
post {
import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._
entity(as[CSpec]) { request =>
complete { (ra.getRestActor ? request).mapTo[PostResult] }
}
}
}
}

View File

@ -0,0 +1,308 @@
package rep.app
import java.util.concurrent._
import java.util.concurrent.atomic.AtomicBoolean
import akka.actor.{ActorSystem, Address, Terminated}
import rep.app.system.ClusterSystem
import rep.app.system.ClusterSystem.InitType
import rep.network.consensus.util.BlockVerify
import akka.cluster.{Cluster, MemberStatus}
import akka.util.Timeout
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.control.Breaks.{break, breakable}
object RepChainMgr {
private var clusterAddr: Address = null //集群种子节点地址
private var instanceOfCluster = new scala.collection.mutable.HashMap[String, (ClusterSystem,Int)]()
private var isSingle = false
private var nodelist : ArrayBuffer[String] = new ArrayBuffer[String]()
private var isStarting = new AtomicBoolean(false)
def isJDK8OfRunEnv:Boolean={
var defaultvalue = false//默认未13
val javaVersion = System.getProperty("java.version").split("[+.\\-]+", 3)
if(javaVersion != null && javaVersion.length >= 2){
if(javaVersion(1) == "8"){
defaultvalue = true
}
}
defaultvalue
}
def Startups(param:Array[(String,Int)])={
param.foreach(f=>{
Startup4Multi(f._1,f._2)
Thread.sleep(2000)
})
}
def Startup4Single(SystemName:String)={
this.isSingle = true
val sys1 = new ClusterSystem(SystemName, InitType.SINGLE_INIT,true)
sys1.init
//val joinAddress = sys1.getClusterAddr
//sys1.joinCluster(joinAddress)
if(!this.instanceOfCluster.contains(SystemName)){
this.nodelist += SystemName
}
this.instanceOfCluster += SystemName -> (sys1,0)
sys1.start
}
def Startup4Multi(SystemName:String,port:Int)={
val sys1 = new ClusterSystem(SystemName,InitType.MULTI_INIT,true)
if(this.isJDK8OfRunEnv){
sys1.init3(port)//
}else{
sys1.init2(port)//初始化参数和配置信息
}
if(this.clusterAddr == null){
this.clusterAddr = sys1.getClusterAddr//获取组网地址
sys1.enableWS()//开启API接口
}else{
sys1.disableWS()
}
//val clusterAddr = sys1.getClusterAddr
//sys1.joinCluster(clusterAddr)
/*if(this.isJDK8OfRunEnv){
sys1.joinCluster(this.clusterAddr)//加入网络
}*/
if(!this.instanceOfCluster.contains(SystemName)){
this.nodelist += SystemName
}
this.instanceOfCluster += SystemName -> (sys1,port)
sys1.start//启动系统
}
def Stop(SystemName:String)={
val sys1 = this.instanceOfCluster(SystemName)
if(sys1 != null){
val sys = sys1._1
if(sys != null){
sys.shutdown
Thread.sleep(10000)
}
}
}
def shutdown(SystemName:String)={
val sys1 = this.instanceOfCluster(SystemName)
if(sys1 != null){
val sys = sys1._1
if(sys != null){
var r = killActorSystem(sys)
if(!r){
Thread.sleep(10000)
System.err.println(s"shutdown happen error,again shutdown,systemname=${SystemName}")
killActorSystem(sys)
}
}
}
}
def killActorSystem(sys:ClusterSystem):Boolean={
var r :Boolean = false
try{
r = sys.terminateOfSystem
}catch{
case e1:Exception => e1.printStackTrace()
}
r
}
import scala.concurrent._
private def isUpOfClusterForChecked(cluster: Cluster): Boolean = {
implicit val timeout = Timeout(120.seconds)
val result = Future.successful(cluster.selfMember.status == MemberStatus.Up)
val result1 = Await.result(result, timeout.duration).asInstanceOf[Boolean]
result1
}
private def isFinishOfStartupForChecked(clusterSystem: ClusterSystem): Boolean = {
var r = false
val cluster = clusterSystem.getClusterInstance
if(cluster != null ){
breakable {
//持续6min检查自己是否UP每次检查的超时时间为120s检查3次
for(i <-1 to 3){
if(isUpOfClusterForChecked(cluster)){
r = true
break
}
}
}
}
r
}
private def processOfRestart(systemName:String):Boolean={
var r = false
try{
System.err.println(s"shutdown start time=${System.currentTimeMillis()}")
var r = shutdown(systemName)
System.err.println(s"shutdown end time=${System.currentTimeMillis()}")
Thread.sleep(5000)
System.err.println(s"terminateOfSystem finished,systemName=${systemName}")
if(isSingle){
Startup4Single(systemName)
}else{
val sys1 = instanceOfCluster(systemName)
if(sys1 != null){
val port = sys1._2
Startup4Multi(systemName,port)
}
}
Thread.sleep(5000)
r = isFinishOfStartupForChecked(instanceOfCluster(systemName)._1)
}catch{
case e:Exception=>e.printStackTrace()
}
r
}
//重启节点的策略是没有启动成功一直启动直到启动成功
private def RestartCulsterUtilToSuccesss(systemName:String): Unit ={
//持续6min检查自己是否UP每次检查的超时时间为120s检查3次
var r = false
isStarting.set(true)
var i = 1
while(!r){
try{
r = processOfRestart(systemName)
if(!r){
if(i > 10){
Thread.sleep(180*1000)
}else if(i > 100){
Thread.sleep(300*1000)
}else{
Thread.sleep(120*1000)
}
}
}catch{
case e:Exception => e.printStackTrace()
}
i += 1
}
isStarting.set(false)
}
val threadPool:ExecutorService=Executors.newFixedThreadPool(1)
def ReStart(SystemName:String)={
/*var scheduledExecutorService1 = Executors.newSingleThreadScheduledExecutor
try{
scheduledExecutorService1.schedule(new RestartThread(SystemName),3,TimeUnit.SECONDS)
}finally {
try{
scheduledExecutorService1.shutdown()
}catch{
case e:Exception => e.printStackTrace()
}
}*/
if(!isStarting.get()){
try {
threadPool.execute(new RestartThread(SystemName))
}catch{
case e:Exception => e.printStackTrace()
}
}
}
var scheduledExecutorService = Executors.newSingleThreadScheduledExecutor
def StartClusterStub={
/*val threadPool:ExecutorService=Executors.newFixedThreadPool(1)
try {
threadPool.execute(new ClusterTestStub)
}finally {
threadPool.shutdown()
}*/
//try{
this.scheduledExecutorService.scheduleWithFixedDelay(//).scheduleAtFixedRate(
new ClusterTestStub,100,60, TimeUnit.SECONDS
)
/*}catch {
case e:Exception =>
try{
scheduledExecutorService.shutdown()
}catch{
case e:Exception => e.printStackTrace()
}
}*/
}
class RestartThread(systemName:String) extends Runnable{
override def run(){
try{
RestartCulsterUtilToSuccesss(systemName)
/*System.err.println(s"shutdown start time=${System.currentTimeMillis()}")
var r = shutdown(systemName)
System.err.println(s"shutdown end time=${System.currentTimeMillis()}")
Thread.sleep(5000)
System.err.println(s"terminateOfSystem finished,systemName=${systemName}")
if(isSingle){
Startup4Single(systemName)
}else{
val sys1 = instanceOfCluster(systemName)
if(sys1 != null){
val port = sys1._2
Startup4Multi(systemName,port)
}
}*/
}catch{
case e:Exception=>e.printStackTrace()
}
}
}
class ClusterTestStub extends Runnable{
override def run(){
try{
//sleep 90 s
//Thread.sleep(90000)
System.err.println(s"entry terminate systemName")
if(!isStarting.get()){
if(!isSingle){
//单机模拟多节点时采用随机down某个节点
System.err.println(s"start terminate systemName")
var rd = scala.util.Random.nextInt(100)
rd = rd % 5
if(rd == 0) rd = rd + 1
var systemname = nodelist(rd)
systemname = "921000006e0012v696.node5"
RepChainMgr.Stop(systemname)
System.err.println(s"stop system,systemName=${systemname}")
}else{
//单机启动时需要做测试时启动该节点的动态停止模拟断网
System.err.println(s"start terminate systemName")
val systemname = nodelist(0)
//如果想down某个节点就在条件中注明down的节点名称例子里面down节点5
if(systemname == "921000006e0012v696.node5"){
RepChainMgr.Stop(systemname)
System.err.println(s"stop system,systemName=${systemname}")
}
}
}
}catch{
case e:Exception=>e.printStackTrace()
}
}
}
}

View File

@ -0,0 +1,83 @@
/*
* 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.app
import java.io.{File, FileFilter}
import rep.app.system.ClusterSystem
import rep.app.system.ClusterSystem.InitType
import scala.collection.mutable
/**
* RepChain启动单机超5个节点以上配合https://gitee.com/BTAJL/RCJava/blob/dev_sdk_preview/src/main/java/com/Example/cert/GenerateJksFiles.java使用
* @author zyf
*/
object RepChain_Multi {
def main(args: Array[String]): Unit = {
val fileDir = new File("jks")
// 过滤掉非节点node的jks
val files = fileDir.listFiles(new FileFilter {
override def accept(file: File): Boolean = {
val fileName = file.getName
if (fileName.endsWith("jks") && fileName.indexOf("node") != -1) {
true
} else {
false
}
}
})
val map = new mutable.HashMap[String, Int]()
for (i <- 0 until files.length) {
map.put("node".+((i + 1).toString), i)
}
//创建系统实例
val nodelist = new Array[String](files.length)
for (i <- 0 until files.length) {
nodelist(map(files(i).getName.split('.')(1))) = files(i).getName.dropRight(4)
}
val sys1 = new ClusterSystem(nodelist(0), InitType.MULTI_INIT, true)
sys1.init
//初始化参数和配置信息
val joinAddress = sys1.getClusterAddr //获取组网地址
sys1.joinCluster(joinAddress) //加入网络
sys1.enableWS() //开启API接口
sys1.start //启动系统
var nodes = Set.empty[ClusterSystem]
nodes += sys1
// 可以根据自己的需要将nodelist.length改成对应的节点数
for (i <- 1 to args(0).toInt) {
Thread.sleep(1000)
val sysN = new ClusterSystem(nodelist(i), InitType.MULTI_INIT, true)
sysN.init
//初始化参数和配置信息
sysN.joinCluster(joinAddress)
sysN.disableWS()
sysN.start
nodes += sysN
}
}
}

View File

@ -1,87 +1,90 @@
/*
* 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.app
import akka.remote.transport.Transport.InvalidAssociationException
import rep.app.system.ClusterSystem
import rep.app.system.ClusterSystem.InitType
/**
* Repchain app start
* @author c4w 2017/9/24.
*/
object Repchain {
def main(args: Array[String]): Unit = {
//创建系统实例
var nodelist : Array[String] = new Array[String] (4)
nodelist(0) = "12110107bi45jh675g.node2"
nodelist(1) = "122000002n00123567.node3"
nodelist(2) = "921000005k36123789.node4"
nodelist(3) = "921000006e0012v696.node5"
val sys1 = new ClusterSystem("121000005l35120456.node1",InitType.MULTI_INIT,true)
sys1.init//初始化参数和配置信息
val joinAddress = sys1.getClusterAddr//获取组网地址
sys1.joinCluster(joinAddress)//加入网络
sys1.enableWS()//开启API接口
sys1.start//启动系统
//val cluster = sys1.getActorSys//获取内部系统SystemActor实例
val node_min = 5
//如果node_max>node_min 将启动node反复离网和入网的仿真但是由于system离网后无法复用并重新加入
//运行一定时间会内存溢出
val node_max = 5
var node_add = true
var nodes = Set.empty[ClusterSystem]
nodes+= sys1
var nodes_off = Set.empty[ClusterSystem]
var tmpsystem : ClusterSystem = null
for(i <- 2 to node_max) {
Thread.sleep(2000)
val len = nodes.size
val sys = new ClusterSystem(nodelist(i-2),InitType.MULTI_INIT,true)
sys.init
sys.joinCluster(joinAddress)
sys.disableWS()
sys.start
nodes += sys
if(i == 5){
tmpsystem = sys
}
}
/* Thread.sleep(1000*60*3)
tmpsystem.shutdown
Thread.sleep(1000*60*2)
val sys = new ClusterSystem(nodelist(3),InitType.MULTI_INIT,true)
sys.init
sys.joinCluster(joinAddress)
sys.disableWS()
sys.start*/
}
}
/*
* 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.app
import akka.actor.ActorRef
import akka.remote.transport.Transport.InvalidAssociationException
import rep.app.system.ClusterSystem
import rep.app.system.ClusterSystem.InitType
/**
* Repchain app start
* @author c4w 2017/9/24.
* -Djavax.net.debug=ssl:handshake:verbose
*/
object Repchain {
def h4(h:String) = {
if (h.size >= 4)
h.substring(0,4)
else
h
}
def nn(s:String) = {
var r = ""
if (s.contains("121000005l35120456.node1")) r = "node1"
if (s.contains("12110107bi45jh675g.node2")) r = "node2"
if (s.contains("122000002n00123567.node3")) r = "node3"
if (s.contains("921000005k36123789.node4")) r = "node4"
if (s.contains("921000006e0012v696.node5")) r = "node5"
r
}
def nn(sender:ActorRef) = {
var r = ""
val s = sender.path.toString
if (s.contains("22522")) r = "node1"
if (s.contains("22523")) r = "node2"
if (s.contains("22524")) r = "node3"
if (s.contains("22525")) r = "node4"
if (s.contains("22526")) r = "node5"
r
}
def main(args: Array[String]): Unit = {
//创建系统实例
var nodelist : Array[String] = new Array[String] (5)
nodelist(0) = "121000005l35120456.node1"
nodelist(1) = "12110107bi45jh675g.node2"
nodelist(2) = "122000002n00123567.node3"
nodelist(3) = "921000005k36123789.node4"
nodelist(4) = "921000006e0012v696.node5"
var nodeports : Array[Int] = new Array[Int](5)
nodeports(0) = 22522
nodeports(1) = 22523
nodeports(2) = 22524
nodeports(3) = 22525
nodeports(4) = 22526
for(i <- 0 to 4) {
Thread.sleep(5000)
RepChainMgr.Startup4Multi(nodelist(i),nodeports(i))
}
//以下代码只能在测试系统稳定性即测试系统离网之后再入网时可以用发布时一定要删除
//Thread.sleep(10000)
//RepChainMgr.StartClusterStub
}
}

View File

@ -21,17 +21,18 @@ import rep.app.system.ClusterSystem
import rep.app.system.ClusterSystem.InitType
/**
* Repchain app start
* Created by User on 2017/9/24.
*/
* Repchain app start
* Created by User on 2017/9/24.
*/
object Repchain_Single {
def main(args: Array[ String ]): Unit = {
var systemTag = "1"
if(args!=null && args.length>0) systemTag = args(0)
val sys1 = new ClusterSystem(systemTag, InitType.SINGLE_INIT,true)
RepChainMgr.Startup4Single(systemTag)
/*val sys1 = new ClusterSystem(systemTag, InitType.SINGLE_INIT,true)
sys1.init
val joinAddress = sys1.getClusterAddr
sys1.joinCluster(joinAddress)
sys1.start
sys1.start*/
}
}

View File

@ -27,7 +27,7 @@ import scala.concurrent.{Await, Future}
import akka.remote.transport.Transport._
import rep.network._
import rep.network.cluster.MemberListener
import rep.network.module.{ModuleManager}
import rep.network.module.IModuleManager
import rep.ui.web.EventServer
import scala.collection.mutable._
@ -53,7 +53,7 @@ object TestMain {
nd_system.actorOf(Props[MemberListener], name_MemberListener)
//等待网络稳定
Thread.sleep(5000)
nd_system.actorOf(Props[ModuleManager], name_PeerManager + i.toString)
nd_system.actorOf(Props[IModuleManager], name_PeerManager + i.toString)
m += i -> nd_system
ma += i -> Cluster(nd_system).selfAddress
}
@ -113,7 +113,7 @@ object TestMain {
system0.actorOf(Props[MemberListener], name_MemberListener)
//等待网络稳定
Thread.sleep(5000)
val nd0 = system0.actorOf(Props[ModuleManager], name_PeerManager + "0")
val nd0 = system0.actorOf(Props[IModuleManager], name_PeerManager + "0")
val ws0 = system0.actorOf(Props[EventServer], "ws")
}
}

View File

@ -1,271 +1,329 @@
/*
* 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.app.conf
import com.typesafe.config.Config
//import collection.JavaConversions._
//import scala.collection.immutable._
import java.util.List
import java.util.ArrayList
/**
* 系统配置信息缓存对象
* @author shidianyue
* @version 0.7
* @update 2018-05 jiangbuyun
* */
object SystemProfile {
/**
* 交易创建类型
*/
case object Trans_Create_Type_Enum {
val MANUAL = 0 //API创建
val AUTO = 1 //自动创建
}
private[this] var _LIMIT_BLOCK_TRANS_NUM: Int = 0//块内最多交易数
private[this] var _MIN_BLOCK_TRANS_NUM: Int = 0//块内最少交易数
private[this] var _VOTE_NOTE_MIN: Int = 0//投票最少参与人数
private[this] var _TRAN_CREATE_DUR: Int = 0//交易创建时间间隔-针对自动创建
private[this] var _TRANS_CREATE_TYPE: Int = 0//交易创建类型
private[this] var _RETRY_TIME: Int = 0//投票重试次数限制
private[this] var _MAX_CATCH_TRANS_NUM: Int = 0//交易最多缓存数量
private[this] var _DISKSPACE_ALARM_NUM:Long=0//磁盘剩余空间预警 单位=M
private[this] var _SERVERPORT:Int=8081//http服务的端口默认为8081
private[this] var _CHECKCERTVALIDATE:Int=0//是否检查证书的有效性0不检查1检查
private[this] var _CONTRACTOPERATIONMODE = 0//设置合约的运行方式0=debug方式1=deploy默认为debug方式如果发布部署必须使用deploy方式
private[this] var _VOTENODELIST : List[String] = new ArrayList[String]
private[this] var _ACCOUNTCHAINCODENAEM : String = "ACCOUNTCHAINCODENAME"
private[this] var _ACCOUNTCHAINCODEVERSION: Int = 1
private[this] var _CertStatusChangeFunction : String = "UpdateCertStatus"
private[this] var _GENESISNODENAME:String = ""
private[this] var _BLOCK_LENGTH: Int = 120000//区块的最大长度
private[this] var _NUMBER_OF_TRANSPROCESSOR = 100 //
private[this] var _DBPATH:String = "" //leveldb数据库文件路径
private[this] var _BLOCKPATH:String = ""//区块文件的路径
private[this] var _FILEMAX: Int = 200000000//区块文件的最大长度
//实时图的事件是否发送如果不发送前端实时图将收不到任何消息
private[this] var _REALTIMEGRAPH_ENABLE = 1 ////0 unable;1 enable; default 1
private def SERVERPORT :Int = _SERVERPORT
private def CHECKCERTVALIDATE:Int = _CHECKCERTVALIDATE
private def DISKSPACE_ALARM_NUM :Long = _DISKSPACE_ALARM_NUM
private def CONTRACTOPERATIONMODE:Int=_CONTRACTOPERATIONMODE
private def GENESISNODENAME:String = _GENESISNODENAME
private def VOTENODELIST : List[String] = _VOTENODELIST
private def ACCOUNTCHAINCODENAEM = _ACCOUNTCHAINCODENAEM
private def ACCOUNTCHAINCODVERSION = _ACCOUNTCHAINCODEVERSION
private def CertStatusChangeFunction = _CertStatusChangeFunction
private def NUMBER_OF_TRANSPROCESSOR = _NUMBER_OF_TRANSPROCESSOR
private def REALTIMEGRAPH_ENABLE = _REALTIMEGRAPH_ENABLE
private def DBPATH:String = _DBPATH
private def BLOCKPATH:String = _BLOCKPATH
private def FILEMAX: Int = _FILEMAX
private def DBPATH_=(value:String):Unit={
_DBPATH = value
}
private def REALTIMEGRAPH_ENABLE_=(value:Int):Unit={
_REALTIMEGRAPH_ENABLE = value
}
private def BLOCKPATH_=(value:String):Unit={
_BLOCKPATH = value
}
private def FILEMAX_=(value:Int):Unit={
_FILEMAX = value
}
private def GENESISNODENAME_=(value:String):Unit={
_GENESISNODENAME = value
}
private def NUMBER_OF_TRANSPROCESSOR_=(value:Int):Unit={
_NUMBER_OF_TRANSPROCESSOR = value
}
private def VOTENODELIST_=(value: List[String]): Unit = {
_VOTENODELIST = value
}
private def ACCOUNTCHAINCODENAEM_=(value:String):Unit={
_ACCOUNTCHAINCODENAEM = value
}
private def CertStatusChangeFunction_=(value:String):Unit={
_CertStatusChangeFunction = value
}
private def ACCOUNTCHAINCODEVERSION_=(value:Int):Unit={
_ACCOUNTCHAINCODEVERSION = value
}
private def SERVERPORT_=(value: Int): Unit = {
_SERVERPORT = value
}
private def CHECKCERTVALIDATE_=(value: Int): Unit = {
_CHECKCERTVALIDATE = value
}
private def CONTRACTOPERATIONMODE_=(value: Int): Unit = {
_CONTRACTOPERATIONMODE = value
}
private def DISKSPACE_ALARM_NUM_=(value: Long): Unit = {
_DISKSPACE_ALARM_NUM = value
}
private def MAX_CATCH_TRANS_NUM: Int = _MAX_CATCH_TRANS_NUM
private def MAX_CATCH_TRANS_NUM_=(value: Int): Unit = {
_MAX_CATCH_TRANS_NUM = value
}
private def RETRY_TIME: Int = _RETRY_TIME
private def RETRY_TIME_=(value: Int): Unit = {
_RETRY_TIME = value
}
private def TRANS_CREATE_TYPE: Int = _TRANS_CREATE_TYPE
private def TRANS_CREATE_TYPE_=(value: Int): Unit = {
_TRANS_CREATE_TYPE = value
}
private def TRAN_CREATE_DUR: Int = _TRAN_CREATE_DUR
private def TRAN_CREATE_DUR_=(value: Int): Unit = {
_TRAN_CREATE_DUR = value
}
private def VOTE_NOTE_MIN: Int = _VOTE_NOTE_MIN
private def VOTE_NOTE_MIN_=(value: Int): Unit = {
_VOTE_NOTE_MIN = value
}
private def MIN_BLOCK_TRANS_NUM: Int = _MIN_BLOCK_TRANS_NUM
private def MIN_BLOCK_TRANS_NUM_=(value: Int): Unit = {
_MIN_BLOCK_TRANS_NUM = value
}
private def LIMIT_BLOCK_TRANS_NUM: Int = _LIMIT_BLOCK_TRANS_NUM
private def LIMIT_BLOCK_TRANS_NUM_=(value: Int): Unit = {
_LIMIT_BLOCK_TRANS_NUM = value
}
private def BLOCK_LENGTH : Int = _BLOCK_LENGTH
private def BLOCK_LENGTH_=(value: Int): Unit = {
_BLOCK_LENGTH = value
}
/**
* 初始化配饰信息
* @param config
*/
def initConfigSystem(config:Config): Unit ={
LIMIT_BLOCK_TRANS_NUM_=(config.getInt("system.block.trans_num_limit"))
BLOCK_LENGTH_=(config.getInt("system.block.block_length"))
MIN_BLOCK_TRANS_NUM_=(config.getInt("system.block.trans_num_min"))
RETRY_TIME_=(config.getInt("system.block.retry_time"))
VOTE_NOTE_MIN_=(config.getInt("system.vote.vote_note_min"))
VOTENODELIST_=(config.getStringList("system.vote.vote_node_list"))
TRAN_CREATE_DUR_=(config.getInt("system.transaction.tran_create_dur"))
MAX_CATCH_TRANS_NUM_=(config.getInt("system.transaction.max_cache_num"))
TRANS_CREATE_TYPE_=(config.getInt("system.trans_create_type"))
DISKSPACE_ALARM_NUM_=(config.getInt("system.diskspaceManager.diskspacealarm"))
SERVERPORT_=(config.getInt("system.httpServicePort"))
CHECKCERTVALIDATE_=(config.getInt("system.checkCertValidate"))
CONTRACTOPERATIONMODE_=(config.getInt("system.contractOperationMode"))
ACCOUNTCHAINCODENAEM_= (config.getString("system.account.chaincodename"))
ACCOUNTCHAINCODEVERSION_=(config.getInt("system.account.chaincodeversion"))
CertStatusChangeFunction_= (config.getString("system.account.CertStatusChangeFunction"))
GENESISNODENAME_=(config.getString("system.genesis_node_name"))
NUMBER_OF_TRANSPROCESSOR_=(config.getInt("system.number_of_transProcessor"))
DBPATH_= (config.getString("system.storage.dbpath"))
BLOCKPATH_= (config.getString("system.storage.blockpath"))
FILEMAX_=(config.getInt("system.storage.filemax"))
REALTIMEGRAPH_ENABLE_=(config.getInt("system.realtimegraph_enable"))
}
def getRealtimeGraph = REALTIMEGRAPH_ENABLE
def getDBPath = DBPATH
def getBlockPath = BLOCKPATH
def getFileMax = FILEMAX
def getLimitBlockTransNum = LIMIT_BLOCK_TRANS_NUM
def getNumberOfTransProcessor = NUMBER_OF_TRANSPROCESSOR
def getBlockLength = BLOCK_LENGTH
def getMinBlockTransNum = MIN_BLOCK_TRANS_NUM
def getVoteNoteMin = VOTE_NOTE_MIN
def getTranCreateDur = TRAN_CREATE_DUR
def getMaxCacheTransNum = MAX_CATCH_TRANS_NUM
def getTransCreateType = TRANS_CREATE_TYPE
def getRetryTime = RETRY_TIME
def getDiskSpaceAlarm = DISKSPACE_ALARM_NUM
def getHttpServicePort = SERVERPORT
def getCheckCertValidate = CHECKCERTVALIDATE
def getContractOperationMode = CONTRACTOPERATIONMODE
def getVoteNodeList = VOTENODELIST
def getAccountChaincodeName = ACCOUNTCHAINCODENAEM
def getCertStatusChangeFunction = CertStatusChangeFunction
def getAccountChaincodeVersion = ACCOUNTCHAINCODVERSION
def getGenesisNodeName = GENESISNODENAME
}
/*
* 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.app.conf
import com.typesafe.config.Config
//import collection.JavaConversions._
//import scala.collection.immutable._
import java.util.List
import java.util.ArrayList
/**
* 系统配置信息缓存对象
* @author shidianyue
* @version 0.7
* @update 2018-05 jiangbuyun
* */
object SystemProfile {
/**
* 交易创建类型
*/
case object Trans_Create_Type_Enum {
val MANUAL = 0 //API创建
val AUTO = 1 //自动创建
}
private[this] var _LIMIT_BLOCK_TRANS_NUM: Int = 0//块内最多交易数
private[this] var _MIN_BLOCK_TRANS_NUM: Int = 0//块内最少交易数
private[this] var _VOTE_NODE_MIN: Int = 0//投票最少参与人数
private[this] var _TRAN_CREATE_DUR: Int = 0//交易创建时间间隔-针对自动创建
private[this] var _TRANS_CREATE_TYPE: Int = 0//交易创建类型
private[this] var _RETRY_TIME: Int = 0//投票重试次数限制
private[this] var _MAX_CATCH_TRANS_NUM: Int = 0//交易最多缓存数量
private[this] var _DISKSPACE_ALARM_NUM:Long=0//磁盘剩余空间预警 单位=M
private[this] var _SERVERPORT:Int=8081//http服务的端口默认为8081
private[this] var _CHECKCERTVALIDATE:Int=0//是否检查证书的有效性0不检查1检查
private[this] var _CONTRACTOPERATIONMODE = 0//设置合约的运行方式0=debug方式1=deploy默认为debug方式如果发布部署必须使用deploy方式
private[this] var _VOTENODELIST : List[String] = new ArrayList[String]
private[this] var _ACCOUNTCHAINCODENAEM : String = "ACCOUNTCHAINCODENAME"
private[this] var _ACCOUNTCHAINCODEVERSION: Int = 1
private[this] var _CertStatusChangeFunction : String = "UpdateCertStatus"
private[this] var _GENESISNODENAME:String = ""
private[this] var _BLOCK_LENGTH: Int = 120000//区块的最大长度
private[this] var _NUMBER_OF_TRANSPROCESSOR = 100 //
private[this] var _HAS_PRELOAD_TRANS_OF_API = true
private[this] var _IS_VERIFY_OF_ENDORSEMENT = true//is_verify_of_endorsement
private[this] var _NUMBER_OF_ENDORSEMENT: Int = 2
private[this] var _TYPE_OF_CONSENSUS:String = "PBFT"
//zhj
private[this] var _PBFT_F: Int = 1
private[this] var _BLOCKNUMBER_OF_RAFT: Int = 100
private[this] var _DBPATH:String = "" //leveldb数据库文件路径
private[this] var _BLOCKPATH:String = ""//区块文件的路径
private[this] var _FILEMAX: Int = 200000000//区块文件的最大长度
//实时图的事件是否发送如果不发送前端实时图将收不到任何消息
private[this] var _REALTIMEGRAPH_ENABLE = 1 ////0 unable;1 enable; default 1
private def SERVERPORT :Int = _SERVERPORT
private def CHECKCERTVALIDATE:Int = _CHECKCERTVALIDATE
private def DISKSPACE_ALARM_NUM :Long = _DISKSPACE_ALARM_NUM
private def CONTRACTOPERATIONMODE:Int=_CONTRACTOPERATIONMODE
private def GENESISNODENAME:String = _GENESISNODENAME
private def VOTENODELIST : List[String] = _VOTENODELIST
private def ACCOUNTCHAINCODENAEM = _ACCOUNTCHAINCODENAEM
private def ACCOUNTCHAINCODVERSION = _ACCOUNTCHAINCODEVERSION
private def CertStatusChangeFunction = _CertStatusChangeFunction
private def NUMBER_OF_TRANSPROCESSOR = _NUMBER_OF_TRANSPROCESSOR
private def HAS_PRELOAD_TRANS_OF_API = _HAS_PRELOAD_TRANS_OF_API
private def IS_VERIFY_OF_ENDORSEMENT = _IS_VERIFY_OF_ENDORSEMENT
private def NUMBER_OF_ENDORSEMENT = _NUMBER_OF_ENDORSEMENT
private def BLOCKNUMBER_OF_RAFT = _BLOCKNUMBER_OF_RAFT
private def REALTIMEGRAPH_ENABLE = _REALTIMEGRAPH_ENABLE
private def TYPE_OF_CONSENSUS : String = _TYPE_OF_CONSENSUS
//zhj
private def PBFT_F = _PBFT_F
private def DBPATH:String = _DBPATH
private def BLOCKPATH:String = _BLOCKPATH
private def FILEMAX: Int = _FILEMAX
private def TYPE_OF_CONSENSUS_=(value:String):Unit={
_TYPE_OF_CONSENSUS = value
}
private def DBPATH_=(value:String):Unit={
_DBPATH = value
}
private def REALTIMEGRAPH_ENABLE_=(value:Int):Unit={
_REALTIMEGRAPH_ENABLE = value
}
private def BLOCKPATH_=(value:String):Unit={
_BLOCKPATH = value
}
private def FILEMAX_=(value:Int):Unit={
_FILEMAX = value
}
private def GENESISNODENAME_=(value:String):Unit={
_GENESISNODENAME = value
}
private def NUMBER_OF_TRANSPROCESSOR_=(value:Int):Unit={
_NUMBER_OF_TRANSPROCESSOR = value
}
private def HAS_PRELOAD_TRANS_OF_API_=(value:Boolean):Unit={
_HAS_PRELOAD_TRANS_OF_API = value
}
private def IS_VERIFY_OF_ENDORSEMENT_=(value:Boolean):Unit={
_IS_VERIFY_OF_ENDORSEMENT = value
}
private def NUMBER_OF_ENDORSEMENT_=(value:Int):Unit={
_NUMBER_OF_ENDORSEMENT = value
}
private def BLOCKNUMBER_OF_RAFT_=(value:Int):Unit={
_BLOCKNUMBER_OF_RAFT = value
}
private def VOTENODELIST_=(value: List[String]): Unit = {
_VOTENODELIST = value
}
private def ACCOUNTCHAINCODENAEM_=(value:String):Unit={
_ACCOUNTCHAINCODENAEM = value
}
private def CertStatusChangeFunction_=(value:String):Unit={
_CertStatusChangeFunction = value
}
private def ACCOUNTCHAINCODEVERSION_=(value:Int):Unit={
_ACCOUNTCHAINCODEVERSION = value
}
private def SERVERPORT_=(value: Int): Unit = {
_SERVERPORT = value
}
private def CHECKCERTVALIDATE_=(value: Int): Unit = {
_CHECKCERTVALIDATE = value
}
private def CONTRACTOPERATIONMODE_=(value: Int): Unit = {
_CONTRACTOPERATIONMODE = value
}
private def DISKSPACE_ALARM_NUM_=(value: Long): Unit = {
_DISKSPACE_ALARM_NUM = value
}
private def MAX_CATCH_TRANS_NUM: Int = _MAX_CATCH_TRANS_NUM
private def MAX_CATCH_TRANS_NUM_=(value: Int): Unit = {
_MAX_CATCH_TRANS_NUM = value
}
private def RETRY_TIME: Int = _RETRY_TIME
private def RETRY_TIME_=(value: Int): Unit = {
_RETRY_TIME = value
}
private def TRANS_CREATE_TYPE: Int = _TRANS_CREATE_TYPE
private def TRANS_CREATE_TYPE_=(value: Int): Unit = {
_TRANS_CREATE_TYPE = value
}
private def TRAN_CREATE_DUR: Int = _TRAN_CREATE_DUR
private def TRAN_CREATE_DUR_=(value: Int): Unit = {
_TRAN_CREATE_DUR = value
}
private def VOTE_NODE_MIN: Int = _VOTE_NODE_MIN
private def VOTE_NODE_MIN_=(value: Int): Unit = {
_VOTE_NODE_MIN = value
}
private def MIN_BLOCK_TRANS_NUM: Int = _MIN_BLOCK_TRANS_NUM
private def MIN_BLOCK_TRANS_NUM_=(value: Int): Unit = {
_MIN_BLOCK_TRANS_NUM = value
}
private def LIMIT_BLOCK_TRANS_NUM: Int = _LIMIT_BLOCK_TRANS_NUM
private def LIMIT_BLOCK_TRANS_NUM_=(value: Int): Unit = {
_LIMIT_BLOCK_TRANS_NUM = value
}
private def BLOCK_LENGTH : Int = _BLOCK_LENGTH
private def BLOCK_LENGTH_=(value: Int): Unit = {
_BLOCK_LENGTH = value
}
/**
* 初始化配饰信息
* @param config
*/
def initConfigSystem(config:Config): Unit ={
LIMIT_BLOCK_TRANS_NUM_=(config.getInt("system.block.trans_num_limit"))
BLOCK_LENGTH_=(config.getInt("system.block.block_length"))
MIN_BLOCK_TRANS_NUM_=(config.getInt("system.block.trans_num_min"))
RETRY_TIME_=(config.getInt("system.block.retry_time"))
VOTE_NODE_MIN_=(config.getInt("system.vote.vote_node_min"))
VOTENODELIST_=(config.getStringList("system.vote.vote_node_list"))
TRAN_CREATE_DUR_=(config.getInt("system.transaction.tran_create_dur"))
MAX_CATCH_TRANS_NUM_=(config.getInt("system.transaction.max_cache_num"))
TRANS_CREATE_TYPE_=(config.getInt("system.trans_create_type"))
DISKSPACE_ALARM_NUM_=(config.getInt("system.diskspaceManager.diskspacealarm"))
SERVERPORT_=(config.getInt("system.httpServicePort"))
CHECKCERTVALIDATE_=(config.getInt("system.checkCertValidate"))
CONTRACTOPERATIONMODE_=(config.getInt("system.contractOperationMode"))
ACCOUNTCHAINCODENAEM_= (config.getString("system.account.chaincodename"))
ACCOUNTCHAINCODEVERSION_=(config.getInt("system.account.chaincodeversion"))
CertStatusChangeFunction_= (config.getString("system.account.CertStatusChangeFunction"))
GENESISNODENAME_=(config.getString("system.genesis_node_name"))
NUMBER_OF_TRANSPROCESSOR_=(config.getInt("system.number_of_transProcessor"))
HAS_PRELOAD_TRANS_OF_API_=(config.getBoolean("system.has_preload_trans_of_api"))
IS_VERIFY_OF_ENDORSEMENT_=(config.getBoolean("system.is_verify_of_endorsement"))
NUMBER_OF_ENDORSEMENT_=(config.getInt("system.number_of_endorsement"))
BLOCKNUMBER_OF_RAFT_=(config.getInt("system.consensus.blocknumberofraft"))
TYPE_OF_CONSENSUS_=(config.getString("system.consensus.type"))
DBPATH_= (config.getString("system.storage.dbpath"))
BLOCKPATH_= (config.getString("system.storage.blockpath"))
FILEMAX_=(config.getInt("system.storage.filemax"))
REALTIMEGRAPH_ENABLE_=(config.getInt("system.realtimegraph_enable"))
}
//zhj
def getPbftF = PBFT_F
def getRealtimeGraph = REALTIMEGRAPH_ENABLE
def getDBPath = DBPATH
def getBlockPath = BLOCKPATH
def getFileMax = FILEMAX
def getLimitBlockTransNum = LIMIT_BLOCK_TRANS_NUM
def getNumberOfTransProcessor = NUMBER_OF_TRANSPROCESSOR
def getBlockNumberOfRaft = BLOCKNUMBER_OF_RAFT
def getTypeOfConsensus : String = TYPE_OF_CONSENSUS
def getHasPreloadTransOfApi = HAS_PRELOAD_TRANS_OF_API
def getIsVerifyOfEndorsement = IS_VERIFY_OF_ENDORSEMENT
def getNumberOfEndorsement = NUMBER_OF_ENDORSEMENT
def getBlockLength = BLOCK_LENGTH
def getMinBlockTransNum = MIN_BLOCK_TRANS_NUM
def getVoteNodeMin = VOTE_NODE_MIN
def getTranCreateDur = TRAN_CREATE_DUR
def getMaxCacheTransNum = MAX_CATCH_TRANS_NUM
def getTransCreateType = TRANS_CREATE_TYPE
def getRetryTime = RETRY_TIME
def getDiskSpaceAlarm = DISKSPACE_ALARM_NUM
def getHttpServicePort = SERVERPORT
def getCheckCertValidate = CHECKCERTVALIDATE
def getContractOperationMode = CONTRACTOPERATIONMODE
def getVoteNodeList = VOTENODELIST
def getAccountChaincodeName = ACCOUNTCHAINCODENAEM
def getCertStatusChangeFunction = CertStatusChangeFunction
def getAccountChaincodeVersion = ACCOUNTCHAINCODVERSION
def getGenesisNodeName = GENESISNODENAME
}

View File

@ -1,224 +1,294 @@
/*
* 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.app.system
import java.io.File
import akka.actor.{ ActorRef, ActorSystem, Address, Props }
import akka.cluster.Cluster
import com.typesafe.config.{ Config, ConfigFactory }
import rep.app.conf.SystemConf
import rep.app.system.ClusterSystem.InitType
import rep.network.base.ModuleBase
import rep.network.module.ModuleManager
import rep.utils.GlobalUtils.ActorType
import rep.storage.cfg._
import java.io.File
import scala.collection.mutable
import rep.app.conf.SystemProfile
import com.typesafe.config.ConfigValueFactory
import java.util.List
import java.util.ArrayList
import org.slf4j.LoggerFactory
import rep.log.RepLogger
/**
* System创建伴生对象
* @author shidianyue
* @version 0.7
* @update 2018-05 jiangbuyun
*/
object ClusterSystem {
/**
* 初始化类型
*/
object InitType {
val SINGLE_INIT = 1 //单机单节点
val MULTI_INIT = 2 //单机多节点
}
}
/**
* System创建类
* @author shidianyue
* @version 0.7
* @since 1.0
* @param sysTag 系统system命名
* @param initType 初始化类型
* @param sysStart 是否开启system不开启仅用于初始化
*/
class ClusterSystem(sysTag: String, initType: Int, sysStart: Boolean) {
protected def log = LoggerFactory.getLogger(this.getClass)
private val USER_CONFIG_PATH = "conf/system.conf"
private val modulePrefix = "RepCluster"
private val moduleName = modulePrefix + "_" + sysTag
private var webSocket: ActorRef = null
private var memberLis: ActorRef = null
private var moduleManager: ActorRef = null
private var statistics: ActorRef = null
private var enableWebSocket = false
private var enableStatistic = false
private var sysConf: Config = initSystem(sysTag)
private var sysActor: ActorSystem = null
private var clusterAddr: Address = null
/**
* 是否开启Web SocketAPI
*/
def enableWS() = enableWebSocket = true
def disableWS() = enableWebSocket = false
/**
* 获取用户和系统的联合配置
* @param userConfigFilePath
* @return
*/
def getUserCombinedConf(userConfigFilePath: String): Config = {
val userConfFile = new File(userConfigFilePath)
val innerConf = ConfigFactory.load()
if (userConfFile.exists()) {
val combined_conf = ConfigFactory.parseFile(userConfFile).withFallback(innerConf)
val final_conf = ConfigFactory.load(combined_conf)
final_conf
} else {
RepLogger.trace(RepLogger.System_Logger, sysTag + "~" + "ClusterSystem" + " ~ " + "Couldn't find the user config file")
innerConf
}
}
/**
* 获取完整配置信息
* 用户系统初始化
* @param sysName
* @return
*/
def getConfigBySys(sysName: String): Config = {
val myConfig =
ConfigFactory.parseString("akka.remote.netty.ssl.security.key-store = \"jks/" + sysName +
".jks\"")
val regularConfig = getUserCombinedConf(USER_CONFIG_PATH)
val combined =
myConfig.withFallback(regularConfig)
val complete =
ConfigFactory.load(combined)
complete
}
def getConf = sysConf
def hasDiskSpace: Boolean = {
var b = true
//val sc: StoreConfig = StoreConfig.getStoreConfig()
val ds = StoreConfig4Scala.getFreeDiskSpace / (1000 * 1000)
if (SystemProfile.getDiskSpaceAlarm >= ds) {
b = false
}
b
}
/**
* 初始化系统参数
* @param sysName
* @return
*/
def initSystem(sysName: String): Config = {
val conf = getConfigBySys(sysName)
RepLogger.trace(RepLogger.System_Logger, sysTag + " ~ " + "ClusterSystem" + "~" + "System configuration successfully")
enableWebSocket = conf.getInt("system.ws_enable") match {
case 0 => false
case 1 => true
}
enableStatistic = conf.getInt("system.statistic_enable") match {
case 0 => false
case 1 => true
}
conf
}
def getClusterAddr = clusterAddr
/**
* 组网
* @param address
* @return
*/
def joinCluster(address: Address): Boolean = {
initType match {
case InitType.SINGLE_INIT =>
Cluster(sysActor)
case InitType.MULTI_INIT =>
Cluster(sysActor).join(address)
}
true
}
/**
* 初始化
*/
def init = {
initConsensusNodeOfConfig
if (sysStart) {
sysActor = ActorSystem(SystemConf.SYSTEM_NAME, sysConf)
clusterAddr = Cluster(sysActor).selfAddress
}
RepLogger.trace(RepLogger.System_Logger, sysTag + "~" + "System" + " ~ " + s"System(${sysTag}) init successfully" + " ~ ")
}
def shutdown = {
Cluster(sysActor).down(clusterAddr)
}
private def initConsensusNodeOfConfig = {
val nodelist = sysConf.getStringList("system.vote.vote_node_list")
if (nodelist.contains(this.sysTag)) {
var roles: List[String] = new ArrayList[String]
roles.add("CRFD-Node:" + this.sysTag)
sysConf = sysConf.withValue("akka.cluster.roles", ConfigValueFactory.fromAnyRef(roles))
}
}
/**
* 启动系统
*/
def start = {
SystemProfile.initConfigSystem(sysActor.settings.config)
if (!hasDiskSpace) {
Cluster(sysActor).down(clusterAddr)
throw new Exception("not enough disk space")
}
moduleManager = sysActor.actorOf(ModuleManager.props("modulemanager", sysTag, enableStatistic, enableWebSocket, true), "modulemanager")
RepLogger.trace(RepLogger.System_Logger, sysTag + "~" + "System" + " ~ " + s"ClusterSystem ${sysTag} start" + " ~ ")
}
}
/*
* 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.app.system
import java.io.File
import akka.actor.{ActorRef, ActorSystem, Address, Props}
import akka.cluster.Cluster
import com.typesafe.config.{Config, ConfigFactory}
import rep.app.conf.{SystemConf, SystemProfile, TimePolicy}
import rep.app.system.ClusterSystem.InitType
import rep.network.base.ModuleBase
import rep.network.module.cfrd.ModuleManagerOfCFRD
import rep.storage.cfg._
import java.io.File
import scala.collection.mutable
import com.typesafe.config.ConfigValueFactory
import java.util.List
import java.util.ArrayList
import akka.util.Timeout
import org.slf4j.LoggerFactory
import rep.log.RepLogger
import scala.concurrent.Await
import scala.concurrent.duration._
import akka.actor.Terminated
import rep.network.module.pbft.ModuleManagerOfPBFT
import rep.network.module.raft.ModuleManagerOfRAFT
/**
* System创建伴生对象
* @author shidianyue
* @version 0.7
* @update 2018-05 jiangbuyun
*/
object ClusterSystem {
/**
* 初始化类型
*/
object InitType {
val SINGLE_INIT = 1 //单机单节点
val MULTI_INIT = 2 //单机多节点
}
}
/**
* System创建类
* @author shidianyue
* @version 0.7
* @since 1.0
* @param sysTag 系统system命名
* @param initType 初始化类型
* @param sysStart 是否开启system不开启仅用于初始化
*/
class ClusterSystem(sysTag: String, initType: Int, sysStart: Boolean) {
protected def log = LoggerFactory.getLogger(this.getClass)
private val USER_CONFIG_PATH = "conf/system.conf"
private val modulePrefix = "RepCluster"
private val moduleName = modulePrefix + "_" + sysTag
private var webSocket: ActorRef = null
private var memberLis: ActorRef = null
private var moduleManager: ActorRef = null
private var statistics: ActorRef = null
private var enableWebSocket = false
private var enableStatistic = false
private var sysConf: Config = initSystem(sysTag)
private var sysActor: ActorSystem = null
private var clusterAddr: Address = null
private var clusterOfInner : Cluster = null
//System.setProperty("scala.concurrent.context.minThreads", "32")
//System.setProperty("scala.concurrent.context.maxThreads", "32")
/**
* 是否开启Web SocketAPI
*/
def enableWS() = enableWebSocket = true
def disableWS() = enableWebSocket = false
/**
* 获取用户和系统的联合配置
* @param userConfigFilePath
* @return
*/
def getUserCombinedConf(userConfigFilePath: String): Config = {
val userConfFile = new File(userConfigFilePath)
val innerConf = ConfigFactory.load()
if (userConfFile.exists()) {
val combined_conf = ConfigFactory.parseFile(userConfFile).withFallback(innerConf)
val final_conf = ConfigFactory.load(combined_conf)
final_conf
} else {
RepLogger.trace(RepLogger.System_Logger, sysTag + "~" + "ClusterSystem" + " ~ " + "Couldn't find the user config file")
innerConf
}
}
/**
* 获取完整配置信息
* 用户系统初始化
* @param sysName
* @return
*/
def getConfigBySys(sysName: String): Config = {
/*val myConfig =
ConfigFactory.parseString("akka.remote.netty.ssl.security.key-store = \"jks/" + sysName +
".jks\"")*/
val myConfig =
ConfigFactory.parseString("akka.remote.artery.ssl.config-ssl-engine.key-store = \"jks/" + sysName +
".jks\"")
val regularConfig = getUserCombinedConf(USER_CONFIG_PATH)
val combined =
myConfig.withFallback(regularConfig)
val complete =
ConfigFactory.load(combined)
complete
}
def getConf = sysConf
def hasDiskSpace: Boolean = {
var b = true
//val sc: StoreConfig = StoreConfig.getStoreConfig()
val ds = StoreConfig4Scala.getFreeDiskSpace / (1000 * 1000)
if (SystemProfile.getDiskSpaceAlarm >= ds) {
b = false
}
b
}
/**
* 初始化系统参数
* @param sysName
* @return
*/
def initSystem(sysName: String): Config = {
val conf = getConfigBySys(sysName)
RepLogger.trace(RepLogger.System_Logger, sysTag + " ~ " + "ClusterSystem" + "~" + "System configuration successfully")
enableWebSocket = conf.getInt("system.ws_enable") match {
case 0 => false
case 1 => true
}
enableStatistic = conf.getInt("system.statistic_enable") match {
case 0 => false
case 1 => true
}
conf
}
def getClusterAddr = clusterAddr
def getClusterInstance : Cluster = clusterOfInner
/**
* 组网
* @param address
* @return
*/
def joinCluster(address: Address): Boolean = {
initType match {
case InitType.SINGLE_INIT =>
clusterOfInner = Cluster(sysActor)
case InitType.MULTI_INIT =>
clusterOfInner = Cluster(sysActor)
clusterOfInner.join(address)
}
true
}
/**
* 初始化
*/
def init = {
initConsensusNodeOfConfig
if (sysStart) {
sysActor = ActorSystem(SystemConf.SYSTEM_NAME, sysConf)
clusterAddr = Cluster(sysActor).selfAddress
}
RepLogger.trace(RepLogger.System_Logger, sysTag + "~" + "System" + " ~ " + s"System(${sysTag}) init successfully" + " ~ ")
}
def init2(port:Int):Unit = {
var myConfig :Config = null
if(this.sysConf.getBoolean("akka.remote.artery.enabled")){
myConfig = ConfigFactory.parseString("akka.remote.artery.canonical.port = " + port )
}else{
myConfig = ConfigFactory.parseString("akka.remote.classic.netty.tcp.port = " + port )
}
var combined = myConfig.withFallback(this.sysConf)
this.sysConf = ConfigFactory.load(combined)
this.init
}
def init3(port:Int):Unit = {
var myConfig :Config = null
myConfig = ConfigFactory.parseString("akka.remote.netty.ssl.port = " + port )
var combined = myConfig.withFallback(this.sysConf)
this.sysConf = ConfigFactory.load(combined)
this.init
}
def shutdown = {
Cluster(sysActor).down(clusterAddr)
System.err.println(s"shutdown ~~ address=${clusterAddr.toString},systemname=${this.sysTag}")
}
def terminateOfSystem={
var r = true
implicit val timeout = Timeout(120.seconds)
try{
val result = sysActor.terminate
val result1 = Await.result(result, timeout.duration).asInstanceOf[Terminated]
r = result1.getAddressTerminated
}catch{
case e:Exception =>
r = false
}
r
}
private def initConsensusNodeOfConfig = {
val nodelist = sysConf.getStringList("system.vote.vote_node_list")
if (nodelist.contains(this.sysTag)) {
var roles: List[String] = new ArrayList[String]
roles.add("CRFD-Node:" + this.sysTag)
sysConf = sysConf.withValue("akka.cluster.roles", ConfigValueFactory.fromAnyRef(roles))
}
}
/**
* 启动系统
*/
def start = {
SystemProfile.initConfigSystem(sysActor.settings.config)
if (!hasDiskSpace) {
Cluster(sysActor).down(clusterAddr)
throw new Exception("not enough disk space")
}
val typeConsensus = SystemProfile.getTypeOfConsensus
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"){
moduleManager = sysActor.actorOf(ModuleManagerOfPBFT.props("modulemanager", sysTag, enableStatistic, enableWebSocket, true), "modulemanager")
}else{
RepLogger.error(RepLogger.System_Logger, sysTag + "~" + "System" + " ~ " + s"ClusterSystem ${sysTag} not startup,unknow consensus" + " ~ ")
}
RepLogger.trace(RepLogger.System_Logger, sysTag + "~" + "System" + " ~ " + s"ClusterSystem ${sysTag} start" + " ~ ")
}
}

View File

@ -20,13 +20,13 @@ import java.io._
import java.security.cert.{ Certificate, CertificateFactory }
import rep.app.conf.SystemProfile
import com.google.protobuf.ByteString
import fastparse.utils.Base64
//import fastparse.utils.Base64
import rep.utils.SerializeUtils
import rep.storage._
import scala.collection.mutable
import com.fasterxml.jackson.core.Base64Variants
//import com.fasterxml.jackson.core.Base64Variants
import java.security.cert.X509Certificate
import javax.xml.bind.DatatypeConverter
//import javax.xml.bind.DatatypeConverter
import java.util.ArrayList
import java.util.List
import sun.security.ec.ECPublicKeyImpl

View File

@ -27,7 +27,7 @@ import java.util.{ArrayList, List}
import rep.app.conf.SystemProfile
import scala.util.control.Breaks._
import fastparse.utils.Base64
//import fastparse.internal..utils.Base64
import org.bouncycastle.util.io.pem.PemReader
/**
@ -41,6 +41,7 @@ object SignTool {
private var keypassword = mutable.HashMap[String, String]()
private var keyStores = mutable.HashMap[String, KeyStore]()
private var PublickeyCerts = mutable.HashMap[String, Certificate]()
//private var PublickeyCerts = mutable.HashMap[String, PublicKey]()
private var TrustNodelist: List[String] = new ArrayList[String]
private var isAddPublicKey = false

View File

@ -1,96 +1,90 @@
/*
* 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.crypto.cert
import java.io._
import fastparse.utils.Base64
import java.util.concurrent.locks._
import org.bouncycastle.util.io.pem.PemReader
import rep.protos.peer.Certificate
import rep.storage._
import rep.utils.SerializeUtils
import rep.app.conf.SystemProfile
import rep.storage.IdxPrefix.WorldStateKeyPreFix
import java.util.concurrent.ConcurrentHashMap
import scala.collection.JavaConverters._
import rep.log.RepLogger
object certCache {
private implicit var caches = new ConcurrentHashMap[String, (Boolean, java.security.cert.Certificate)] asScala
def getCertByPem(pemcert: String): java.security.cert.Certificate = {
val cf = java.security.cert.CertificateFactory.getInstance("X.509")
// val cert = cf.generateCertificate(
// new ByteArrayInputStream(
// Base64.Decoder(
// pemcert.replaceAll("\r\n", "")
// .replaceAll("\n","")
// .stripPrefix("-----BEGIN CERTIFICATE-----")
// .stripSuffix("-----END CERTIFICATE-----")).toByteArray
// )
// )
val pemReader = new PemReader(new StringReader(pemcert))
val certByte = pemReader.readPemObject().getContent
val cert = cf.generateCertificate(new ByteArrayInputStream(certByte))
cert
}
def getCertForUser(certKey: String, sysTag: String): java.security.cert.Certificate = {
var rcert: java.security.cert.Certificate = null
try {
if (caches.contains(certKey)) {
val ck = caches(certKey)
if(ck._1){
//证书有效时返回
rcert = caches(certKey)._2
}
} else {
val sr: ImpDataAccess = ImpDataAccess.GetDataAccess(sysTag)
val accountChaincodeName = SystemProfile.getAccountChaincodeName
val cert = Option(sr.Get(IdxPrefix.WorldStateKeyPreFix + accountChaincodeName + "_" + certKey))
if (cert != None && !(new String(cert.get)).equalsIgnoreCase("null")) {
val kvcert = SerializeUtils.deserialise(cert.get).asInstanceOf[Certificate]
if (kvcert != null ) {
if(kvcert.certValid){
//从worldstate中获取证书如果证书以及证书是有效时返回证书信息
rcert = getCertByPem(kvcert.certificate)
}
caches += certKey -> (kvcert.certValid, rcert)
}
}
}
} catch {
case e:Exception => RepLogger.trace(RepLogger.System_Logger, s"${certKey}, getCertForUser execept,msg=${e.getMessage}")
}
rcert
}
def CertStatusUpdate(ck:String)={
if(ck != null){
val pos = ck.lastIndexOf("_")
if(pos > 0){
val ckey = ck.substring(ck.lastIndexOf("_")+1)
if(this.caches.contains(ckey)){
this.caches -= ckey
}
}
}
}
}
/*
* 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.crypto.cert
import java.io._
import java.security.PublicKey
import org.bouncycastle.util.io.pem.PemReader
import rep.protos.peer.Certificate
import rep.storage._
import rep.utils.SerializeUtils
import rep.app.conf.SystemProfile
import java.util.concurrent.ConcurrentHashMap
import rep.log.RepLogger
//import scala.jdk.CollectionConverters._
import scala.collection.JavaConverters._
object certCache {
private var caches = new ConcurrentHashMap[String, (Boolean, java.security.cert.Certificate)] asScala
//private var caches = new ConcurrentHashMap[String, (Boolean, java.security.PublicKey)] asScala
def getCertByPem(pemcert: String): java.security.cert.Certificate = {
val cf = java.security.cert.CertificateFactory.getInstance("X.509")
val pemReader = new PemReader(new StringReader(pemcert))
val certByte = pemReader.readPemObject().getContent
val cert = cf.generateCertificate(new ByteArrayInputStream(certByte))
cert
}
//java.security.cert.Certificate = {
def getCertForUser(certKey: String, sysTag: String): java.security.cert.Certificate={
var rcert: java.security.cert.Certificate = null
//var rcert: java.security.PublicKey = null
try {
if (caches.contains(certKey)) {
val ck = caches(certKey)
if(ck._1){
//证书有效时返回
rcert = caches(certKey)._2
}
} else {
val sr: ImpDataAccess = ImpDataAccess.GetDataAccess(sysTag)
val accountChaincodeName = SystemProfile.getAccountChaincodeName
val cert = Option(sr.Get(IdxPrefix.WorldStateKeyPreFix + accountChaincodeName + "_" + certKey))
if (cert != None && !(new String(cert.get)).equalsIgnoreCase("null")) {
val kvcert = SerializeUtils.deserialise(cert.get).asInstanceOf[Certificate]
if (kvcert != null ) {
if(kvcert.certValid){
//从worldstate中获取证书如果证书以及证书是有效时返回证书信息
rcert = getCertByPem(kvcert.certificate)
}
caches += certKey -> (kvcert.certValid, rcert)
}
}
}
} catch {
case e:Exception => RepLogger.trace(RepLogger.System_Logger, s"${certKey}, getCertForUser execept,msg=${e.getMessage}")
}
rcert
}
def CertStatusUpdate(ck:String)={
if(ck != null){
val pos = ck.lastIndexOf("_")
if(pos > 0){
val ckey = ck.substring(ck.lastIndexOf("_")+1)
if(this.caches.contains(ckey)){
this.caches -= ckey
}
}
}
}
}

View File

@ -1,123 +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.log
import rep.network.Topic
import rep.protos.peer._
import akka.stream.actor._
import akka.actor.{Props,Address,PoisonPill}
import akka.cluster.pubsub.DistributedPubSub
import akka.cluster.pubsub.DistributedPubSubMediator.{Publish, Subscribe}
import akka.cluster.Cluster
import akka.cluster.ClusterEvent._
import akka.cluster.MemberStatus
import rep.ui.web.EventServer
import rep.network.tools.PeerExtension
import rep.storage._
import akka.stream.Graph
/** 负责处理websocket事件订阅的actor伴生对象
* @author c4w
*/
object EventActor {
def props: Props = Props[EventActor]
}
/** 负责处理websocket事件订阅的Actor一方面作为消费者在后台订阅Event,另一方面作为WebSocket的source
* 向浏览器push事件流, 事件流采用protobuf流
* @author c4w
* @constructor
*/
class EventActor extends ActorPublisher[Event] {
import scala.concurrent.duration._
val cluster = Cluster(context.system)
var nodes = Set.empty[Address]
var buffer = Vector.empty[Event]
/** 启动,订阅集群入网、离网事件,订阅Topic事件
*
*/
override def preStart(): Unit ={
cluster.subscribe(self, classOf[MemberEvent])
val mediator = DistributedPubSub(context.system).mediator
//发送订阅Event
mediator ! Subscribe(Topic.Event, self)
//发送当前出块人
val pe = PeerExtension(context.system)
self ! new Event( pe.getBlocker.blocker, "", Event.Action.CANDIDATOR)
val ref = context.actorSelection("/user/modulemanager/memberlistener")
if(ref != null) ref ! cluster.state
}
/** 停止处理,取消订阅
*
*/
override def postStop(): Unit =
cluster unsubscribe self
/** 接收Event处理支持所谓“背压”方式即根据web端消费能力push
*
*/
override def receive: Receive = {
//Topic事件
case evt:Event=>
//当浏览器关掉自杀
if(this.isCanceled){
self ! PoisonPill
}else{
if (buffer.isEmpty && totalDemand > 0) {
onNext(evt)
}
else {
buffer :+= evt
if (totalDemand > 0) {
val (use,keep) = buffer.splitAt(totalDemand.toInt)
buffer = keep
use foreach onNext
}
}
}
//集群事件
/*case state: CurrentClusterState =>
val iter = state.members.iterator;
iter.foreach { m =>
if (m.status == MemberStatus.Up){
self ! new Event( m.address.toString, "", Event.Action.MEMBER_UP)
}
}
//节点入网
case MemberUp(member) =>
nodes += member.address
self !new Event( member.address.toString, "", Event.Action.MEMBER_UP)
case UnreachableMember(member) =>
//节点离网
case MemberRemoved(member, _) =>
val maddr = member.address.toString
val saddr = Cluster(context.system).selfAddress.toString
//println(s"-------$maddr-----$saddr")
if(maddr == saddr){
context.system.terminate()
}else{
nodes -= member.address
self ! new Event( member.address.toString,"",Event.Action.MEMBER_DOWN)
}
case _: MemberEvent => // ignore
*/
}
}

View File

@ -16,12 +16,10 @@
package rep.log
import rep.network.Topic
import rep.protos.peer._
import akka.stream.actor._
import akka.actor.{ Props, Address, Actor, ActorRef, Terminated }
import akka.actor.{Actor, ActorRef, Address, Props, Terminated}
import akka.cluster.pubsub.DistributedPubSub
import akka.cluster.pubsub.DistributedPubSubMediator.{ Publish, Subscribe }
import akka.cluster.pubsub.DistributedPubSubMediator.{Publish, Subscribe}
import akka.cluster.Cluster
import akka.cluster.ClusterEvent._
import akka.cluster.MemberStatus
@ -29,8 +27,10 @@ import rep.ui.web.EventServer
import rep.network.tools.PeerExtension
import rep.storage._
import akka.stream.Graph
import scala.collection.mutable.{ HashSet, Set }
import rep.log.RecvEventActor.{ Register }
import scala.collection.mutable.{HashSet, Set}
import rep.log.RecvEventActor.Register
import rep.network.autotransaction.Topic
import rep.network.util.NodeHelp
object RecvEventActor {

View File

@ -36,8 +36,12 @@ object RepLogger {
def Vote_Logger = LoggerFactory.getLogger("Vote_Logger")
def OutputTime_Logger = LoggerFactory.getLogger("OutputTime_Logger")
def TransLifeCycle_Logger = LoggerFactory.getLogger("TransLifeCycle_Logger")
def trace(logger:Logger,msg:String)={
def APIAccess_Logger = LoggerFactory.getLogger("APIAccess_Logger")
//zhj
def zLogger = LoggerFactory.getLogger("System_Logger")
def trace(logger:Logger,msg:String)={
logger.trace(msg)
}

View File

@ -16,6 +16,7 @@
package rep.log
import java.util.concurrent.ConcurrentHashMap
//import scala.jdk.CollectionConverters._
import scala.collection.JavaConverters._
import java.util.concurrent.atomic._

View File

@ -1,219 +1,216 @@
/*
* 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
import akka.actor.{ Actor, Address, Props }
import com.google.protobuf.ByteString
import com.google.protobuf.timestamp.Timestamp
import rep.app.conf.SystemProfile
import rep.crypto.{ Sha256 }
import rep.network.base.ModuleBase
import rep.network.cluster.ClusterActor
import rep.network.tools.PeerExtension
import rep.protos.peer._
import rep.utils.GlobalUtils.ActorType
import rep.utils.{ IdTool, TimeUtils }
import akka.cluster.pubsub.DistributedPubSubMediator.Publish
import scala.concurrent.forkjoin.ThreadLocalRandom
import java.text.SimpleDateFormat
import rep.crypto.cert.SignTool
import rep.log.RepLogger
/**
*
* 代理节点辅助类
* 用来定时生成Transaction
* 之后也应该通过其接收前端数据进而生成Transaction
*
* @author jiangbuyun
*/
object Topic {
val Transaction = "Transaction"
val Block = "Block"
val Event = "Event"
val Endorsement = "Endorsement"
}
object InnerTopic {
val BlockRestore = "BlockRestore"
}
object PeerHelper {
def props(name: String): Props = Props(classOf[PeerHelper], name)
case object Tick
case object TickInit
case object TickInvoke
case object TickQuery
/**
* 采用节点私钥创建交易的方法
*
*/
def createTransaction4Invoke(nodeName: String, chaincodeId: ChaincodeId,
chaincodeInputFunc: String, params: Seq[String]): Transaction = {
var t: Transaction = new Transaction()
val millis = TimeUtils.getCurrentTime()
if (chaincodeId == null) t
val txid = IdTool.getRandomUUID
val cip = new ChaincodeInput(chaincodeInputFunc, params)
t = t.withId(txid)
t = t.withCid(chaincodeId)
t = t.withIpt(cip)
t = t.withType(rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE)
t = t.clearSignature
val certid = IdTool.getCertIdFromName(nodeName)
var sobj = Signature(Option(certid), Option(Timestamp(millis / 1000, ((millis % 1000) * 1000000).toInt)))
sobj = sobj.withSignature(ByteString.copyFrom(SignTool.sign(nodeName, t.toByteArray)))
t = t.withSignature(sobj)
t
}
def createTransaction4Deploy(nodeName: String, chaincodeId: ChaincodeId,
spcPackage: String, legal_prose: String, timeout: Int,
ctype: rep.protos.peer.ChaincodeDeploy.CodeType): Transaction = {
var t: Transaction = new Transaction()
val millis = TimeUtils.getCurrentTime()
if (chaincodeId == null) t
val txid = IdTool.getRandomUUID
var cip = new ChaincodeDeploy(timeout)
cip = cip.withCodePackage(spcPackage)
cip = cip.withLegalProse(legal_prose)
cip = cip.withCtype(ctype)
t = t.withId(txid)
t = t.withCid(chaincodeId)
t = t.withSpec(cip)
t = t.withType(rep.protos.peer.Transaction.Type.CHAINCODE_DEPLOY)
t = t.clearSignature
val certid = IdTool.getCertIdFromName(nodeName)
var sobj = Signature(Option(certid), Option(Timestamp(millis / 1000, ((millis % 1000) * 1000000).toInt)))
sobj = sobj.withSignature(ByteString.copyFrom(SignTool.sign(nodeName, t.toByteArray)))
t = t.withSignature(sobj)
t
}
def createTransaction4State(nodeName: String, chaincodeId: ChaincodeId,
state:Boolean): Transaction = {
var t: Transaction = new Transaction()
val millis = TimeUtils.getCurrentTime()
if (chaincodeId == null) t
val txid = IdTool.getRandomUUID
t = t.withId(txid)
t = t.withCid(chaincodeId)
t = t.withType(rep.protos.peer.Transaction.Type.CHAINCODE_SET_STATE)
t = t.withState(state)
t = t.clearSignature
val certid = IdTool.getCertIdFromName(nodeName)
var sobj = Signature(Option(certid), Option(Timestamp(millis / 1000, ((millis % 1000) * 1000000).toInt)))
sobj = sobj.withSignature(ByteString.copyFrom(SignTool.sign(nodeName, t.toByteArray)))
t = t.withSignature(sobj)
t
}
}
class PeerHelper(name: String) extends ModuleBase(name) {
import rep.network.PeerHelper._
import scala.concurrent.duration._
import context.dispatcher
//val si1 = scala.io.Source.fromFile("scripts/example_invoke_" + pe.getSysTag + ".js")
//val li1 = try si1.mkString finally si1.close()
val si2 = scala.io.Source.fromFile("api_req/json/transfer_" + pe.getSysTag + ".json")
val li2 = try si2.mkString finally si2.close()
//val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
var chaincode:ChaincodeId = new ChaincodeId("ContractAssetsTPL",1)
override def preStart(): Unit = {
//注册接收交易的广播
SubscribeTopic(mediator, self, selfAddr, Topic.Transaction, true)
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("Transaction Creator Start"))
scheduler.scheduleOnce(15.seconds, self, Tick)
}
// override postRestart so we don't call preStart and schedule a new Tick
override def postRestart(reason: Throwable): Unit = ()
override def receive = {
case Tick =>
//val blk = BlockHelper.genesisBlockCreator()
//chaincode = IdTool.getCid(blk.transactions(0).getCid)
scheduler.scheduleOnce(10.seconds, self, TickInit)
case TickInit =>
if (SystemProfile.getTranCreateDur > 0)
scheduler.scheduleOnce(SystemProfile.getTranCreateDur.millis, self, TickInvoke)
case TickInvoke =>
try {
//createTransForLoop //在做tps测试到时候执行该函数并且注释其他代码
val t3 = createTransaction4Invoke(pe.getSysTag, chaincode,
"transfer", Seq(li2))
pe.getActorRef(ActorType.transactionpool) ! t3
RepLogger.trace(RepLogger.System_Logger,this.getLogMsgPrefix(s"########################create transaction id =${t3.id}"))
} catch {
case e: RuntimeException => throw e
}
scheduler.scheduleOnce(SystemProfile.getTranCreateDur.millis, self, TickInvoke)
}
//自动循环不间断提交交易到系统用于压力测试或者tps测试时使用
def createTransForLoop = {
var count: Int = 0;
if (pe.getSysTag == "121000005l35120456.node1"|| pe.getSysTag == "12110107bi45jh675g.node2" || pe.getSysTag=="122000002n00123567.node3" ||
pe.getSysTag=="921000005k36123789.node4" || pe.getSysTag=="921000006e0012v696.node5")
while (true) {
try {
val start = System.currentTimeMillis()
//val start = System.currentTimeMillis()
//todo 在运行时需要传送正确的chaincodename
//val chaincodeId = new ChaincodeId("chaincode-name", 1)
val t3 = createTransaction4Invoke(pe.getSysTag, chaincode,
"transfer", Seq(li2))
//pe.getActorRef(ActorType.transactionpool) ! t3
pe.getTransPoolMgr.putTran(t3,pe.getSysTag)
//mediator ! Publish(Topic.Transaction, t3)
//RepLogger.trace(RepLogger.System_Logger,this.getLogMsgPrefix(s"########################create transaction id =${t3.id}"))
count += 1
if (count > 1000) {
val end = System.currentTimeMillis()
RepLogger.trace(RepLogger.System_Logger,"send 1000 trans spent = " + (end - start))
//Thread.sleep(1000)
count = 0
}
//val end = System.currentTimeMillis()
//println(s"!!!!!!!!!!!!!!!!!!!!auto create trans time=${end-start}")
} catch {
case e: RuntimeException => throw e
}
}
}
}
/*
* 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.autotransaction
import akka.actor.Props
import akka.cluster.pubsub.DistributedPubSubMediator.Publish
import com.google.protobuf.ByteString
import com.google.protobuf.timestamp.Timestamp
import rep.app.conf.SystemProfile
import rep.crypto.cert.SignTool
import rep.log.RepLogger
import rep.network.base.ModuleBase
import rep.protos.peer._
import rep.utils.{IdTool, TimeUtils}
import rep.network.module.ModuleActorType
import rep.utils.GlobalUtils.EventType
/**
*
* 代理节点辅助类
* 用来定时生成Transaction
* 之后也应该通过其接收前端数据进而生成Transaction
*
* @author jiangbuyun
*/
object Topic {
val Transaction = "Transaction"
val Block = "Block"
val Event = "Event"
val Endorsement = "Endorsement"
}
object InnerTopic {
val BlockRestore = "BlockRestore"
}
object PeerHelper {
def props(name: String): Props = Props(classOf[PeerHelper], name)
case object Tick
case object TickInit
case object TickInvoke
case object TickQuery
/**
* 采用节点私钥创建交易的方法
*
*/
def createTransaction4Invoke(nodeName: String, chaincodeId: ChaincodeId,
chaincodeInputFunc: String, params: Seq[String]): Transaction = {
var t: Transaction = new Transaction()
val millis = TimeUtils.getCurrentTime()
if (chaincodeId == null) t
val txid = IdTool.getRandomUUID
val cip = new ChaincodeInput(chaincodeInputFunc, params)
t = t.withId(txid)
t = t.withCid(chaincodeId)
t = t.withIpt(cip)
t = t.withType(rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE)
t = t.clearSignature
val certid = IdTool.getCertIdFromName(nodeName)
var sobj = Signature(Option(certid), Option(Timestamp(millis / 1000, ((millis % 1000) * 1000000).toInt)))
sobj = sobj.withSignature(ByteString.copyFrom(SignTool.sign(nodeName, t.toByteArray)))
t = t.withSignature(sobj)
t
}
def createTransaction4Deploy(nodeName: String, chaincodeId: ChaincodeId,
spcPackage: String, legal_prose: String, timeout: Int,
ctype: rep.protos.peer.ChaincodeDeploy.CodeType): Transaction = {
var t: Transaction = new Transaction()
val millis = TimeUtils.getCurrentTime()
if (chaincodeId == null) t
val txid = IdTool.getRandomUUID
var cip = new ChaincodeDeploy(timeout)
cip = cip.withCodePackage(spcPackage)
cip = cip.withLegalProse(legal_prose)
cip = cip.withCtype(ctype)
t = t.withId(txid)
t = t.withCid(chaincodeId)
t = t.withSpec(cip)
t = t.withType(rep.protos.peer.Transaction.Type.CHAINCODE_DEPLOY)
t = t.clearSignature
val certid = IdTool.getCertIdFromName(nodeName)
var sobj = Signature(Option(certid), Option(Timestamp(millis / 1000, ((millis % 1000) * 1000000).toInt)))
sobj = sobj.withSignature(ByteString.copyFrom(SignTool.sign(nodeName, t.toByteArray)))
t = t.withSignature(sobj)
t
}
def createTransaction4State(nodeName: String, chaincodeId: ChaincodeId,
state:Boolean): Transaction = {
var t: Transaction = new Transaction()
val millis = TimeUtils.getCurrentTime()
if (chaincodeId == null) t
val txid = IdTool.getRandomUUID
t = t.withId(txid)
t = t.withCid(chaincodeId)
t = t.withType(rep.protos.peer.Transaction.Type.CHAINCODE_SET_STATE)
t = t.withState(state)
t = t.clearSignature
val certid = IdTool.getCertIdFromName(nodeName)
var sobj = Signature(Option(certid), Option(Timestamp(millis / 1000, ((millis % 1000) * 1000000).toInt)))
sobj = sobj.withSignature(ByteString.copyFrom(SignTool.sign(nodeName, t.toByteArray)))
t = t.withSignature(sobj)
t
}
}
class PeerHelper(name: String) extends ModuleBase(name) {
import PeerHelper._
import context.dispatcher
import scala.concurrent.duration._
//val si1 = scala.io.Source.fromFile("scripts/example_invoke_" + pe.getSysTag + ".js")
//val li1 = try si1.mkString finally si1.close()
val si2 = scala.io.Source.fromFile("api_req/json/transfer_" + pe.getSysTag + ".json","UTF-8")
val li2 = try si2.mkString finally si2.close()
//val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
var chaincode:ChaincodeId = new ChaincodeId("ContractAssetsTPL",1)
override def preStart(): Unit = {
//注册接收交易的广播
SubscribeTopic(mediator, self, selfAddr, Topic.Transaction, true)
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("Transaction Creator Start"))
scheduler.scheduleOnce(15.seconds, self, Tick)
}
// override postRestart so we don't call preStart and schedule a new Tick
override def postRestart(reason: Throwable): Unit = ()
override def receive = {
case Tick =>
//val blk = BlockHelper.genesisBlockCreator()
//chaincode = IdTool.getCid(blk.transactions(0).getCid)
scheduler.scheduleOnce(10.seconds, self, TickInit)
case TickInit =>
if (SystemProfile.getTranCreateDur > 0)
scheduler.scheduleOnce(SystemProfile.getTranCreateDur.millis, self, TickInvoke)
case TickInvoke =>
try {
//createTransForLoop //在做tps测试到时候执行该函数并且注释其他代码
val t3 = createTransaction4Invoke(pe.getSysTag, chaincode,
"transfer", Seq(li2))
mediator ! Publish(Topic.Transaction, t3)
sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION)
RepLogger.trace(RepLogger.System_Logger,this.getLogMsgPrefix(s"########################create transaction id =${t3.id}"))
} catch {
case e: RuntimeException => throw e
}
scheduler.scheduleOnce(SystemProfile.getTranCreateDur.millis, self, TickInvoke)
}
//自动循环不间断提交交易到系统用于压力测试或者tps测试时使用
def createTransForLoop = {
var count: Int = 0;
if (pe.getSysTag == "121000005l35120456.node1"|| pe.getSysTag == "12110107bi45jh675g.node2" || pe.getSysTag=="122000002n00123567.node3" ||
pe.getSysTag=="921000005k36123789.node4" || pe.getSysTag=="921000006e0012v696.node5")
while (true) {
try {
val start = System.currentTimeMillis()
//val start = System.currentTimeMillis()
//todo 在运行时需要传送正确的chaincodename
//val chaincodeId = new ChaincodeId("chaincode-name", 1)
val t3 = createTransaction4Invoke(pe.getSysTag, chaincode,
"transfer", Seq(li2))
//pe.getActorRef(ActorType.transactionpool) ! t3
pe.getTransPoolMgr.putTran(t3,pe.getSysTag)
//mediator ! Publish(Topic.Transaction, t3)
//RepLogger.trace(RepLogger.System_Logger,this.getLogMsgPrefix(s"########################create transaction id =${t3.id}"))
count += 1
if (count > 1000) {
val end = System.currentTimeMillis()
RepLogger.trace(RepLogger.System_Logger,"send 1000 trans spent = " + (end - start))
//Thread.sleep(1000)
count = 0
}
//val end = System.currentTimeMillis()
//println(s"!!!!!!!!!!!!!!!!!!!!auto create trans time=${end-start}")
} catch {
case e: RuntimeException => throw e
}
}
}
}

View File

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

View File

@ -1,110 +1,109 @@
/*
* 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.base
import akka.actor.{Actor, Address, ActorRef}
import rep.app.system.ClusterSystem
import rep.network.cluster.ClusterActor
import rep.network.tools.PeerExtension
import rep.crypto.Sha256
import scala.collection.mutable
import org.slf4j.LoggerFactory
import rep.log.RepTimeTracer
import rep.log.RepLogger
import rep.utils.GlobalUtils.{ActorType}
/**
* 模块基础类伴生对象
*
* @author shidianyue
* @version 1.0
*
* @update 2018-05 jiangbuyun
**/
object ModuleBase {
}
/**
* 系统模块基础类
*
* @author shidianyue
* @version 1.0
* @param name 模块名称
**/
abstract class ModuleBase(name: String) extends Actor with ClusterActor with BaseActor{
val pe = PeerExtension(context.system)
val atype = ModuleNameToIntActorType
atype match{
case 0 =>
case _ =>
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"--------Actor create,actor name=${name}"))
pe.register(atype, self)
}
private def ModuleNameToIntActorType:Int={
name match{
case "memberlistener" => 1
case "modulemanager" => 2
case "webapi" => 3
case "peerhelper" => 4
case "blocker" => 5
case "preloaderoftransaction" => 6
case "endorser" => 7
case "voter" => 8
case "synchrequester" => 9
case "transactionpool" => 10
case "storager" => 11
case "synchresponser" => 12
case "statiscollecter" => 13
case "endorsementcollectioner" => 14
//case "endorsementrequester" => 15
case "confirmerofblock" => 16
case "gensisblock" => 17
case "api" => 18
case "transactiondispatcher" => 19
case "dispatchofRecvendorsement" => 20
case "dispatchofpreload" => 21
case _ => 0
}
}
/**
* 日志前缀
*
*/
def getLogMsgPrefix(msg:String):String = {
s"${pe.getSysTag}~${this.name}~${msg}~"
}
/**
* 事件时间戳封装
* @param msg
* @param step
* @param actorRef
*/
def logTime(timetag:String,time:Long,isstart:Boolean,bheight:Long,trannum:Int): Unit = {
if(isstart){
RepTimeTracer.setStartTime(pe.getSysTag, timetag, time,bheight,trannum)
}else{
RepTimeTracer.setEndTime(pe.getSysTag, timetag, time,bheight,trannum)
}
}
}
/*
* 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.base
import akka.actor.{Actor, Address, ActorRef}
import rep.app.system.ClusterSystem
import rep.network.cluster.ClusterActor
import rep.network.tools.PeerExtension
import rep.crypto.Sha256
import scala.collection.mutable
import org.slf4j.LoggerFactory
import rep.log.RepTimeTracer
import rep.log.RepLogger
/**
* 模块基础类伴生对象
*
* @author shidianyue
* @version 1.0
*
* @update 2018-05 jiangbuyun
**/
object ModuleBase {
}
/**
* 系统模块基础类
*
* @author shidianyue
* @version 1.0
* @param name 模块名称
**/
abstract class ModuleBase(name: String) extends Actor with ClusterActor with BaseActor{
val pe = PeerExtension(context.system)
/*val atype = ModuleNameToIntActorType
atype match{
case 0 =>
case _ =>
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"--------Actor create,actor name=${name}"))
pe.register(atype, self)
}*/
/*private def ModuleNameToIntActorType:Int={
name match{
case "memberlistener" => 1
case "modulemanager" => 2
case "webapi" => 3
case "peerhelper" => 4
case "blocker" => 5
case "preloaderoftransaction" => 6
case "endorser" => 7
case "voter" => 8
case "synchrequester" => 9
case "transactionpool" => 10
case "storager" => 11
case "synchresponser" => 12
case "statiscollecter" => 13
case "endorsementcollectioner" => 14
//case "endorsementrequester" => 15
case "confirmerofblock" => 16
case "gensisblock" => 17
case "api" => 18
case "transactiondispatcher" => 19
case "dispatchofRecvendorsement" => 20
case "dispatchofpreload" => 21
case _ => 0
}
}*/
/**
* 日志前缀
*
*/
def getLogMsgPrefix(msg:String):String = {
s"${pe.getSysTag}~${this.name}~${msg}~"
}
/**
* 事件时间戳封装
* @param msg
* @param step
* @param actorRef
*/
def logTime(timetag:String,time:Long,isstart:Boolean,bheight:Long,trannum:Int): Unit = {
if(isstart){
RepTimeTracer.setStartTime(pe.getSysTag, timetag, time,bheight,trannum)
}else{
RepTimeTracer.setEndTime(pe.getSysTag, timetag, time,bheight,trannum)
}
}
}

View File

@ -0,0 +1,137 @@
package rep.network.cache
import akka.actor.{Address, Props}
import rep.app.conf.SystemProfile
import rep.crypto.cert.SignTool
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.protos.peer.{Event, Transaction}
import rep.storage.ImpDataAccess
import rep.utils.ActorUtils
import rep.utils.GlobalUtils.EventType
/**
* Created by jiangbuyun on 2020/03/19.
* 抽象的交易池actor
*/
object ITransactionPool{
def props(name: String): Props = Props(classOf[ITransactionPool], name)
//交易检查结果
case class CheckedTransactionResult(result: Boolean, msg: String)
}
abstract class ITransactionPool (moduleName: String) extends ModuleBase(moduleName) {
import akka.actor.ActorSelection
private val transPoolActorName = "/user/modulemanager/transactionpool"
private var addr4NonUser = ""
val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag)
override def preStart(): Unit = {
//注册接收交易的广播
SubscribeTopic(mediator, self, selfAddr, Topic.Transaction, true)
}
def toAkkaUrl(sn: Address, actorName: String): String = {
return sn.toString + "/" + actorName;
}
def visitStoreService(sn: Address, actorName: String, t1: Transaction) = {
try {
val selection: ActorSelection = context.actorSelection(toAkkaUrl(sn, actorName));
selection ! t1
} catch {
case e: Exception => e.printStackTrace()
}
}
/**
* 检查交易是否符合规则
* @param t
* @param dataAccess
* @return
*/
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"
} else {
result = true
}
} else {
resultMsg = s"The transaction(${t.id}) is not completed"
}
} catch {
case e: RuntimeException => throw e
}
}else{
result = true
}
CheckedTransactionResult(result, resultMsg)
}
protected def sendVoteMessage:Unit
private def addTransToCache(t: Transaction) = {
val checkedTransactionResult = checkTransaction(t, dataaccess)
//签名验证成功
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) = {
if (this.addr4NonUser == "" && this.selfAddr.indexOf("/user") > 0) {
this.addr4NonUser = this.selfAddr.substring(0, this.selfAddr.indexOf("/user"))
}
pe.getNodeMgr.getStableNodes.foreach(f => {
if (this.addr4NonUser != "" && !NodeHelp.isSameNode(f.toString, this.addr4NonUser)) {
visitStoreService(f, this.transPoolActorName, t)
}
})
}
override def receive = {
//处理接收的交易
case t: Transaction =>
//保存交易到本地
sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION)
addTransToCache(t)
//广播交易到其他共识节点
if (ActorUtils.isHelper(sender().path.toString) || ActorUtils.isAPI(sender().path.toString)) {
//广播交易
publishTrans(t)
RepLogger.trace(RepLogger.System_Logger,this.getLogMsgPrefix(s"${pe.getSysTag} recv self created tran,txid=${t.id}"))
//广播发送交易事件
sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION)
} else{
RepLogger.trace(RepLogger.System_Logger,this.getLogMsgPrefix(s"${pe.getSysTag} recv broadcast tran,txid=${t.id}"))
}
case _ => //ignore
}
}

View File

@ -0,0 +1,84 @@
package rep.network.cache
import akka.actor.Props
import rep.app.conf.SystemProfile
import rep.crypto.cert.SignTool
import rep.log.RepLogger
import rep.network.autotransaction.Topic
import rep.network.base.ModuleBase
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
import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker
object TransactionChecker{
def props(name: String): Props = Props(classOf[TransactionChecker], name)
case class CheckedTransactionResult(result: Boolean, msg: String)
}
class TransactionChecker (moduleName: String) extends ModuleBase(moduleName){
val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag)
/**
* 检查交易是否符合规则
* @param t
* @param dataAccess
* @return
*/
def checkTransaction(t: Transaction, dataAccess: ImpDataAccess): TransactionChecker.CheckedTransactionResult = {
var resultMsg = ""
var result = false
if(SystemProfile.getHasPreloadTransOfApi){
val sig = t.getSignature
val tOutSig = t.clearSignature
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"
} else {
result = true
}
} else {
resultMsg = s"The transaction(${t.id}) is not completed"
}
} catch {
case e: RuntimeException => throw e
}
}else{
result = true
}
TransactionChecker.CheckedTransactionResult(result, resultMsg)
}
private def addTransToCache(t: Transaction) = {
val checkedTransactionResult = checkTransaction(t, dataaccess)
//签名验证成功
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 (poolIsEmpty)//加入交易之前交易池为空发送抽签消息
pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker
}
}
override def receive = {
//处理接收的交易
case t: Transaction =>
//保存交易到本地
sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION)
addTransToCache(t)
case _ => //ignore
}
}

View File

@ -0,0 +1,50 @@
package rep.network.cache
import akka.actor.Props
import akka.routing.{ActorRefRoutee, Routee, Router, SmallestMailboxRoutingLogic}
import rep.app.conf.SystemProfile
import rep.log.RepLogger
import rep.network.autotransaction.Topic
import rep.network.base.ModuleBase
import rep.network.consensus.cfrd.endorse.Endorser4Future
import rep.protos.peer.{Event, Transaction}
import rep.utils.ActorUtils
import rep.utils.GlobalUtils.EventType
import scala.collection.immutable.IndexedSeq
object TransactionOfCollectioner{
def props(name: String): Props = Props(classOf[TransactionOfCollectioner], name)
}
class TransactionOfCollectioner (moduleName: String) extends ModuleBase(moduleName){
private var router: Router = null
override def preStart(): Unit = {
//注册接收交易的广播
SubscribeTopic(mediator, self, selfAddr, Topic.Transaction, true)
}
private def createRouter = {
if (router == null) {
var list: Array[Routee] = new Array[Routee](SystemProfile.getVoteNodeList.size())
for (i <- 0 to SystemProfile.getVoteNodeList.size() - 1) {
var ca = context.actorOf(TransactionChecker.props("transactionchecker" + i), "transactionchecker" + i)
context.watch(ca)
list(i) = new ActorRefRoutee(ca)
}
val rlist: IndexedSeq[Routee] = list.toIndexedSeq
router = Router(SmallestMailboxRoutingLogic(), rlist)
}
}
override def receive = {
//处理接收的交易
case t: Transaction =>
createRouter
router.route(t,self)
case _ => //ignore
}
}

View File

@ -1,151 +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.cache
import java.security.cert.Certificate
import com.google.protobuf.ByteString
import akka.actor.{ Actor, Address, Props }
import akka.cluster.pubsub.DistributedPubSubMediator.Publish
import rep.app.conf.SystemProfile
import rep.crypto.cert.SignTool
import rep.network.{ Topic }
import rep.network.base.ModuleBase
import rep.network.cache.TransactionPool.CheckedTransactionResult
import rep.network.consensus.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
/**
* 交易缓冲池伴生对象
*
* @author shidianyue
* @version 1.0
*/
object TransactionPool {
def props(name: String): Props = Props(classOf[TransactionPool], name)
//交易检查结果
case class CheckedTransactionResult(result: Boolean, msg: String)
}
/**
* 交易缓冲池类
*
* @author shidianyue
* @version 1.0
* @param moduleName
*/
class TransactionPool(moduleName: String) extends ModuleBase(moduleName) {
import akka.actor.ActorSelection
val dataaccess: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag)
override def preStart(): Unit = {
//注册接收交易的广播
SubscribeTopic(mediator, self, selfAddr, Topic.Transaction, true)
}
def toAkkaUrl(sn: Address, actorName: String): String = {
return sn.toString + "/" + actorName;
}
def visitStoreService(sn: Address, actorName: String, t1: Transaction) = {
try {
val selection: ActorSelection = context.actorSelection(toAkkaUrl(sn, actorName));
selection ! t1
} catch {
case e: Exception => e.printStackTrace()
}
}
/**
* 检查交易是否符合规则
* @param t
* @param dataAccess
* @return
*/
def checkTransaction(t: Transaction, dataAccess: ImpDataAccess): CheckedTransactionResult = {
var resultMsg = ""
var result = false
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)) {
dataAccess.isExistTrans4Txid(t.id) match {
case false => result = true
case true => resultMsg = s"The transaction(${t.id}) is duplicated with txid"
}
} else {
resultMsg = s"The transaction(${t.id}) is not completed"
}
} catch {
case e: RuntimeException => throw e
}
CheckedTransactionResult(result, resultMsg)
}
override def receive = {
//处理接收的交易
case t: Transaction =>
//我们在这里并不缓存该Transaction在接收到同级别的广播时再进行缓存
// mediator ! Publish(Topic.Transaction, t)
//pe.getStableNodes.foreach(sn=>{
// visitStoreService(sn , "/user/moduleManager/transactionPool",t)
//})
if (ActorUtils.isHelper(sender().path.toString) ||
ActorUtils.isAPI(sender().path.toString)) {
//广播交易
mediator ! Publish(Topic.Transaction, t)
//广播发送交易事件
sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION)
} else {
//交易缓存,这里默认各个节点的交易缓存都是一致的但是因为入网时间不一致所有可能会有区别最终以出块人的交易为准
//TODO kami 验证交易签名和证书
//val checkedTransactionResult = CheckedTransactionResult(true, "")
sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Transaction, Event.Action.TRANSACTION)
val checkedTransactionResult = checkTransaction(t, dataaccess)
if (checkedTransactionResult.result) {
//签名验证成功
if (pe.getTransPoolMgr.getTransLength() < 100)
RepLogger.trace(RepLogger.System_Logger, this.getLogMsgPrefix(s"<<<<<<<<<<<<<>>>>>>>>>transaction=${pe.getTransPoolMgr.getTransLength()}"))
if (SystemProfile.getMaxCacheTransNum == 0 || pe.getTransPoolMgr.getTransLength() < SystemProfile.getMaxCacheTransNum) {
pe.getTransPoolMgr.putTran(t,pe.getSysTag)
//广播接收交易事件
if (pe.getTransPoolMgr.getTransLength() >= SystemProfile.getMinBlockTransNum)
pe.getActorRef(GlobalUtils.ActorType.voter) ! VoteOfBlocker
}
}
}
case _ => //ignore
}
}

View File

@ -0,0 +1,22 @@
package rep.network.cache.cfrd
import akka.actor.Props
import rep.network.cache.ITransactionPool
import rep.network.module.cfrd.CFRDActorType
import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker
/**
* Created by jiangbuyun on 2020/03/19.
* CFRD共识的确认块actor
*/
object TransactionPoolOfCFRD{
def props(name: String): Props = Props(classOf[TransactionPoolOfCFRD], name)
}
class TransactionPoolOfCFRD (moduleName: String) extends ITransactionPool(moduleName){
override protected def sendVoteMessage: Unit = {
pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.
*
*/
//zhj
package rep.network.cache.pbft
import akka.actor.Props
import rep.network.cache.ITransactionPool
import rep.network.consensus.pbft.MsgOfPBFT
import rep.network.consensus.pbft.MsgOfPBFT.VoteOfBlocker
import rep.network.consensus.pbft.vote.VoterOfPBFT
import rep.network.module.ModuleActorType
import rep.network.module.pbft.PBFTActorType
/**
* 交易缓冲池伴生对象
*
* @author shidianyue
* @version 1.0
*/
object TransactionPoolOfPBFT {
def props(name: String): Props = Props(classOf[TransactionPoolOfPBFT], name)
//交易检查结果
case class CheckedTransactionResult(result: Boolean, msg: String)
}
/**
* 交易缓冲池类
*
* @author shidianyue
* @version 1.0
* @param moduleName
*/
class TransactionPoolOfPBFT(moduleName: String) extends ITransactionPool(moduleName) {
override protected def sendVoteMessage: Unit = {
pe.getActorRef(PBFTActorType.ActorType.voter) ! VoteOfBlocker("cache")
}
}

View File

@ -0,0 +1,22 @@
package rep.network.cache.raft
import akka.actor.Props
import rep.network.cache.ITransactionPool
import rep.network.module.cfrd.CFRDActorType
import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker
/**
* Created by jiangbuyun on 2020/03/19.
* RAFT共识的确认块actor
*/
object TransactionPoolOfRAFT{
def props(name: String): Props = Props(classOf[TransactionPoolOfRAFT], name)
}
class TransactionPoolOfRAFT (moduleName: String) extends ITransactionPool(moduleName){
override protected def sendVoteMessage: Unit = {
pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker
}
}

View File

@ -18,11 +18,11 @@ package rep.network.cluster
import akka.actor.{Actor, ActorRef}
import akka.cluster.pubsub.DistributedPubSubMediator.{Publish, Subscribe}
import rep.network.Topic
import rep.protos.peer.Event
import rep.utils.ActorUtils
import rep.utils.GlobalUtils.EventType
import rep.app.conf.SystemProfile
import rep.network.autotransaction.Topic
/**
* Akka组网类

View File

@ -1,193 +1,216 @@
/*
* 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.cluster
import akka.actor.{Actor, Address,Props}
import akka.cluster.ClusterEvent._
import akka.cluster.pubsub.DistributedPubSub
import akka.cluster.{Cluster, MemberStatus}
import rep.app.conf.TimePolicy
import rep.app.conf.SystemProfile
import rep.network.Topic
import rep.network.cluster.MemberListener.{ Recollection}
import rep.network.tools.PeerExtension
import rep.utils.GlobalUtils.{ActorType,EventType}
import rep.utils.{ TimeUtils}
import org.slf4j.LoggerFactory
import scala.collection.mutable.HashMap
import rep.network.base.ModuleBase
import rep.network.sync.SyncMsg.StartSync
import scala.util.control.Breaks._
import scala.collection.mutable.ArrayBuffer
import rep.log.RepLogger
import rep.protos.peer.Event
import rep.network.util.NodeHelp
/**
* Cluster节点状态监听模块
*
* @author shidianyue
* @version 1.0
* @update 2018-05 jiangbuyun
**/
object MemberListener {
def props(name: String): Props = Props(classOf[MemberListener], name)
//稳定节点回收请求
case object Recollection
}
/**
* Cluster节点状态监听类
*
* @author shidianyue
* @version 1.0
* @since 1.0
**/
class MemberListener(MoudleName:String) extends ModuleBase(MoudleName) with ClusterActor {
import context.dispatcher
import scala.concurrent.duration._
protected def log = LoggerFactory.getLogger(this.getClass)
val addr_self = akka.serialization.Serialization.serializedActorPath(self)
val cluster = Cluster(context.system)
var preloadNodesMap = HashMap[ Address, (Long,String) ]()
private var isStartSynch = false
override def preStart(): Unit =
super.preStart()
cluster.subscribe(self, classOf[ MemberEvent ])
context.system.eventStream.subscribe(self, classOf[ akka.remote.DisassociatedEvent ])
SubscribeTopic(mediator, self, addr_self, Topic.Event, false)
/**
* 节点状态是否稳定
* @param srcTime
* @param dur
* @return
*/
def isStableNode(srcTime: Long, dur: Long): Boolean = {
(TimeUtils.getCurrentTime() - srcTime) > dur
}
override def postStop(): Unit =
cluster unsubscribe self
def receive = {
//系统初始化时状态
case state: CurrentClusterState =>
RepLogger.trace(RepLogger.System_Logger, this.getLogMsgPrefix("Member call first time"))
var nodes = Set.empty[ Address ]
var snodes = new ArrayBuffer[(Address ,String)]()
state.members.foreach(m=>{
if (m.status == MemberStatus.Up){
nodes += m.address
if(NodeHelp.isCandidatorNode(m.roles)){
snodes.append((m.address,NodeHelp.getNodeName(m.roles)))
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"CurrentClusterState: nodes is candidator,node name =${NodeHelp.getNodeName(m.roles)}"))
sendEvent(EventType.PUBLISH_INFO, mediator, NodeHelp.getNodeName(m.roles), Topic.Event, Event.Action.MEMBER_UP)
}else{
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"CurrentClusterState: nodes is candidator,node name =${m.address.toString}"))
}
}
})
pe.getNodeMgr.resetNodes(nodes)
pe.getNodeMgr.resetStableNodes(snodes.toSet)
//成员入网
case MemberUp(member) =>
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("Member is Up: {}. {} nodes in cluster"+"~"+member.address+"~"+pe.getNodeMgr.getNodes.mkString("|")))
pe.getNodeMgr.putNode(member.address)
if(member.roles != null && !member.roles.isEmpty && NodeHelp.isCandidatorNode(member.roles)){
preloadNodesMap.put(member.address, (TimeUtils.getCurrentTime(),NodeHelp.getNodeName(member.roles)))
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Member is Up: nodes is condidator,node name=${NodeHelp.getNodeName(member.roles)}"))
sendEvent(EventType.PUBLISH_INFO, mediator, NodeHelp.getNodeName(member.roles), Topic.Event, Event.Action.MEMBER_UP)
}else{
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Member is Up: nodes is not condidator,node address=${member.address.toString}"))
}
scheduler.scheduleOnce(TimePolicy.getSysNodeStableDelay+TimePolicy.getStableTimeDur millis,self, Recollection)
//稳定节点收集
case Recollection =>
RepLogger.trace(RepLogger.System_Logger, this.getLogMsgPrefix(" MemberListening recollection"))
preloadNodesMap.foreach(node => {
if (isStableNode(node._2._1, TimePolicy.getSysNodeStableDelay)) {
pe.getNodeMgr.putStableNode(node._1,node._2._2)
if(!this.isStartSynch){
if(pe.getNodeMgr.getStableNodes.size >= SystemProfile.getVoteNoteMin){
//组网成功之后开始系统同步
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: system startup ,start sync,node name=${node._2._2}"))
pe.getActorRef(ActorType.synchrequester) ! StartSync(true)
this.isStartSynch = true
}else{
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: nodes less ${SystemProfile.getVoteNoteMin},node name=${node._2._2}"))
}
}else{
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: local consensus start finish,node name=${node._2._2}"))
}
}else{
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: nodes not stable,node name=${node._2._2}"))
}
})
if (preloadNodesMap.size > 0){
pe.getNodeMgr.getStableNodes.foreach(node => {
if (preloadNodesMap.contains(node)) {
preloadNodesMap.remove(node)
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: clear preloadnodemap,node=${node}"))
}
})
}
if (preloadNodesMap.size > 0) self ! Recollection
//成员离网
case MemberRemoved(member, _) =>
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("Member is Removed: {}. {} nodes cluster"+"~"+member.address))
preloadNodesMap.remove(member.address)
pe.getNodeMgr.removeNode(member.address)
pe.getNodeMgr.removeStableNode(member.address)
sendEvent(EventType.PUBLISH_INFO, mediator, NodeHelp.getNodeName(member.roles), Topic.Event, Event.Action.MEMBER_DOWN)
case event: akka.remote.DisassociatedEvent => //ignore
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("DisassociatedEvent: {}. {} nodes cluster"+"~"+event.remoteAddress.toString))
preloadNodesMap.remove(event.remoteAddress)
pe.getNodeMgr.removeNode(event.remoteAddress)
pe.getNodeMgr.removeStableNode(event.remoteAddress)
case MemberLeft(member) => //ignore
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("MemberLeft: {}. {} nodes cluster"+"~"+member.address.toString))
preloadNodesMap.remove(member.address)
pe.getNodeMgr.removeNode(member.address)
pe.getNodeMgr.removeStableNode(member.address)
case MemberExited(member) => //ignore
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("MemberExited: {}. {} nodes cluster"+"~"+member.address.toString))
preloadNodesMap.remove(member.address)
pe.getNodeMgr.removeNode(member.address)
pe.getNodeMgr.removeStableNode(member.address)
case _: MemberEvent => // ignore
}
/*
* 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.cluster
import akka.actor.{Actor, Address, Props}
import akka.cluster.ClusterEvent._
import akka.cluster.pubsub.DistributedPubSub
import akka.cluster.{Cluster, MemberStatus}
import rep.app.conf.TimePolicy
import rep.app.conf.SystemProfile
import rep.network.cluster.MemberListener.Recollection
import rep.network.module.cfrd.CFRDActorType
import rep.utils.GlobalUtils.EventType
import rep.utils.TimeUtils
import org.slf4j.LoggerFactory
import scala.collection.mutable.HashMap
import rep.network.base.ModuleBase
import rep.network.sync.SyncMsg.StartSync
import scala.util.control.Breaks._
import scala.collection.mutable.ArrayBuffer
import rep.log.RepLogger
import rep.protos.peer.Event
import rep.network.util.NodeHelp
import rep.app.RepChainMgr
import rep.network.autotransaction.Topic
import rep.network.consensus.byzantium.ConsensusCondition
/**
* Cluster节点状态监听模块
*
* @author shidianyue
* @version 1.0
* @update 2018-05 jiangbuyun
*/
object MemberListener {
def props(name: String): Props = Props(classOf[MemberListener], name)
//稳定节点回收请求
case object Recollection
}
/**
* Cluster节点状态监听类
*
* @author shidianyue
* @version 1.0
* @since 1.0
*/
class MemberListener(MoudleName: String) extends ModuleBase(MoudleName) with ClusterActor {
import context.dispatcher
import scala.concurrent.duration._
protected def log = LoggerFactory.getLogger(this.getClass)
val addr_self = akka.serialization.Serialization.serializedActorPath(self)
val cluster = Cluster(context.system)
var preloadNodesMap = HashMap[Address, (Long, String)]()
private var isStartSynch = false
override def preStart(): Unit =
super.preStart()
cluster.subscribe(self, classOf[MemberEvent])
cluster.subscribe(self,classOf[ClusterDomainEvent])
//context.system.eventStream.subscribe(self, classOf[akka.remote.DisassociatedEvent])
//SubscribeTopic(mediator, self, addr_self, Topic.Event, false)
/**
* 节点状态是否稳定
* @param srcTime
* @param dur
* @return
*/
def isStableNode(srcTime: Long, dur: Long): Boolean = {
(TimeUtils.getCurrentTime() - srcTime) > dur
}
override def postStop(): Unit =
cluster unsubscribe self
def receive = {
//系统初始化时状态
case state: CurrentClusterState =>
RepLogger.trace(RepLogger.System_Logger, this.getLogMsgPrefix("Member call first time"))
var nodes = Set.empty[Address]
var snodes = new ArrayBuffer[(Address, String)]()
state.members.foreach(m => {
if (m.status == MemberStatus.Up) {
nodes += m.address
if (NodeHelp.isCandidatorNode(m.roles)) {
snodes.append((m.address, NodeHelp.getNodeName(m.roles)))
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"CurrentClusterState: nodes is candidator,node name =${NodeHelp.getNodeName(m.roles)}"))
sendEvent(EventType.PUBLISH_INFO, mediator, NodeHelp.getNodeName(m.roles), Topic.Event, Event.Action.MEMBER_UP)
} else {
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"CurrentClusterState: nodes is candidator,node name =${m.address.toString}"))
}
}
})
pe.getNodeMgr.resetNodes(nodes)
pe.getNodeMgr.resetStableNodes(snodes.toSet)
//成员入网
case MemberUp(member) =>
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("Member is Up: {}. {} nodes in cluster" + "~" + member.address + "~" + pe.getNodeMgr.getNodes.mkString("|")))
pe.getNodeMgr.putNode(member.address)
if (member.roles != null && !member.roles.isEmpty && NodeHelp.isCandidatorNode(member.roles)) {
preloadNodesMap.put(member.address, (TimeUtils.getCurrentTime(), NodeHelp.getNodeName(member.roles)))
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Member is Up: nodes is condidator,node name=${NodeHelp.getNodeName(member.roles)}"))
sendEvent(EventType.PUBLISH_INFO, mediator, NodeHelp.getNodeName(member.roles), Topic.Event, Event.Action.MEMBER_UP)
} else {
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Member is Up: nodes is not condidator,node address=${member.address.toString}"))
}
schedulerLink = scheduler.scheduleOnce((
//TimePolicy.getSysNodeStableDelay +
TimePolicy.getStableTimeDur).millis, self, Recollection)
//稳定节点收集
case Recollection =>
schedulerLink = clearSched()
RepLogger.trace(RepLogger.System_Logger, this.getLogMsgPrefix(" MemberListening recollection"))
preloadNodesMap.foreach(node => {
if (isStableNode(node._2._1, TimePolicy.getSysNodeStableDelay)) {
pe.getNodeMgr.putStableNode(node._1, node._2._2)
} else {
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: nodes not stable,node name=${node._2._2}"))
}
})
if (preloadNodesMap.size > 0) {
pe.getNodeMgr.getStableNodes.foreach(node => {
if (preloadNodesMap.contains(node)) {
preloadNodesMap.remove(node)
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: clear preloadnodemap,node=${node}"))
}
})
}
if (!this.isStartSynch) {
if (ConsensusCondition.CheckWorkConditionOfSystem(pe.getNodeMgr.getStableNodes.size)) {
//组网成功之后开始系统同步
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: system startup ,start sync,node name=${pe.getSysTag}"))
pe.getActorRef(CFRDActorType.ActorType.synchrequester) ! StartSync(true)
this.isStartSynch = true
} else {
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: nodes less ${SystemProfile.getVoteNodeMin},node name=${pe.getSysTag}"))
}
} else {
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix(s"Recollection: local consensus start finish,node name=${pe.getSysTag}"))
}
if (preloadNodesMap.size > 0) {
//self ! Recollection
schedulerLink = scheduler.scheduleOnce((
TimePolicy.getStableTimeDur/5).millis, self, Recollection)
}
//成员离网
case MemberRemoved(member, _) =>
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("Member is Removed: {}. {} nodes cluster" + "~" + member.address))
System.err.println(s"MemberRemoved:printer=${pe.getSysTag} ~~ removed=${pe.getNodeMgr.getNodeName4AddrString(member.address.toString)}")
val tmp = pe.getNodeMgr.getNodeName4AddrString(member.address.toString)
if(tmp.equals(pe.getSysTag)){
RepChainMgr.ReStart(pe.getSysTag)
}
preloadNodesMap.remove(member.address)
pe.getNodeMgr.removeNode(member.address)
pe.getNodeMgr.removeStableNode(member.address)
sendEvent(EventType.PUBLISH_INFO, mediator, NodeHelp.getNodeName(member.roles), Topic.Event, Event.Action.MEMBER_DOWN)
/*case event: akka.remote.DisassociatedEvent => //ignore
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("DisassociatedEvent: {}. {} nodes cluster" + "~" + event.remoteAddress.toString))
preloadNodesMap.remove(event.remoteAddress)
pe.getNodeMgr.removeNode(event.remoteAddress)
pe.getNodeMgr.removeStableNode(event.remoteAddress)*/
case MemberLeft(member) => //ignore
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("MemberLeft: {}. {} nodes cluster" + "~" + member.address.toString))
/*preloadNodesMap.remove(member.address)
pe.getNodeMgr.removeNode(member.address)
pe.getNodeMgr.removeStableNode(member.address)*/
case MemberExited(member) => //ignore
RepLogger.info(RepLogger.System_Logger, this.getLogMsgPrefix("MemberExited: {}. {} nodes cluster" + "~" + member.address.toString))
/*preloadNodesMap.remove(member.address)
pe.getNodeMgr.removeNode(member.address)
pe.getNodeMgr.removeStableNode(member.address)*/
case _: MemberEvent => // ignore
}
}

View File

@ -0,0 +1,78 @@
package rep.network.confirmblock
import akka.actor.{ActorRef, Props}
import akka.util.Timeout
import rep.log.{RepLogger, RepTimeTracer}
import rep.network.base.ModuleBase
import rep.network.consensus.common.MsgOfConsensus.{ConfirmedBlock}
import rep.network.consensus.util.BlockVerify
import scala.concurrent._
/**
* Created by jiangbuyun on 2020/03/19.
* 抽象的确认块actor
*/
object IConfirmOfBlock{
def props(name: String): Props = Props(classOf[IConfirmOfBlock], name)
}
abstract class IConfirmOfBlock(moduleName: String) extends ModuleBase(moduleName) {
import context.dispatcher
import scala.concurrent.duration._
import rep.protos.peer._
implicit val timeout = Timeout(3.seconds)
protected def asyncVerifyEndorse(e: Signature, byteOfBlock: Array[Byte]): Future[Boolean] = {
val result = Promise[Boolean]
val tmp = BlockVerify.VerifyOneEndorseOfBlock(e, byteOfBlock, pe.getSysTag)
if (tmp._1) {
result.success(true)
} else {
result.success(false)
}
result.future
}
protected def asyncVerifyEndorses(block: Block): Boolean = {
val b = block.clearEndorsements.toByteArray
val listOfFuture: Seq[Future[Boolean]] = block.endorsements.map(x => {
asyncVerifyEndorse(x, b)
})
val futureOfList: Future[List[Boolean]] = Future.sequence(listOfFuture.toList).recover({
case e: Exception =>
null
})
val result1 = Await.result(futureOfList, timeout.duration).asInstanceOf[List[Boolean]]
var result = true
if (result1 == null) {
false
} else {
result1.foreach(f => {
if (!f) {
result = false
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"comfirmOfBlock verify endorse is error, break,block height=${block.height},local height=${pe.getCurrentHeight}"))
}
})
}
result
}
protected def handler(block: Block, actRefOfBlock: ActorRef)
protected def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef)
override def receive = {
case ConfirmedBlock(block, actRefOfBlock) =>
RepTimeTracer.setStartTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size)
checkedOfConfirmBlock(block, actRefOfBlock)
RepTimeTracer.setEndTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size)
case _ => //ignore
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.byzantium.ConsensusCondition
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 (ConsensusCondition.ConsensusConditionChecked(block.endorsements.size)) {
//符合大多数人背书要求
handler(block, actRefOfBlock)
} else {
//错误没有符合大多人背书要求
}
}
}
}

View File

@ -0,0 +1,170 @@
/*
* 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.
*
*/
//zhj
package rep.network.confirmblock.pbft
import akka.actor.{ActorRef, Props}
import akka.util.Timeout
import rep.app.Repchain
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
import rep.network.consensus.common.MsgOfConsensus.{BatchStore, BlockRestore}
import rep.network.consensus.pbft.MsgOfPBFT
import rep.network.consensus.util.BlockVerify
import rep.network.module.ModuleActorType.ActorType
import rep.network.persistence.IStorager.SourceOfBlock
import rep.utils.GlobalUtils.EventType
import scala.concurrent._
object ConfirmOfBlockOfPBFT {
def props(name: String): Props = Props(classOf[ConfirmOfBlockOfPBFT], name)
}
class ConfirmOfBlockOfPBFT(moduleName: String) extends IConfirmOfBlock(moduleName) {
import context.dispatcher
private var lastBlockTime = System.currentTimeMillis()
private var transCount = 0
private var tpsstr = ""
override def preStart(): Unit = {
RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("confirm Block module start"))
SubscribeTopic(mediator, self, selfAddr, Topic.Block, false)
}
import rep.protos.peer._
import scala.concurrent.duration._
case class DataSig(data:Array[Byte], sig : Signature)
private def asyncVerifyEndorses(block: Block, replies : Seq[MPbftReply]): Boolean = {
val b = block.clearEndorsements.toByteArray
val ds = scala.collection.mutable.Buffer[DataSig]()
replies.foreach( r => {
ds += DataSig(r.clearSignature.toByteArray, r.signature.get)
for (c <- r.commits) {
ds += DataSig(c.clearSignature.toByteArray, c.signature.get)
c.prepares.foreach(p=>{
ds += DataSig(b, p.signature.get)
})
}
})
/*val listOfFuture: Seq[Future[Boolean]] = block.endorsements.map(x => {
asyncVerifyEndorse(x, b)
}) */
val listOfFuture: Seq[Future[Boolean]] = ds.map(x => {
asyncVerifyEndorse(x.sig, x.data)
})
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) {
result = 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): Unit ={
RepLogger.error(RepLogger.Consensus_Logger,pe.getSysTag + ", Internal error, ConfirmOfBlockOfPBFT.handler")
}
private def handler(block: Block, actRefOfBlock: ActorRef, replies : Seq[MPbftReply]) = {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement start,height=${block.height}"))
var b = true
if (SystemProfile.getIsVerifyOfEndorsement)
b = asyncVerifyEndorses(block,replies)
if (b) {
transCount += block.transactions.size
val ms = System.currentTimeMillis()
val delta = ms - lastBlockTime
if (delta > 300000) {
val tps = transCount *1000 / delta
tpsstr += tps + ", "
RepLogger.debug(RepLogger.zLogger,pe.getSysTag + ", TPS=" + tpsstr)
transCount = 0;
lastBlockTime = System.currentTimeMillis()
}
pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock))
pe.getActorRef(ActorType.storager) ! BatchStore
sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW)
}
}
override protected def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef): Unit ={
RepLogger.error(RepLogger.Consensus_Logger,pe.getSysTag + ", Internal error, ConfirmOfBlockOfPBFT.checkedOfConfirmBlock")
}
private def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef, replies : Seq[MPbftReply]) = {
if (pe.getCurrentBlockHash == "" && block.previousBlockHash.isEmpty()) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}"))
handler(block, actRefOfBlock, replies)
} 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) ! SyncRequestOfStorager(sender,block.height)
} else {
handler(block, actRefOfBlock)
pe.setConfirmHeight(block.height)
}
} else { */
if ( replies.size >= (SystemProfile.getPbftF + 1))
handler(block, actRefOfBlock, replies)
//}
}
}
override def receive = {
//Endorsement block
case MsgOfConsensus.ConfirmedBlock(block, actRefOfBlock) =>
RepLogger.debug(RepLogger.zLogger,"R: " + Repchain.nn(sender) + "->" + Repchain.nn(pe.getSysTag) + ", ConfirmedBlock(2p): " + ", " + Repchain.h4(block.hashOfBlock.toStringUtf8))
RepTimeTracer.setStartTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size)
checkedOfConfirmBlock(block, actRefOfBlock, Seq.empty)
RepTimeTracer.setEndTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size)
case MsgOfPBFT.ConfirmedBlock(block, actRefOfBlock, replies) =>
RepLogger.debug(RepLogger.zLogger,"R: " + Repchain.nn(sender) + "->" + Repchain.nn(pe.getSysTag) + ", ConfirmedBlock: " + ", " + Repchain.h4(block.hashOfBlock.toStringUtf8))
RepTimeTracer.setStartTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size)
checkedOfConfirmBlock(block, actRefOfBlock, replies)
RepTimeTracer.setEndTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size)
case _ => //ignore
}
}

View File

@ -0,0 +1,68 @@
package rep.network.confirmblock.raft
import akka.actor.{ActorRef, Props}
import rep.app.conf.SystemProfile
import rep.log.RepLogger
import rep.network.autotransaction.Topic
import rep.network.confirmblock.IConfirmOfBlock
import rep.network.consensus.common.MsgOfConsensus.BlockRestore
import rep.network.module.ModuleActorType
import rep.network.persistence.IStorager.SourceOfBlock
import rep.network.util.NodeHelp
import rep.protos.peer.{Block, Event}
import rep.utils.GlobalUtils.EventType
import rep.network.consensus.common.MsgOfConsensus.BatchStore
/**
* Created by jiangbuyun on 2020/03/19.
* RAFT共识的确认块actor
*/
object ConfirmBlockOfRAFT{
def props(name: String): Props = Props(classOf[ConfirmBlockOfRAFT], name)
}
class ConfirmBlockOfRAFT(moduleName: String) extends IConfirmOfBlock(moduleName: String) {
override def preStart(): Unit = {
RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("ConfirmBlockOfRAFT module start"))
SubscribeTopic(mediator, self, selfAddr, Topic.Block, false)
}
override protected def handler(block: Block, actRefOfBlock: ActorRef) = {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement start,height=${block.height}"))
if (SystemProfile.getIsVerifyOfEndorsement) {
if (asyncVerifyEndorses(block)) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement end,height=${block.height}"))
//背书人的签名一致
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement sort,height=${block.height}"))
pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock))
pe.getActorRef(ModuleActorType.ActorType.storager) ! BatchStore
sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW)
} else {
//背书验证有错误
RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement error,height=${block.height}"))
}
} else {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement sort,height=${block.height}"))
pe.getBlockCacheMgr.addToCache(BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock))
pe.getActorRef(ModuleActorType.ActorType.storager) ! BatchStore
sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW)
}
}
override protected def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef) = {
if (pe.getCurrentBlockHash == "" && block.previousBlockHash.isEmpty()) {
//if (NodeHelp.isSeedNode(pe.getNodeMgr.getStableNodeName4Addr(actRefOfBlock.path.address))) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}"))
handler(block, actRefOfBlock)
//}else{
// RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"not confirm genesis block,blocker is not seed node,height=${block.height}"))
//}
} else {
//与上一个块一致
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify blockhash,height=${block.height}"))
handler(block, actRefOfBlock)
pe.setConfirmHeight(block.height)
}
}
}

View File

@ -1,211 +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.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.vote.Voter.VoteOfBlocker
import rep.network.base.ModuleBase
import rep.network.consensus.block.Blocker.{ ConfirmedBlock, PreTransBlock, PreTransBlockResult }
import rep.protos.peer._
import rep.storage.ImpDataAccess
import rep.utils.GlobalUtils.{ ActorType, 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 rep.network.Topic
import rep.network.consensus.endorse.EndorseMsg
import rep.log.RepLogger
import rep.log.RepTimeTracer
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 == num ){
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(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)
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 CreateBlockHandler = {
//if (preblock == null) {
val blc = CreateBlock(0)
if (blc != null) {
RepTimeTracer.setEndTime(pe.getSysTag, "createBlock", System.currentTimeMillis(),blc.height,blc.transactions.size)
this.preblock = blc
schedulerLink = clearSched()
//在发出背书时告诉对方我是当前出块人取出系统的名称
//pe.getActorRef(ActorType.endorsementcollectioner) ! EndorseMsg.CollectEndorsement(this.preblock, pe.getBlocker.blocker)
RepTimeTracer.setStartTime(pe.getSysTag, "Endorsement", System.currentTimeMillis(),blc.height,blc.transactions.size)
pe.getActorRef(ActorType.endorsementcollectioner) ! EndorseMsg.CollectEndorsement(this.preblock, pe.getSysTag)
//schedulerLink = scheduler.scheduleOnce(TimePolicy.getTimeoutEndorse seconds, self, Blocker.EndorseOfBlockTimeOut)
}else{
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("create new block error,CreateBlock is null" + "~" + selfAddr))
pe.getActorRef( ActorType.voter) ! VoteOfBlocker
}
//}
}
override def receive = {
//创建块请求给出块人
case Blocker.CreateBlock =>
//if(pe.getSysTag == "121000005l35120456.node1" && !pe.isSetExcept){
//pe.isSetExcept = true
//throw new Exception("^^^^^^^^^^^^^^^^exception^^^^^^^^^^")
//}
if (!pe.isSynching) {
if (NodeHelp.isBlocker(pe.getBlocker.blocker, pe.getSysTag) && pe.getBlocker.voteBlockHash == pe.getCurrentBlockHash) {
sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.CANDIDATOR)
//是出块节点
if (preblock == null || (preblock.previousBlockHash.toStringUtf8() != pe.getBlocker.voteBlockHash)) {
CreateBlockHandler
}
} else {
//出块标识错误,暂时不用做任何处理
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,do not blocker or blocker hash not equal current hash,height=${pe.getCurrentHeight}" + "~" + selfAddr))
}
} else {
//节点状态不对
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"create new block,node status error,status is synching,height=${pe.getCurrentHeight}" + "~" + selfAddr))
}
case _ => //ignore
}
}

View File

@ -1,143 +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.block
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 }
import rep.crypto.Sha256
import rep.network.base.ModuleBase
import rep.network.Topic
import rep.network.util.NodeHelp
import rep.protos.peer.{ Event, Transaction }
import rep.utils.GlobalUtils.{ ActorType, 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.block.Blocker.{ ConfirmedBlock }
import rep.network.persistence.Storager.{ BlockRestore, SourceOfBlock ,BatchStore}
import rep.network.consensus.util.{ BlockVerify, BlockHelp }
import rep.log.RepLogger
import rep.log.RepTimeTracer
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 (asyncVerifyEndorses(block)) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"confirm verify endorsement end,height=${block.height}"))
//背书人的签名一致
if (BlockVerify.VerifyEndorserSorted(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(ActorType.storager) ! BatchStore
sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Block, Event.Action.BLOCK_NEW)
//pe.getActorRef(ActorType.storager) ! BlockRestore(block, SourceOfBlock.CONFIRMED_BLOCK, actRefOfBlock)
} else {
////背书信息排序错误
}
} else {
//背书验证有错误
}
}
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 (NodeHelp.ConsensusConditionChecked(block.endorsements.size, pe.getNodeMgr.getStableNodes.size)) {
//符合大多数人背书要求
handler(block, actRefOfBlock)
} else {
//错误没有符合大多人背书要求
}
}
}
override def receive = {
//Endorsement block
case ConfirmedBlock(block, actRefOfBlock) =>
RepTimeTracer.setStartTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(),block.height,block.transactions.size)
checkedOfConfirmBlock(block, actRefOfBlock)
RepTimeTracer.setEndTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(),block.height,block.transactions.size)
case _ => //ignore
}
}

View File

@ -0,0 +1,60 @@
package rep.network.consensus.byzantium
import java.util.concurrent.atomic.AtomicInteger
import rep.app.conf.SystemProfile
/**
* Created by jiangbuyun on 2020/06/30.
* 实现共识一致性计算条件是大于1/2通过还是大于2/3通过
* todo:自动部署可以更新
*/
object ConsensusCondition {
private var ConsensusNodes : AtomicInteger = new AtomicInteger(SystemProfile.getVoteNodeList.size())
private var ConsensusScale : AtomicInteger = new AtomicInteger(SystemProfile.getNumberOfEndorsement)
private var LeastNodeNumber: AtomicInteger = new AtomicInteger(SystemProfile.getVoteNodeMin)
private def Check(input:Int):Boolean={
var scaledata = this.ConsensusScale.get()
if(this.ConsensusScale == 1) {
scaledata = 2
}
if(scaledata == 2) {
//采用大于1/2方法计算
input >= (Math.floor(((this.ConsensusNodes.get()) * 1.0) / scaledata + 1))
}else if(scaledata == 2) {
//采用大于2/3方法计算
input >= (Math.floor((((this.ConsensusNodes.get()) * 1.0) / scaledata) * 2) + 1)
}else{
false
}
}
//提供一致性判断方法
def ConsensusConditionChecked(inputNumber: Int): Boolean = {
if (SystemProfile.getTypeOfConsensus == "PBFT") { //zhj
true
} else {
this.Check(inputNumber)
}
}
//系统是否可以正常工作
def CheckWorkConditionOfSystem(nodeNumber:Int):Boolean = {
nodeNumber >= this.LeastNodeNumber.get() && this.Check(nodeNumber)
}
def ChangeConsensusNodes(nodeNumber:Int): Unit ={
this.ConsensusNodes.set(nodeNumber)
}
def ChangeConsensusScale(scale:Int)={
this.ConsensusScale.set(scale)
}
def ChangeLeastNodeNumber(limit:Int) ={
this.LeastNodeNumber.set(limit)
}
}

View File

@ -0,0 +1,62 @@
package rep.network.consensus.cfrd
import akka.actor.{ActorRef, Address}
import rep.protos.peer.{Block, BlockchainInfo, Signature, Transaction, TransactionResult}
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
//case class CreateBlockTPS(ts : Seq[Transaction], trs : Seq[TransactionResult]) //zhjtps
///////////////////////////////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 verifyTransOfEndorsement(blc: Block, blocker: String)
case class verifyTransRepeatOfEndorsement(blc: Block, blocker: String)
case class verifyTransPreloadOfEndorsement(blc: Block, blocker: String)
//背书收集者消息
case class CollectEndorsement(blc: Block, blocker: String)
//背书人返回的背书结果
case class ResultOfEndorsed(result: Int, endor: Signature, BlockHash: String,endorserOfChainInfo:BlockchainInfo,endorserOfVote:BlockerInfo)
//背书请求者返回的结果
case class ResultOfEndorseRequester(result: Boolean, endor: Signature, BlockHash: String, endorser: Address)
//////////////////////////////endorsement共识消息结束/////////////////////////
}

View File

@ -0,0 +1,96 @@
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.{CollectEndorsement, CreateBlock,/* CreateBlockTPS,*/ 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, Transaction, TransactionResult}
import rep.utils.GlobalUtils.EventType
import rep.utils.SerializeUtils
/**
* 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){
//zhjtps
/*var blockTPS :Block = null
var tsTPS : Seq[Transaction] = null
var trsTPS : Seq[TransactionResult] = null*/
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
//zhjtps
/*if ( tsTPS != null )
if (tsTPS.size > 0 )
if (trsTPS != null)
if (trsTPS.size >0) {
var b = true
tsTPS.foreach(t => b &&= pe.getTransPoolMgr.findTrans(t.id))
if (b)
blc = PackedBlockTPS(tsTPS,trsTPS,0)
}
tsTPS = null
trsTPS = null*/
if (blc ==null)
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)
//RepLogger.print(RepLogger.zLogger,"send CollectEndorsement, " + pe.getSysTag
// + ", " + pe.getCurrentBlockHash+ ", " + blc.previousBlockHash.toStringUtf8)
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))
}
//zhjtps
/* case CreateBlockTPS(ts : Seq[Transaction], trs : Seq[TransactionResult]) =>
tsTPS = ts
trsTPS = trs*/
case _ => //ignore
}
}

View File

@ -14,28 +14,29 @@
*
*/
package rep.network.consensus.block
package rep.network.consensus.cfrd.block
import akka.actor.{ Actor, ActorRef, Props, Address, ActorSelection }
import akka.actor.Props
import akka.cluster.pubsub.DistributedPubSubMediator.Publish
import akka.routing._;
import rep.app.conf.{ SystemProfile, TimePolicy }
import akka.routing._
import rep.app.conf.SystemProfile
import rep.network.base.ModuleBase
import rep.network.consensus.endorse.EndorseMsg.{ RequesterOfEndorsement, ResultOfEndorseRequester, CollectEndorsement,ResendEndorseInfo }
import rep.network.consensus.block.Blocker.ConfirmedBlock
import rep.network.tools.PeerExtension
import rep.network.Topic
import rep.network.consensus.common.MsgOfConsensus.ConfirmedBlock
import rep.network.consensus.cfrd.MsgOfCFRD.{CollectEndorsement, RequesterOfEndorsement, ResendEndorseInfo, ResultOfEndorseRequester}
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.utils.GlobalUtils.EventType
import rep.network.util.NodeHelp
import rep.network.consensus.util.BlockHelp
import rep.network.consensus.util.BlockVerify
import rep.log.RepLogger
import rep.log.RepTimeTracer
import rep.network.autotransaction.Topic
import rep.network.consensus.byzantium.ConsensusCondition
/**
* Created by jiangbuyun on 2020/03/19.
* 背书的收集的actor
*/
object EndorseCollector {
def props(name: String): Props = Props(classOf[EndorseCollector], name)
@ -85,13 +86,13 @@ class EndorseCollector(moduleName: String) extends ModuleBase(moduleName) {
private def CheckAndFinishHandler {
sendEvent(EventType.PUBLISH_INFO, mediator, pe.getSysTag, Topic.Endorsement, Event.Action.ENDORSEMENT)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("entry collectioner check "))
if (NodeHelp.ConsensusConditionChecked(this.recvedEndorse.size + 1, pe.getNodeMgr.getNodes.size)) {
if (ConsensusCondition.ConsensusConditionChecked(this.recvedEndorse.size + 1)) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("collectioner package endorsement to block"))
this.recvedEndorse.foreach(f => {
this.block = BlockHelp.AddEndorsementToBlock(this.block, f._2)
})
var consensus = this.block.endorsements.toArray[Signature]
BlockVerify.sort(consensus)
consensus=BlockVerify.sort(consensus)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix("collectioner endorsement sort"))
this.block = this.block.withEndorsements(consensus)
RepTimeTracer.setEndTime(pe.getSysTag, "Endorsement", System.currentTimeMillis(),this.block.height,this.block.transactions.size)
@ -110,7 +111,7 @@ class EndorseCollector(moduleName: String) extends ModuleBase(moduleName) {
if (this.block != null && this.block.hashOfBlock.toStringUtf8() == block.hashOfBlock.toStringUtf8()) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"collectioner is waiting endorse result,height=${block.height},local height=${pe.getCurrentHeight}"))
} else {
if(block.previousBlockHash.toStringUtf8() == pe.getCurrentBlockHash){
if( block.previousBlockHash.toStringUtf8() == pe.getCurrentBlockHash){
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( s"collectioner recv endorsement,height=${block.height},local height=${pe.getCurrentHeight}"))
resetEndorseInfo(block, blocker)
pe.getNodeMgr.getStableNodes.foreach(f => {

View File

@ -14,31 +14,27 @@
*
*/
package rep.network.consensus.block
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, Props, Address, ActorSelection }
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.endorse.EndorseMsg.{ EndorsementInfo, ResultOfEndorsed, RequesterOfEndorsement, ResultOfEndorseRequester, ResultFlagOfEndorse,ResendEndorseInfo }
import rep.network.tools.PeerExtension
import rep.network.Topic
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, ActorType }
import rep.network.consensus.cfrd.MsgOfCFRD.{/*CreateBlockTPS,*/ EndorsementInfo, RequesterOfEndorsement, ResendEndorseInfo, ResultFlagOfEndorse, ResultOfEndorseRequester, ResultOfEndorsed}
import rep.network.sync.SyncMsg.StartSync
import rep.log.RepLogger
import rep.log.RepTimeTracer
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)
@ -46,10 +42,9 @@ object EndorsementRequest4Future {
class EndorsementRequest4Future(moduleName: String) extends ModuleBase(moduleName) {
import context.dispatcher
import scala.collection.breakOut
import scala.concurrent.duration._
implicit val timeout = Timeout(TimePolicy.getTimeoutEndorse seconds)
implicit val timeout = Timeout(TimePolicy.getTimeoutEndorse.seconds)
//private val endorsementActorName = "/user/modulemanager/endorser"
private val endorsementActorName = "/user/modulemanager/dispatchofRecvendorsement"
@ -102,7 +97,7 @@ class EndorsementRequest4Future(moduleName: String) extends ModuleBase(moduleNam
if (result.result == ResultFlagOfEndorse.BlockHeightError) {
if (result.endorserOfChainInfo.height > pe.getCurrentHeight + 1) {
//todo 需要从块缓冲判断是否启动块同步
pe.getActorRef(ActorType.synchrequester) ! StartSync(false)
pe.getActorRef(CFRDActorType.ActorType.synchrequester) ! StartSync(false)
context.parent ! ResultOfEndorseRequester(false, null, reqinfo.blc.hashOfBlock.toStringUtf8(), reqinfo.endorer)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( s"--------endorsementRequest4Future recv endorsement result must synch,height=${reqinfo.blc.height},local height=${pe.getCurrentHeight} "))
} else {

View File

@ -0,0 +1,168 @@
/*
* 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.{Actor, ActorRef, ActorSelection, Address, Props}
import akka.cluster.pubsub.DistributedPubSubMediator.Publish
import akka.routing._
import rep.app.conf.{SystemCertList, SystemProfile, TimePolicy}
import rep.network.base.ModuleBase
import rep.network.tools.PeerExtension
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
import rep.log.RepLogger
import rep.log.RepTimeTracer
import rep.network.autotransaction.Topic
import rep.network.consensus.cfrd.MsgOfCFRD.{EndorsementInfo, ResultFlagOfEndorse, ResultOfEndorsed, verifyTransOfEndorsement, verifyTransPreloadOfEndorsement, verifyTransRepeatOfEndorsement}
import rep.network.module.cfrd.CFRDActorType
import rep.network.sync.SyncMsg.StartSync
import akka.util.ByteString
/**
* Created by jiangbuyun on 2020/03/19.
* 接收并分派背书请求actor
*/
object DispatchOfRecvEndorsement {
def props(name: String): Props = Props(classOf[DispatchOfRecvEndorsement], name)
}
class DispatchOfRecvEndorsement(moduleName: String) extends ModuleBase(moduleName) {
import context.dispatcher
import scala.concurrent.duration._
import scala.collection.immutable._
private var router: Router = null
override def preStart(): Unit = {
RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix( "DispatchOfRecvEndorsement Start"))
}
private def createRouter = {
if (router == null) {
var list: Array[Routee] = new Array[Routee](SystemProfile.getVoteNodeList.size())
for (i <- 0 to SystemProfile.getVoteNodeList.size() - 1) {
var ca = context.actorOf(Endorser4Future.props("endorser" + i), "endorser" + i)
context.watch(ca)
list(i) = new ActorRefRoutee(ca)
}
val rlist: IndexedSeq[Routee] = list.toIndexedSeq
router = Router(SmallestMailboxRoutingLogic(), rlist)
}
}
private def isAllowEndorse(info: EndorsementInfo): Int = {
if (info.blocker == pe.getSysTag) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( s"DispatchOfRecvEndorsement is itself,do not endorse,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
1
} else {
if (NodeHelp.isCandidateNow(pe.getSysTag, SystemCertList.getSystemCertList)) {
//是候选节点可以背书
//if (info.blc.previousBlockHash.toStringUtf8 == pe.getCurrentBlockHash && NodeHelp.isBlocker(info.blocker, pe.getBlocker.blocker)) {
if (info.blc.previousBlockHash.toStringUtf8 == pe.getBlocker.voteBlockHash && NodeHelp.isBlocker(info.blocker, pe.getBlocker.blocker)) {
//可以进入背书
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( s"DispatchOfRecvEndorsementvote result equalallow entry endorse,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
0
} else {
//todo 需要判断区块缓存再决定是否需要启动同步,并且当前没有同步才启动同步如果已经同步则不需要发送消息
if(info.blc.height > pe.getCurrentHeight+1 && !pe.isSynching){
pe.getActorRef(CFRDActorType.ActorType.synchrequester) ! StartSync(false)
}
/*else if(info.blc.height > pe.getCurrentHeight+1){
pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfForce
}*/
//当前块hash和抽签的出块人都不一致暂时不能够进行背书可以进行缓存
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( s"DispatchOfRecvEndorsementblock hash is not equal or blocker is not equal,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
2
}
} else {
//不是候选节点不能够参与背书
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( "DispatchOfRecvEndorsementit is not candidator node,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
3
}
}
}
private def checkEndorseSign(block: Block): Boolean = {
//println(s"${pe.getSysTag}:entry checkEndorseSign")
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkEndorseSign", System.currentTimeMillis(),block.height,block.transactions.size)
var result = false
val r = BlockVerify.VerifyAllEndorseOfBlock(block, pe.getSysTag)
result = r._1
//println(s"${pe.getSysTag}:entry checkEndorseSign after,checkEndorseSign=${result}")
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkEndorseSign", System.currentTimeMillis(),block.height,block.transactions.size)
result
}
private def EndorseHandler(info: EndorsementInfo) = {
val r = isAllowEndorse(info)
r match {
case 0 =>
if(checkEndorseSign(info.blc)){
var tmp = pe.getCurrentEndorseInfo
tmp.clean
tmp.block = info.blc
tmp.verifyBlockSign.set(true)
router.route(verifyTransOfEndorsement(info.blc, info.blocker), sender)
router.route(verifyTransRepeatOfEndorsement(info.blc, info.blocker), sender)
router.route(verifyTransPreloadOfEndorsement(info.blc, info.blocker), sender)
}else{
sender ! ResultOfEndorsed(ResultFlagOfEndorse.VerifyError, null, info.blc.hashOfBlock.toStringUtf8(), pe.getSystemCurrentChainStatus, pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"DispatchOfRecvEndorsementblocker sign verify error,self height=${pe.getCurrentHeight},block height=${info.blc.height}"))
}
case 2 =>
//cache endorse,waiting revote
sender ! ResultOfEndorsed(ResultFlagOfEndorse.BlockHeightError, null, info.blc.hashOfBlock.toStringUtf8(), pe.getSystemCurrentChainStatus, pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"DispatchOfRecvEndorsementendorsement entry cache,self height=${pe.getCurrentHeight},block height=${info.blc.height}"))
case 1 =>
//do not endorse
sender ! ResultOfEndorsed(ResultFlagOfEndorse.BlockerSelfError, null, info.blc.hashOfBlock.toStringUtf8(), pe.getSystemCurrentChainStatus, pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"DispatchOfRecvEndorsementitself,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
case 3 =>
//do not endorse
sender ! ResultOfEndorsed(ResultFlagOfEndorse.CandidatorError, null, info.blc.hashOfBlock.toStringUtf8(), pe.getSystemCurrentChainStatus, pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"DispatchOfRecvEndorsementit is not candator,do not endorse,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
}
}
override def receive = {
case EndorsementInfo(block, blocker) =>
createRouter
/*if(!pe.isSynching){
RepTimeTracer.setStartTime(pe.getSysTag, s"DispatchOfRecvEndorsement-recvendorsement-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
EndorseHandler(EndorsementInfo(block, blocker))
RepTimeTracer.setEndTime(pe.getSysTag, s"DispatchOfRecvEndorsement-recvendorsement-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
}else{
sender ! ResultOfEndorsed(ResultFlagOfEndorse.EnodrseNodeIsSynching, null, block.hashOfBlock.toStringUtf8(),pe.getSystemCurrentChainStatus,pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"DispatchOfRecvEndorsementdo not endorse,it is synching,recv endorse request,endorse height=${block.height},local height=${pe.getCurrentHeight}"))
}*/
router.route(EndorsementInfo(block, blocker), sender)
case _ => //ignore
}
}

View File

@ -0,0 +1,587 @@
/*
* 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.util.Timeout
import akka.pattern.{AskTimeoutException, ask}
import akka.actor.Props
import com.google.protobuf.ByteString
import rep.network.base.ModuleBase
import rep.network.util.NodeHelp
import rep.app.conf.{SystemCertList, SystemProfile, TimePolicy}
import rep.crypto.Sha256
import rep.utils.GlobalUtils.EventType
import rep.network.autotransaction.Topic
import scala.util.control.Breaks._
import rep.network.module.ModuleActorType
import rep.network.module.cfrd.CFRDActorType
import rep.network.consensus.common.MsgOfConsensus.{PreTransBlock, PreTransBlockResult}
import rep.network.consensus.cfrd.MsgOfCFRD.{EndorsementInfo, ResultFlagOfEndorse, ResultOfEndorsed, VoteOfForce, verifyTransOfEndorsement, verifyTransPreloadOfEndorsement, verifyTransRepeatOfEndorsement}
import rep.network.consensus.util.{BlockHelp, BlockVerify}
import rep.network.sync.SyncMsg.StartSync
import rep.log.RepLogger
import rep.log.RepTimeTracer
import rep.network.consensus.common.algorithm.{IAlgorithmOfVote, IRandomAlgorithmOfVote}
import rep.sc.Sandbox.DoTransactionResult
import rep.sc.SandboxDispatcher.DoTransaction
import rep.sc.TypeOfSender
import scala.collection.mutable.ArrayBuffer
/**
* Created by jiangbuyun on 2020/03/19.
* 背书actor
*/
object Endorser4Future {
def props(name: String): Props = Props(classOf[Endorser4Future], name)
}
class Endorser4Future(moduleName: String) extends ModuleBase(moduleName) {
import context.dispatcher
import scala.concurrent.duration._
import rep.protos.peer._
import rep.storage.ImpDataAccess
import scala.concurrent._
implicit val timeout = Timeout(TimePolicy.getTimeoutPreload.seconds)
//zhjtps
/*protected var algorithmInVoted:IAlgorithmOfVote = new IRandomAlgorithmOfVote*/
override def preStart(): Unit = {
RepLogger.info(RepLogger.Consensus_Logger, this.getLogMsgPrefix("Endorser4Future Start"))
}
//背书块的交易预执行,然后验证block
//zhjtps
/*private def AskPreloadTransactionOfBlock(block: Block): Future[Boolean] = {
var blc2: Block = null
val isMe = isNextBlocker(block)
var nextTrans: Seq[Transaction] = null
if (isMe) {
nextTrans = CollectedTransOfBlockTPS(0, block.transactions, SystemProfile.getLimitBlockTransNum, SystemProfile.getBlockLength).reverse
blc2 = block.withTransactions(block.transactions ++ nextTrans.toSeq)
} else {
blc2 = block
}
pe.getActorRef(ModuleActorType.ActorType.dispatchofpreload).ask(PreTransBlock(blc2, "endors"))(timeout)
.mapTo[PreTransBlockResult].flatMap(f => {
val result = Promise[Boolean]
var tr = ArrayBuffer[TransactionResult]()
var nextTr = ArrayBuffer[TransactionResult]()
if (isMe) {
val txId1 : Seq[String] = block.transactions.map(_.id)
val txId2 : Seq[String] = nextTrans.map(_.id)
f.blc.transactionResults.foreach(x=>{
if (txId1.contains(x.txId))
tr.append(x)
if (txId2.contains(x.txId))
nextTr.append(x)
})
}
var tmpblock : Block = null
if (isMe) {
tmpblock = f.blc.withTransactions(block.transactions).withTransactionResults(tr.toSeq)
//val statehashstr = Sha256.hashstr(Array.concat(pe.getSystemCurrentChainStatus.currentStateHash.toByteArray() ,
// SerializeUtils.serialise(tr)))
tmpblock = tmpblock.withStateHash(ByteString.copyFromUtf8(block.stateHash.toStringUtf8))//zhj todo
tmpblock = tmpblock.withHashOfBlock(block.hashOfBlock)
tmpblock = BlockHelp.AddSignToBlock(tmpblock, pe.getSysTag)
} else
tmpblock = f.blc.withHashOfBlock(block.hashOfBlock)
/*val b1 = block.clearEndorsements.withHashOfBlock(ByteString.EMPTY).toByteArray
val b2 = tmpblock.clearEndorsements.withHashOfBlock(ByteString.EMPTY).toByteArray
for (i<-0 to b1.size-1){
if (b1(i)!=b2(i))
1
}*/
if (BlockVerify.VerifyHashOfBlock(tmpblock)) {
if (isMe) {
pe.getActorRef(CFRDActorType.ActorType.blocker) ! CreateBlockTPS(nextTrans,nextTr)
}
result.success(true)
} else {
result.success(false)
}
result.future
}).recover({
case e: Throwable =>
RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AskPreloadTransactionOfBlock error"))
false
})
}*/
private def AskPreloadTransactionOfBlock(block: Block): Future[Boolean] = Future{
var b = false
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-AskPreloadTransactionOfBlock", System.currentTimeMillis(),block.height,block.transactions.size)
try {
val future1 = pe.getActorRef(ModuleActorType.ActorType.dispatchofpreload).ask(PreTransBlock(block, "endors"))
val result = Await.result(future1, timeout.duration).asInstanceOf[PreTransBlockResult]
var tmpblock = result.blc.withHashOfBlock(block.hashOfBlock)
if (BlockVerify.VerifyHashOfBlock(tmpblock)) {
b = true
}
} catch {
case e: AskTimeoutException =>
RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AskPreloadTransactionOfBlock error=AskTimeoutException"))
case te:TimeoutException =>
RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AskPreloadTransactionOfBlock error=TimeoutException"))
}
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-AskPreloadTransactionOfBlock", System.currentTimeMillis(),block.height,block.transactions.size)
b
}.recover({
case e: Throwable =>
RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AskPreloadTransactionOfBlock error=recover"))
false
})
private def AskPreloadTransactionOfBlock1(block: Block): Boolean = {
var b = false
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-AskPreloadTransactionOfBlock", System.currentTimeMillis(),block.height,block.transactions.size)
try {
val future1 = pe.getActorRef(ModuleActorType.ActorType.dispatchofpreload).ask(PreTransBlock(block, "endors"))
val result = Await.result(future1, timeout.duration).asInstanceOf[PreTransBlockResult]
var tmpblock = result.blc.withHashOfBlock(block.hashOfBlock)
if (BlockVerify.VerifyHashOfBlock(tmpblock)) {
b = true
}
} catch {
case e: AskTimeoutException =>
RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AskPreloadTransactionOfBlock error=AskTimeoutException"))
case te:TimeoutException =>
RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AskPreloadTransactionOfBlock error=TimeoutException"))
}
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-AskPreloadTransactionOfBlock", System.currentTimeMillis(),block.height,block.transactions.size)
b
}
/*private def AskPreloadTransactionOfBlock(block: Block): Future[Boolean] =
//pe.getActorRef(ActorType.preloaderoftransaction).ask(PreTransBlock(block, "endors"))(timeout).mapTo[PreTransBlockResult].flatMap(f => {
pe.getActorRef(ModuleActorType.ActorType.dispatchofpreload).ask(PreTransBlock(block, "endors"))(timeout).mapTo[PreTransBlockResult].flatMap(f => {
//println(s"${pe.getSysTag}:entry AskPreloadTransactionOfBlock")
val result = Promise[Boolean]
var tmpblock = f.blc.withHashOfBlock(block.hashOfBlock)
if (BlockVerify.VerifyHashOfBlock(tmpblock)) {
result.success(true)
} else {
result.success(false)
}
result.future
}).recover({
case e: Throwable =>
RepLogger.error(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry AskPreloadTransactionOfBlock error"))
false
})*/
private def checkRepeatOfTrans(trans: Seq[Transaction],height:Long): Future[Boolean] = Future {
//println("entry checkRepeatOfTrans")
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkRepeatOfTrans", System.currentTimeMillis(),height,trans.size)
var isRepeat: Boolean = false
val aliaslist = trans.distinct
if (aliaslist.size != trans.size) {
isRepeat = true
} else {
val sr: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag)
breakable(
trans.foreach(f => {
if (sr.isExistTrans4Txid(f.id)) {
isRepeat = true
break
}
//println(s"${pe.getSysTag}:entry checkRepeatOfTrans loop")
}))
}
//println(s"${pe.getSysTag}:entry checkRepeatOfTrans after,isrepeat=${isRepeat}")
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkRepeatOfTrans", System.currentTimeMillis(),height,trans.size)
isRepeat
}
private def checkRepeatOfTrans1(trans: Seq[Transaction],height:Long): Boolean = {
//println("entry checkRepeatOfTrans")
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkRepeatOfTrans", System.currentTimeMillis(),height,trans.size)
var isRepeat: Boolean = false
val aliaslist = trans.distinct
if (aliaslist.size != trans.size) {
isRepeat = true
} else {
val sr: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag)
breakable(
trans.foreach(f => {
if (sr.isExistTrans4Txid(f.id)) {
isRepeat = true
break
}
//println(s"${pe.getSysTag}:entry checkRepeatOfTrans loop")
}))
}
//println(s"${pe.getSysTag}:entry checkRepeatOfTrans after,isrepeat=${isRepeat}")
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkRepeatOfTrans", System.currentTimeMillis(),height,trans.size)
isRepeat
}
private def asyncVerifyTransaction(t: Transaction): Future[Boolean] = Future {
//println(s"${pe.getSysTag}:entry asyncVerifyTransaction")
var result = false
if (pe.getTransPoolMgr.findTrans(t.id)) {
result = true
} else {
val tmp = BlockVerify.VerifyOneSignOfTrans(t, pe.getSysTag)
if (tmp._1) {
result = true
}
//println(s"${pe.getSysTag}:entry asyncVerifyTransaction loop")
}
//println(s"${pe.getSysTag}:entry asyncVerifyTransaction after,asyncVerifyTransaction=${result}")
result
}
private def asyncVerifyTransaction1(t: Transaction): Boolean = {
//println(s"${pe.getSysTag}:entry asyncVerifyTransaction")
var result = false
if (pe.getTransPoolMgr.findTrans(t.id)) {
result = true
} else {
val tmp = BlockVerify.VerifyOneSignOfTrans(t, pe.getSysTag)
if (tmp._1) {
result = true
}
//println(s"${pe.getSysTag}:entry asyncVerifyTransaction loop")
}
//println(s"${pe.getSysTag}:entry asyncVerifyTransaction after,asyncVerifyTransaction=${result}")
result
}
private def asyncVerifyTransactions(block: Block): Future[Boolean] = Future {
//println(s"${pe.getSysTag}:entry asyncVerifyTransactions")
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-asyncVerifyTransactions", System.currentTimeMillis(),block.height,block.transactions.size)
var result = true
val listOfFuture: Seq[Future[Boolean]] = block.transactions.map(x => {
asyncVerifyTransaction(x)
})
val futureOfList: Future[List[Boolean]] = Future.sequence(listOfFuture.toList)
//val result1 = Await.result(futureOfList, timeout4Sign.duration).asInstanceOf[Int]
futureOfList.map(x => {
x.foreach(f => {
if (f) {
result = false
}
//println(s"${pe.getSysTag}:entry asyncVerifyTransactions loop result")
})
})
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-asyncVerifyTransactions", System.currentTimeMillis(),block.height,block.transactions.size)
//println(s"${pe.getSysTag}:entry asyncVerifyTransactions after,asyncVerifyTransactions=${result}")
result
}
private def asyncVerifyTransactions1(block: Block): Boolean = {
//println(s"${pe.getSysTag}:entry asyncVerifyTransactions")
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-asyncVerifyTransactions", System.currentTimeMillis(),block.height,block.transactions.size)
var result = true
breakable(
block.transactions.foreach(t => {
if (!asyncVerifyTransaction1(t)) {
result = false
break
}
}))
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-asyncVerifyTransactions", System.currentTimeMillis(),block.height,block.transactions.size)
//println(s"${pe.getSysTag}:entry asyncVerifyTransactions after,asyncVerifyTransactions=${result}")
result
}
private def checkEndorseSign(block: Block): Future[Boolean] = Future {
//println(s"${pe.getSysTag}:entry checkEndorseSign")
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkEndorseSign", System.currentTimeMillis(),block.height,block.transactions.size)
var result = false
val r = BlockVerify.VerifyAllEndorseOfBlock(block, pe.getSysTag)
result = r._1
//println(s"${pe.getSysTag}:entry checkEndorseSign after,checkEndorseSign=${result}")
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkEndorseSign", System.currentTimeMillis(),block.height,block.transactions.size)
result
}
private def checkEndorseSign1(block: Block): Boolean = {
//println(s"${pe.getSysTag}:entry checkEndorseSign")
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkEndorseSign", System.currentTimeMillis(),block.height,block.transactions.size)
var result = false
val r = BlockVerify.VerifyAllEndorseOfBlock(block, pe.getSysTag)
result = r._1
//println(s"${pe.getSysTag}:entry checkEndorseSign after,checkEndorseSign=${result}")
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-checkEndorseSign", System.currentTimeMillis(),block.height,block.transactions.size)
result
}
private def checkAllEndorseSign(block: Block):Boolean = {
var result = false
val r = BlockVerify.VerifyAllEndorseOfBlock(block, pe.getSysTag)
result = r._1
result
}
private def isAllowEndorse(info: EndorsementInfo): Int = {
if (info.blocker == pe.getSysTag) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( s"endorser is itself,do not endorse,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
1
} else {
if (NodeHelp.isCandidateNow(pe.getSysTag, SystemCertList.getSystemCertList)) {
//是候选节点可以背书
//if (info.blc.previousBlockHash.toStringUtf8 == pe.getCurrentBlockHash && NodeHelp.isBlocker(info.blocker, pe.getBlocker.blocker)) {
if (info.blc.previousBlockHash.toStringUtf8 == pe.getBlocker.voteBlockHash && NodeHelp.isBlocker(info.blocker, pe.getBlocker.blocker)) {
//可以进入背书
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( s"vote result equalallow entry endorse,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
0
} else {
//todo 需要判断区块缓存再决定是否需要启动同步,并且当前没有同步才启动同步如果已经同步则不需要发送消息
if(info.blc.height > pe.getCurrentHeight+1 && !pe.isSynching){
pe.getActorRef(CFRDActorType.ActorType.synchrequester) ! StartSync(false)
}
/*else if(info.blc.height > pe.getCurrentHeight+1){
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}"))
2
}
} else {
//不是候选节点不能够参与背书
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix( "it is not candidator node,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
3
}
}
}
private def VerifyInfo(blc: Block) = {
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-VerifyInfo", System.currentTimeMillis(),blc.height,blc.transactions.size)
val transSign = asyncVerifyTransactions(blc)
val transRepeat = checkRepeatOfTrans(blc.transactions,blc.height)
val endorseSign = checkEndorseSign(blc)
val transExe = AskPreloadTransactionOfBlock(blc)
val result = for {
v1 <- transSign
v2 <- transRepeat
v3 <- endorseSign
v4 <- transExe
} yield (v1 && !v2 && v3 && v4)
val result1 = Await.result(result, timeout.duration*2).asInstanceOf[Boolean]
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-VerifyInfo", System.currentTimeMillis(),blc.height,blc.transactions.size)
//SendVerifyEndorsementInfo(blc,result1)
result1
}
/*private def VerifyInfo(blc: Block) = {
var b = false
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}-VerifyInfo", System.currentTimeMillis(),blc.height,blc.transactions.size)
if(asyncVerifyTransactions1(blc) && checkEndorseSign1(blc) && !checkRepeatOfTrans1(blc.transactions,blc.height) && AskPreloadTransactionOfBlock1(blc)){
b = true
}
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}-VerifyInfo", System.currentTimeMillis(),blc.height,blc.transactions.size)
b
}*/
private def SendVerifyEndorsementInfo(blc: Block,result1:Boolean) = {
if (result1) {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry 7"))
sendEvent(EventType.RECEIVE_INFO, mediator, pe.getSysTag, Topic.Endorsement,Event.Action.ENDORSEMENT)
sender ! ResultOfEndorsed(ResultFlagOfEndorse.success, BlockHelp.SignBlock(blc, pe.getSysTag),
blc.hashOfBlock.toStringUtf8(),pe.getSystemCurrentChainStatus,pe.getBlocker)
} else {
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry 8"))
sender ! ResultOfEndorsed(ResultFlagOfEndorse.VerifyError, null, blc.hashOfBlock.toStringUtf8(),
pe.getSystemCurrentChainStatus,pe.getBlocker)
}
}
//zhjtps
/*protected def isNextBlocker(blc:Block) : Boolean =
{
var candidator: Array[String] = Array.empty[String]
candidator = algorithmInVoted.candidators(pe.getSysTag, blc.hashOfBlock.toStringUtf8,
SystemCertList.getSystemCertList, Sha256.hash(blc.hashOfBlock.toStringUtf8))
val nextBlocker = algorithmInVoted.blocker(candidator.toArray[String], 0)
nextBlocker.equals(pe.getSysTag)
}*/
//zhjtps
/*protected def CollectedTransOfBlockTPS(start: Int, bypassTrans : Seq[Transaction], num: Int, limitsize: Int): ArrayBuffer[Transaction] = {
var result = ArrayBuffer.empty[Transaction]
try {
val tmplist = pe.getTransPoolMgr.getTransListClone(start, num + bypassTrans.size, pe.getSysTag)
if (tmplist.size > 0) {
var transsize = 0
breakable(
tmplist.foreach(f => {
transsize += f.toByteArray.size
if (transsize * 3 > limitsize) {
break
} else {
if (!bypassTrans.contains(f))
f +=: result
if (result.size >= num)
break
}
}))
}
} finally {
}
result
}*/
private def EndorseHandler(info: EndorsementInfo) = {
val r = isAllowEndorse(info)
r match {
case 0 =>
var result1 = true
if (SystemProfile.getIsVerifyOfEndorsement) {
result1 = VerifyInfo(info.blc)
SendVerifyEndorsementInfo(info.blc, result1)
}else{
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"${pe.getSysTag}:entry 8"))
sender ! ResultOfEndorsed(ResultFlagOfEndorse.VerifyError, null, info.blc.hashOfBlock.toStringUtf8(),
pe.getSystemCurrentChainStatus,pe.getBlocker)
}
case 2 =>
//cache endorse,waiting revote
sender ! ResultOfEndorsed(ResultFlagOfEndorse.BlockHeightError, null, info.blc.hashOfBlock.toStringUtf8(), pe.getSystemCurrentChainStatus, pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"endorsement entry cache,self height=${pe.getCurrentHeight},block height=${info.blc.height}"))
case 1 =>
//do not endorse
sender ! ResultOfEndorsed(ResultFlagOfEndorse.BlockerSelfError, null, info.blc.hashOfBlock.toStringUtf8(), pe.getSystemCurrentChainStatus, pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"itself,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
case 3 =>
//do not endorse
sender ! ResultOfEndorsed(ResultFlagOfEndorse.CandidatorError, null, info.blc.hashOfBlock.toStringUtf8(), pe.getSystemCurrentChainStatus, pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"it is not candator,do not endorse,recv endorse request,endorse height=${info.blc.height},local height=${pe.getCurrentHeight}"))
}
}
private def verifyTransOfEndorsementOfOp(info: EndorsementInfo)={
var tmp = pe.getCurrentEndorseInfo
if(tmp.block.hashOfBlock.toStringUtf8.equals(info.blc.hashOfBlock.toStringUtf8) && !tmp.verifyTran.get()){
if(asyncVerifyTransactions1(info.blc)){
tmp.verifyTran.set(true)
EndorseIsFinish(tmp,info)
}else{
//tmp.verifyTran.set(false)
SendVerifyEndorsementInfo(info.blc,false)
}
}
EndorseIsFinish(tmp,info)
}
private def verifyTransRepeatOfEndorsementOfOp(info: EndorsementInfo)={
var tmp = pe.getCurrentEndorseInfo
if(tmp.block.hashOfBlock.toStringUtf8.equals(info.blc.hashOfBlock.toStringUtf8) && tmp.checkRepeatTrans.get() == 0){
if(!checkRepeatOfTrans1(info.blc.transactions,info.blc.height)){
tmp.checkRepeatTrans.set(1)
EndorseIsFinish(tmp,info)
}else{
//tmp.checkRepeatTrans.set(2)
SendVerifyEndorsementInfo(info.blc,false)
}
}
EndorseIsFinish(tmp,info)
}
private def verifyTransPreloadOfEndorsementOfOp(info: EndorsementInfo)={
var tmp = pe.getCurrentEndorseInfo
if(tmp.block.hashOfBlock.toStringUtf8.equals(info.blc.hashOfBlock.toStringUtf8) && !tmp.preload.get()){
if(AskPreloadTransactionOfBlock1(info.blc)){
tmp.preload.set(true)
EndorseIsFinish(tmp,info)
}else{
//tmp.preload.set(false)
SendVerifyEndorsementInfo(info.blc,false)
}
}
}
private def EndorseIsFinish(re:RecvEndorsInfo,info: EndorsementInfo)={
if(re.preload.get() && re.verifyBlockSign.get() && re.checkRepeatTrans.get()==1 && re.verifyTran.get()){
SendVerifyEndorsementInfo(info.blc, true)
}
}
override def receive = {
//Endorsement block
case EndorsementInfo(block, blocker) =>
if(!pe.isSynching){
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
EndorseHandler(EndorsementInfo(block, blocker))
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
}else{
sender ! ResultOfEndorsed(ResultFlagOfEndorse.EnodrseNodeIsSynching, null, block.hashOfBlock.toStringUtf8(),pe.getSystemCurrentChainStatus,pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"do not endorse,it is synching,recv endorse request,endorse height=${block.height},local height=${pe.getCurrentHeight}"))
}
case verifyTransOfEndorsement(block, blocker) =>
if(!pe.isSynching){
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-verifyTransOfEndorsementOfOp-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
verifyTransOfEndorsementOfOp(EndorsementInfo(block, blocker))
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-verifyTransOfEndorsementOfOp-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
}else{
sender ! ResultOfEndorsed(ResultFlagOfEndorse.EnodrseNodeIsSynching, null, block.hashOfBlock.toStringUtf8(),pe.getSystemCurrentChainStatus,pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"do not endorse,it is synching,recv endorse request,endorse height=${block.height},local height=${pe.getCurrentHeight}"))
}
case verifyTransRepeatOfEndorsement(block, blocker) =>
if(!pe.isSynching){
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-verifyTransRepeatOfEndorsementOfOp-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
verifyTransRepeatOfEndorsementOfOp(EndorsementInfo(block, blocker))
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-verifyTransRepeatOfEndorsementOfOp-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
}else{
sender ! ResultOfEndorsed(ResultFlagOfEndorse.EnodrseNodeIsSynching, null, block.hashOfBlock.toStringUtf8(),pe.getSystemCurrentChainStatus,pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"do not endorse,it is synching,recv endorse request,endorse height=${block.height},local height=${pe.getCurrentHeight}"))
}
case verifyTransPreloadOfEndorsement(block, blocker) =>
if(!pe.isSynching){
RepTimeTracer.setStartTime(pe.getSysTag, s"recvendorsement-verifyTransPreloadOfEndorsementOfOp-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
verifyTransPreloadOfEndorsementOfOp(EndorsementInfo(block, blocker))
RepTimeTracer.setEndTime(pe.getSysTag, s"recvendorsement-verifyTransPreloadOfEndorsementOfOp-${moduleName}", System.currentTimeMillis(),block.height,block.transactions.size)
}else{
sender ! ResultOfEndorsed(ResultFlagOfEndorse.EnodrseNodeIsSynching, null, block.hashOfBlock.toStringUtf8(),pe.getSystemCurrentChainStatus,pe.getBlocker)
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"do not endorse,it is synching,recv endorse request,endorse height=${block.height},local height=${pe.getCurrentHeight}"))
}
case _ => //ignore
}
}

View File

@ -0,0 +1,23 @@
package rep.network.consensus.cfrd.endorse
import java.util.concurrent.atomic.{AtomicBoolean, AtomicInteger}
import akka.util.ByteString
import rep.protos.peer.Block
class RecvEndorsInfo {
var block : Block = null
var verifyBlockSign : AtomicBoolean = new AtomicBoolean(false)
var verifyTran : AtomicBoolean = new AtomicBoolean(false)
var checkRepeatTrans : AtomicInteger = new AtomicInteger(0)
var preload:AtomicBoolean = new AtomicBoolean(false)
def clean={
block = null
verifyBlockSign.set(false)
verifyTran.set(false)
checkRepeatTrans.set(0)
preload.set(false)
}
}

View File

@ -0,0 +1,92 @@
package rep.network.consensus.cfrd.vote
import akka.actor.Props
import rep.app.conf.{SystemCertList, TimePolicy}
import rep.log.RepLogger
import rep.network.consensus.common.vote.IVoter
import rep.network.module.cfrd.CFRDActorType
import rep.network.consensus.cfrd.MsgOfCFRD.{CreateBlock, VoteOfBlocker,VoteOfForce}
import rep.network.util.NodeHelp
import rep.network.consensus.common.algorithm.IRandomAlgorithmOfVote
/**
* Created by jiangbuyun on 2020/03/17.
* 实现CFRD抽签actor
*/
object VoterOfCFRD{
def props(name: String): Props = Props(classOf[VoterOfCFRD],name)
}
class VoterOfCFRD(moduleName: String) extends IVoter(moduleName: String) {
import scala.concurrent.duration._
import context.dispatcher
this.algorithmInVoted = new IRandomAlgorithmOfVote
override def preStart(): Unit = {
RepLogger.info(RepLogger.Vote_Logger, this.getLogMsgPrefix("VoterOfCFRD module start"))
}
override protected def NoticeBlockerMsg: Unit = {
if (this.Blocker.blocker.equals(pe.getSysTag)) {
//发送建立新块的消息
pe.getActorRef(CFRDActorType.ActorType.blocker) ! CreateBlock
}
}
override protected def DelayVote: Unit = {
this.voteCount += 1
var time = this.voteCount * TimePolicy.getVoteRetryDelay
schedulerLink = clearSched()
schedulerLink = scheduler.scheduleOnce(TimePolicy.getVoteRetryDelay.millis, self, VoteOfBlocker)
}
override protected def vote(isForce: Boolean): Unit = {
if (checkTranNum || isForce) {
val currentblockhash = pe.getCurrentBlockHash
val currentheight = pe.getCurrentHeight
if (this.Blocker.voteBlockHash == "") {
this.cleanVoteInfo
this.resetCandidator(currentblockhash)
this.resetBlocker(0, currentblockhash, currentheight)
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},first voter,blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr))
} else {
if (!this.Blocker.voteBlockHash.equals(currentblockhash)) {
//抽签的基础块已经变化需要重续选择候选人
this.cleanVoteInfo
this.resetCandidator(currentblockhash)
this.resetBlocker(0, currentblockhash, currentheight)
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},hash change,reset voter,height=${currentheight},hash=${currentblockhash},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr))
} else {
if (this.Blocker.blocker == "") {
this.cleanVoteInfo
this.resetCandidator(currentblockhash)
this.resetBlocker(0, currentblockhash, currentheight)
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},blocker=null,reset voter,height=${currentheight},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr))
} else {
if ((System.currentTimeMillis() - this.Blocker.voteTime) / 1000 > TimePolicy.getTimeOutBlock) {
//说明出块超时
this.voteCount = 0
this.resetBlocker(this.Blocker.VoteIndex + 1, currentblockhash, currentheight)
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},block timeout,reset voter,height=${currentheight},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr))
} else {
NoticeBlockerMsg
}
}
}
}
} else {
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},transaction is not enough,waiting transaction,height=${pe.getCurrentHeight}" + "~" + selfAddr))
}
}
override def receive: Receive = {
case VoteOfBlocker =>
if (NodeHelp.isCandidateNow(pe.getSysTag, SystemCertList.getSystemCertList)) {
voteMsgHandler(false)
}
case VoteOfForce=>
voteMsgHandler(true)
}
}

View File

@ -0,0 +1,34 @@
package rep.network.consensus.common
import akka.actor.ActorRef
import rep.protos.peer.Block
/**
* Created by jiangbuyun on 2020/03/17.
* 汇总共识层中所有公共的消息目前公共的消息由预出块的交易预执行消息以及持久化的存储区块的消息
*/
object MsgOfConsensus {
///////////////////////////////预出块时预执行交易的相关消息开始//////////////////////////////
//发送预出块给交易预执行分配器预执行预出块里面的所有交易
case class PreTransBlock(block: Block, prefixOfDbTag: String)
//预出块的预执行的结果消息
case class PreTransBlockResult(blc: Block, result: Boolean)
///////////////////////////////预出块时预执行交易的相关消息结束//////////////////////////////
///////////////////////////////存储时发送给持久化actor的相关消息开始//////////////////////////////
//对于单个区块需要存储时发送下面的消息给持久化actor
final case class BlockRestore(blk: Block, SourceOfBlock: Int, blker: ActorRef)
//这个消息用于出块时提高存储效率发送批处理消息处理机制是先把确认块存放到缓存发送消息给持久化之后持久化actor开始存储
final case object BatchStore
///////////////////////////////存储时发送给持久化actor的相关消息结束//////////////////////////////
///////////////////////////////创世块actor的相关消息开始//////////////////////////////
case object GenesisBlock
///////////////////////////////创世块actor的相关消息结束//////////////////////////////
///////////////////////////////块确认actor的相关消息开始//////////////////////////////
//共识完成之后广播正式出块的消息
case class ConfirmedBlock(blc: Block, actRef: ActorRef)
///////////////////////////////块确认actor的相关消息结束//////////////////////////////
}

View File

@ -0,0 +1,24 @@
package rep.network.consensus.common.algorithm
/**
* Created by jiangbuyun on 2020/03/17.
* 定义抽签算法的接口
*/
trait IAlgorithmOfVote {
/**
* 获取出块人竞争胜出者
* @param nodes
* @tparam T
* @return
*/
def blocker(nodes:Array[String], position:Int):String
/**
* 获取候选人节点
* @param nodes
* @tparam T
* @param seed 随机种子
* @return
*/
def candidators(Systemname:String,hash:String,nodes:Set[String], seed:Array[Byte]):Array[String]
}

Some files were not shown because too many files have changed in this diff Show More