mirror of
https://gitee.com/BTAJL/repchain.git
synced 2024-12-02 03:38:08 +08:00
Merge remote-tracking branch 'origin/RepChain_1.1.0_RC'
# Conflicts: # README.md
This commit is contained in:
commit
bbcb252aa5
22
README.md
22
README.md
@ -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 IDE,File->New->Project or Project from VersionControl
|
||||
- 使用Idea的sbt插件导入
|
||||
- 右键单击 rep.app.Repchain.scala,Run '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
|
||||
|
62
build.sbt
62
build.sbt
@ -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)
|
||||
|
@ -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"/>
|
||||
|
375
conf/system.conf
375
conf/system.conf
@ -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//0,automatic 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//0,automatic 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#该参数确认背书比例,可选值:1,2,3;如果等于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
|
||||
}
|
||||
|
||||
}
|
@ -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.
@ -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.
@ -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.
@ -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.
@ -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.
@ -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.
@ -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-----
|
||||
|
@ -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-----
|
||||
|
@ -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-----
|
||||
|
@ -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-----
|
||||
|
@ -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-----
|
||||
|
@ -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.
BIN
jks_ca/121000005l35120456.node1.jks
Normal file
BIN
jks_ca/121000005l35120456.node1.jks
Normal file
Binary file not shown.
BIN
jks_ca/12110107bi45jh675g.node2.jks
Normal file
BIN
jks_ca/12110107bi45jh675g.node2.jks
Normal file
Binary file not shown.
BIN
jks_ca/122000002n00123567.node3.jks
Normal file
BIN
jks_ca/122000002n00123567.node3.jks
Normal file
Binary file not shown.
BIN
jks_ca/921000005k36123789.node4.jks
Normal file
BIN
jks_ca/921000005k36123789.node4.jks
Normal file
Binary file not shown.
BIN
jks_ca/921000006e0012v696.node5.jks
Normal file
BIN
jks_ca/921000006e0012v696.node5.jks
Normal file
Binary file not shown.
BIN
jks_ca/951002007l78123233.super_admin.jks
Normal file
BIN
jks_ca/951002007l78123233.super_admin.jks
Normal file
Binary file not shown.
BIN
jks_ca/cacerts
Normal file
BIN
jks_ca/cacerts
Normal file
Binary file not shown.
20
jks_ca/certs/121000005l35120456.node1.cer
Normal file
20
jks_ca/certs/121000005l35120456.node1.cer
Normal 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-----
|
20
jks_ca/certs/12110107bi45jh675g.node2.cer
Normal file
20
jks_ca/certs/12110107bi45jh675g.node2.cer
Normal 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-----
|
20
jks_ca/certs/122000002n00123567.node3.cer
Normal file
20
jks_ca/certs/122000002n00123567.node3.cer
Normal 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-----
|
20
jks_ca/certs/921000005k36123789.node4.cer
Normal file
20
jks_ca/certs/921000005k36123789.node4.cer
Normal 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-----
|
20
jks_ca/certs/921000006e0012v696.node5.cer
Normal file
20
jks_ca/certs/921000006e0012v696.node5.cer
Normal 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-----
|
20
jks_ca/certs/951002007l78123233.super_admin.cer
Normal file
20
jks_ca/certs/951002007l78123233.super_admin.cer
Normal 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
10
jks_ca/certs/trust.cer
Normal 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
BIN
jks_ca/mytrust
Normal file
Binary file not shown.
BIN
jks_ca/mytruststore.jks
Normal file
BIN
jks_ca/mytruststore.jks
Normal file
Binary file not shown.
BIN
jks_ca/p12s/121000005l35120456.node1.p12
Normal file
BIN
jks_ca/p12s/121000005l35120456.node1.p12
Normal file
Binary file not shown.
BIN
jks_ca/p12s/12110107bi45jh675g.node2.p12
Normal file
BIN
jks_ca/p12s/12110107bi45jh675g.node2.p12
Normal file
Binary file not shown.
BIN
jks_ca/p12s/122000002n00123567.node3.p12
Normal file
BIN
jks_ca/p12s/122000002n00123567.node3.p12
Normal file
Binary file not shown.
BIN
jks_ca/p12s/921000005k36123789.node4.p12
Normal file
BIN
jks_ca/p12s/921000005k36123789.node4.p12
Normal file
Binary file not shown.
BIN
jks_ca/p12s/921000006e0012v696.node5.p12
Normal file
BIN
jks_ca/p12s/921000006e0012v696.node5.p12
Normal file
Binary file not shown.
BIN
jks_ca/p12s/super_admin.p12
Normal file
BIN
jks_ca/p12s/super_admin.p12
Normal file
Binary file not shown.
BIN
jks_ca/p12s/trust.p12
Normal file
BIN
jks_ca/p12s/trust.p12
Normal file
Binary file not shown.
BIN
jks_ca/trust
Normal file
BIN
jks_ca/trust
Normal file
Binary file not shown.
@ -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
|
||||
|
@ -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)
|
@ -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"
|
@ -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
|
@ -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;
|
||||
//区块的hash。在计算块hash的时候,不包括签名信息;在签名时需要包括块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;
|
||||
//区块的hash。在计算块hash的时候,不包括签名信息;在签名时需要包括块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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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"))
|
||||
}
|
@ -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))))
|
||||
}
|
||||
}
|
25
src/main/scala/rep/api/rest/RestRouter.scala
Normal file
25
src/main/scala/rep/api/rest/RestRouter.scala
Normal 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)
|
||||
}
|
||||
}
|
@ -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] }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
308
src/main/scala/rep/app/RepChainMgr.scala
Normal file
308
src/main/scala/rep/app/RepChainMgr.scala
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
83
src/main/scala/rep/app/RepChain_Multi.scala
Normal file
83
src/main/scala/rep/app/RepChain_Multi.scala
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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*/
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 Socket(API)
|
||||
*/
|
||||
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 Socket(API)
|
||||
*/
|
||||
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" + " ~ ")
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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._
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ trait BaseActor extends Actor {
|
||||
|
||||
var schedulerLink: akka.actor.Cancellable = null
|
||||
|
||||
//implicit
|
||||
def scheduler = context.system.scheduler
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
137
src/main/scala/rep/network/cache/ITransactionPool.scala
vendored
Normal file
137
src/main/scala/rep/network/cache/ITransactionPool.scala
vendored
Normal 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
|
||||
}
|
||||
}
|
84
src/main/scala/rep/network/cache/TransactionChecker.scala
vendored
Normal file
84
src/main/scala/rep/network/cache/TransactionChecker.scala
vendored
Normal 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
|
||||
}
|
||||
|
||||
}
|
50
src/main/scala/rep/network/cache/TransactionOfCollectioner.scala
vendored
Normal file
50
src/main/scala/rep/network/cache/TransactionOfCollectioner.scala
vendored
Normal 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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
22
src/main/scala/rep/network/cache/cfrd/TransactionPoolOfCFRD.scala
vendored
Normal file
22
src/main/scala/rep/network/cache/cfrd/TransactionPoolOfCFRD.scala
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
package rep.network.cache.cfrd
|
||||
|
||||
|
||||
import akka.actor.Props
|
||||
import rep.network.cache.ITransactionPool
|
||||
import rep.network.module.cfrd.CFRDActorType
|
||||
import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker
|
||||
|
||||
/**
|
||||
* Created by jiangbuyun on 2020/03/19.
|
||||
* CFRD共识的确认块actor
|
||||
*/
|
||||
|
||||
object TransactionPoolOfCFRD{
|
||||
def props(name: String): Props = Props(classOf[TransactionPoolOfCFRD], name)
|
||||
}
|
||||
|
||||
class TransactionPoolOfCFRD (moduleName: String) extends ITransactionPool(moduleName){
|
||||
override protected def sendVoteMessage: Unit = {
|
||||
pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker
|
||||
}
|
||||
}
|
51
src/main/scala/rep/network/cache/pbft/TransactionPoolOfPBFT.scala
vendored
Normal file
51
src/main/scala/rep/network/cache/pbft/TransactionPoolOfPBFT.scala
vendored
Normal 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")
|
||||
}
|
||||
}
|
22
src/main/scala/rep/network/cache/raft/TransactionPoolOfRAFT.scala
vendored
Normal file
22
src/main/scala/rep/network/cache/raft/TransactionPoolOfRAFT.scala
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
package rep.network.cache.raft
|
||||
|
||||
import akka.actor.Props
|
||||
import rep.network.cache.ITransactionPool
|
||||
import rep.network.module.cfrd.CFRDActorType
|
||||
import rep.network.consensus.cfrd.MsgOfCFRD.VoteOfBlocker
|
||||
|
||||
/**
|
||||
* Created by jiangbuyun on 2020/03/19.
|
||||
* RAFT共识的确认块actor
|
||||
*/
|
||||
|
||||
object TransactionPoolOfRAFT{
|
||||
def props(name: String): Props = Props(classOf[TransactionPoolOfRAFT], name)
|
||||
}
|
||||
|
||||
class TransactionPoolOfRAFT (moduleName: String) extends ITransactionPool(moduleName){
|
||||
override protected def sendVoteMessage: Unit = {
|
||||
pe.getActorRef(CFRDActorType.ActorType.voter) ! VoteOfBlocker
|
||||
}
|
||||
}
|
||||
|
@ -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组网类
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package rep.network.confirmblock
|
||||
|
||||
|
||||
import akka.actor.{ActorRef, Props}
|
||||
import akka.util.Timeout
|
||||
import rep.log.{RepLogger, RepTimeTracer}
|
||||
import rep.network.base.ModuleBase
|
||||
import rep.network.consensus.common.MsgOfConsensus.{ConfirmedBlock}
|
||||
import rep.network.consensus.util.BlockVerify
|
||||
import scala.concurrent._
|
||||
|
||||
/**
|
||||
* Created by jiangbuyun on 2020/03/19.
|
||||
* 抽象的确认块actor
|
||||
*/
|
||||
|
||||
object IConfirmOfBlock{
|
||||
def props(name: String): Props = Props(classOf[IConfirmOfBlock], name)
|
||||
}
|
||||
|
||||
abstract class IConfirmOfBlock(moduleName: String) extends ModuleBase(moduleName) {
|
||||
import context.dispatcher
|
||||
import scala.concurrent.duration._
|
||||
import rep.protos.peer._
|
||||
|
||||
implicit val timeout = Timeout(3.seconds)
|
||||
|
||||
protected def asyncVerifyEndorse(e: Signature, byteOfBlock: Array[Byte]): Future[Boolean] = {
|
||||
val result = Promise[Boolean]
|
||||
|
||||
val tmp = BlockVerify.VerifyOneEndorseOfBlock(e, byteOfBlock, pe.getSysTag)
|
||||
if (tmp._1) {
|
||||
result.success(true)
|
||||
} else {
|
||||
result.success(false)
|
||||
}
|
||||
result.future
|
||||
}
|
||||
|
||||
protected def asyncVerifyEndorses(block: Block): Boolean = {
|
||||
val b = block.clearEndorsements.toByteArray
|
||||
val listOfFuture: Seq[Future[Boolean]] = block.endorsements.map(x => {
|
||||
asyncVerifyEndorse(x, b)
|
||||
})
|
||||
val futureOfList: Future[List[Boolean]] = Future.sequence(listOfFuture.toList).recover({
|
||||
case e: Exception =>
|
||||
null
|
||||
})
|
||||
|
||||
val result1 = Await.result(futureOfList, timeout.duration).asInstanceOf[List[Boolean]]
|
||||
|
||||
var result = true
|
||||
if (result1 == null) {
|
||||
false
|
||||
} else {
|
||||
result1.foreach(f => {
|
||||
if (!f) {
|
||||
result = false
|
||||
RepLogger.trace(RepLogger.Consensus_Logger, this.getLogMsgPrefix(s"comfirmOfBlock verify endorse is error, break,block height=${block.height},local height=${pe.getCurrentHeight}"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
protected def handler(block: Block, actRefOfBlock: ActorRef)
|
||||
|
||||
protected def checkedOfConfirmBlock(block: Block, actRefOfBlock: ActorRef)
|
||||
|
||||
override def receive = {
|
||||
case ConfirmedBlock(block, actRefOfBlock) =>
|
||||
RepTimeTracer.setStartTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size)
|
||||
checkedOfConfirmBlock(block, actRefOfBlock)
|
||||
RepTimeTracer.setEndTime(pe.getSysTag, "blockconfirm", System.currentTimeMillis(), block.height, block.transactions.size)
|
||||
case _ => //ignore
|
||||
}
|
||||
}
|
@ -0,0 +1,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 {
|
||||
//错误,没有符合大多人背书要求。
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
60
src/main/scala/rep/network/consensus/byzantium/ConsensusCondition.scala
Executable file
60
src/main/scala/rep/network/consensus/byzantium/ConsensusCondition.scala
Executable 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)
|
||||
}
|
||||
|
||||
}
|
62
src/main/scala/rep/network/consensus/cfrd/MsgOfCFRD.scala
Normal file
62
src/main/scala/rep/network/consensus/cfrd/MsgOfCFRD.scala
Normal 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(共识)消息,结束/////////////////////////
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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 => {
|
@ -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 {
|
@ -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"DispatchOfRecvEndorsement,vote result equal,allow 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"DispatchOfRecvEndorsement,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( "DispatchOfRecvEndorsement,it 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"DispatchOfRecvEndorsement,blocker 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"DispatchOfRecvEndorsement,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"DispatchOfRecvEndorsement,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"DispatchOfRecvEndorsement,it 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"DispatchOfRecvEndorsement,do not endorse,it is synching,recv endorse request,endorse height=${block.height},local height=${pe.getCurrentHeight}"))
|
||||
}*/
|
||||
|
||||
router.route(EndorsementInfo(block, blocker), sender)
|
||||
case _ => //ignore
|
||||
}
|
||||
}
|
@ -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 equal,allow 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
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package rep.network.consensus.cfrd.vote
|
||||
|
||||
import akka.actor.Props
|
||||
import rep.app.conf.{SystemCertList, TimePolicy}
|
||||
import rep.log.RepLogger
|
||||
import rep.network.consensus.common.vote.IVoter
|
||||
import rep.network.module.cfrd.CFRDActorType
|
||||
import rep.network.consensus.cfrd.MsgOfCFRD.{CreateBlock, VoteOfBlocker,VoteOfForce}
|
||||
import rep.network.util.NodeHelp
|
||||
import rep.network.consensus.common.algorithm.IRandomAlgorithmOfVote
|
||||
|
||||
/**
|
||||
* Created by jiangbuyun on 2020/03/17.
|
||||
* 实现CFRD抽签actor
|
||||
*/
|
||||
|
||||
object VoterOfCFRD{
|
||||
def props(name: String): Props = Props(classOf[VoterOfCFRD],name)
|
||||
}
|
||||
|
||||
class VoterOfCFRD(moduleName: String) extends IVoter(moduleName: String) {
|
||||
import scala.concurrent.duration._
|
||||
import context.dispatcher
|
||||
|
||||
this.algorithmInVoted = new IRandomAlgorithmOfVote
|
||||
|
||||
override def preStart(): Unit = {
|
||||
RepLogger.info(RepLogger.Vote_Logger, this.getLogMsgPrefix("VoterOfCFRD module start"))
|
||||
}
|
||||
|
||||
override protected def NoticeBlockerMsg: Unit = {
|
||||
if (this.Blocker.blocker.equals(pe.getSysTag)) {
|
||||
//发送建立新块的消息
|
||||
pe.getActorRef(CFRDActorType.ActorType.blocker) ! CreateBlock
|
||||
}
|
||||
}
|
||||
|
||||
override protected def DelayVote: Unit = {
|
||||
this.voteCount += 1
|
||||
var time = this.voteCount * TimePolicy.getVoteRetryDelay
|
||||
schedulerLink = clearSched()
|
||||
schedulerLink = scheduler.scheduleOnce(TimePolicy.getVoteRetryDelay.millis, self, VoteOfBlocker)
|
||||
}
|
||||
|
||||
override protected def vote(isForce: Boolean): Unit = {
|
||||
if (checkTranNum || isForce) {
|
||||
val currentblockhash = pe.getCurrentBlockHash
|
||||
val currentheight = pe.getCurrentHeight
|
||||
if (this.Blocker.voteBlockHash == "") {
|
||||
this.cleanVoteInfo
|
||||
this.resetCandidator(currentblockhash)
|
||||
this.resetBlocker(0, currentblockhash, currentheight)
|
||||
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},first voter,blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr))
|
||||
} else {
|
||||
if (!this.Blocker.voteBlockHash.equals(currentblockhash)) {
|
||||
//抽签的基础块已经变化,需要重续选择候选人
|
||||
this.cleanVoteInfo
|
||||
this.resetCandidator(currentblockhash)
|
||||
this.resetBlocker(0, currentblockhash, currentheight)
|
||||
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},hash change,reset voter,height=${currentheight},hash=${currentblockhash},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr))
|
||||
} else {
|
||||
if (this.Blocker.blocker == "") {
|
||||
this.cleanVoteInfo
|
||||
this.resetCandidator(currentblockhash)
|
||||
this.resetBlocker(0, currentblockhash, currentheight)
|
||||
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},blocker=null,reset voter,height=${currentheight},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr))
|
||||
} else {
|
||||
if ((System.currentTimeMillis() - this.Blocker.voteTime) / 1000 > TimePolicy.getTimeOutBlock) {
|
||||
//说明出块超时
|
||||
this.voteCount = 0
|
||||
this.resetBlocker(this.Blocker.VoteIndex + 1, currentblockhash, currentheight)
|
||||
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},block timeout,reset voter,height=${currentheight},blocker=${this.Blocker.blocker},voteidx=${this.Blocker.VoteIndex}" + "~" + selfAddr))
|
||||
} else {
|
||||
NoticeBlockerMsg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RepLogger.trace(RepLogger.Vote_Logger, this.getLogMsgPrefix(s"sysname=${pe.getSysTag},transaction is not enough,waiting transaction,height=${pe.getCurrentHeight}" + "~" + selfAddr))
|
||||
}
|
||||
}
|
||||
|
||||
override def receive: Receive = {
|
||||
case VoteOfBlocker =>
|
||||
if (NodeHelp.isCandidateNow(pe.getSysTag, SystemCertList.getSystemCertList)) {
|
||||
voteMsgHandler(false)
|
||||
}
|
||||
case VoteOfForce=>
|
||||
voteMsgHandler(true)
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package rep.network.consensus.common
|
||||
|
||||
import akka.actor.ActorRef
|
||||
import rep.protos.peer.Block
|
||||
|
||||
|
||||
/**
|
||||
* Created by jiangbuyun on 2020/03/17.
|
||||
* 汇总共识层中所有公共的消息,目前公共的消息由预出块的交易预执行消息以及持久化的存储区块的消息。
|
||||
*/
|
||||
object MsgOfConsensus {
|
||||
///////////////////////////////预出块时,预执行交易的相关消息,开始//////////////////////////////
|
||||
//发送预出块给交易预执行分配器,预执行预出块里面的所有交易。
|
||||
case class PreTransBlock(block: Block, prefixOfDbTag: String)
|
||||
//预出块的预执行的结果消息
|
||||
case class PreTransBlockResult(blc: Block, result: Boolean)
|
||||
///////////////////////////////预出块时,预执行交易的相关消息,结束//////////////////////////////
|
||||
|
||||
///////////////////////////////存储时,发送给持久化actor的相关消息,开始//////////////////////////////
|
||||
//对于单个区块需要存储时,发送下面的消息给持久化actor。
|
||||
final case class BlockRestore(blk: Block, SourceOfBlock: Int, blker: ActorRef)
|
||||
//这个消息用于出块时,提高存储效率,发送批处理消息。处理机制是,先把确认块存放到缓存,发送消息给持久化,之后持久化actor开始存储。
|
||||
final case object BatchStore
|
||||
///////////////////////////////存储时,发送给持久化actor的相关消息,结束//////////////////////////////
|
||||
|
||||
///////////////////////////////创世块actor的相关消息,开始//////////////////////////////
|
||||
case object GenesisBlock
|
||||
///////////////////////////////创世块actor的相关消息,结束//////////////////////////////
|
||||
|
||||
///////////////////////////////块确认actor的相关消息,开始//////////////////////////////
|
||||
//共识完成之后,广播正式出块的消息
|
||||
case class ConfirmedBlock(blc: Block, actRef: ActorRef)
|
||||
///////////////////////////////块确认actor的相关消息,结束//////////////////////////////
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package rep.network.consensus.common.algorithm
|
||||
|
||||
/**
|
||||
* Created by jiangbuyun on 2020/03/17.
|
||||
* 定义抽签算法的接口
|
||||
*/
|
||||
trait IAlgorithmOfVote {
|
||||
/**
|
||||
* 获取出块人(竞争胜出者)
|
||||
* @param nodes
|
||||
* @tparam T
|
||||
* @return
|
||||
*/
|
||||
def blocker(nodes:Array[String], position:Int):String
|
||||
|
||||
/**
|
||||
* 获取候选人节点
|
||||
* @param nodes
|
||||
* @tparam T
|
||||
* @param seed 随机种子
|
||||
* @return
|
||||
*/
|
||||
def candidators(Systemname:String,hash:String,nodes:Set[String], seed:Array[Byte]):Array[String]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user