From 00542995eb013a1eecf05bc60dedcad51f31d5e4 Mon Sep 17 00:00:00 2001 From: brightestboy Date: Tue, 26 Jan 2021 15:01:45 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81feat:=20=E5=A2=9E=E5=8A=A0GenesisBuil?= =?UTF-8?q?derTool=EF=BC=8C=E6=89=93=E5=8C=85=E5=88=B0RepChain.jar?= =?UTF-8?q?=E4=B9=8B=E5=90=8E=E6=94=AF=E6=8C=81=E4=BD=BF=E7=94=A8=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E7=94=9F=E6=88=90gensis.json=E6=96=87=E4=BB=B6;2?= =?UTF-8?q?=E3=80=81=E5=A2=9E=E5=BC=BA=E5=88=9B=E4=B8=96=E5=9D=97=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=B7=A5=E5=85=B7GenesisBuilderMulti=EF=BC=9A?= =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B3=A8=E5=86=8C=E8=AF=81=E4=B9=A6=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E4=B8=9A=E5=8A=A1=E5=90=88=E7=BA=A6=E7=9A=84?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E7=A4=BA=E4=BE=8B=EF=BC=9B3=E3=80=81?= =?UTF-8?q?=E9=83=A8=E5=88=86=E6=9B=B4=E6=AD=A3gensis.json=E4=B8=BAgenesis?= =?UTF-8?q?.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. "命令格式eg:java -Dgenesis=./genesis.json -cp RepChain.jar rep.utils.GenesisBuilderTool ./jks ./jks/certs ./tpl/ContractCertTPL.scala ./tpl/CustomTPL.scala tpl/CustomTPL1.scala" 2. GenesisBuilderMulti可注册业务合约 3. GenesisBuilderTool暂不能执行调用合约的交易 4. 部分更正gensis.json为genesis.json,一些源码文件里的暂时没有修改 --- api_req/README.md | 2 +- json/{gensis.json => genesis.json} | 0 .../network/consensus/util/BlockHelp.scala | 2 +- src/main/scala/rep/utils/GenesisBuilder.scala | 2 +- .../scala/rep/utils/GenesisBuilderMulti.scala | 33 +++- .../scala/rep/utils/GenesisBuilderTool.scala | 182 ++++++++++++++++++ 6 files changed, 215 insertions(+), 6 deletions(-) rename json/{gensis.json => genesis.json} (100%) create mode 100644 src/main/scala/rep/utils/GenesisBuilderTool.scala diff --git a/api_req/README.md b/api_req/README.md index b6800f37..ca50f4df 100644 --- a/api_req/README.md +++ b/api_req/README.md @@ -35,5 +35,5 @@ * 该jmeter测试脚本,执行一次过后,清除一下区块,再进行下一次测试演示 * 将jmx/7a0fa308-9bba-415f-ae10-39832ef2b52f放到jmeter的目录下,该文件用来测试`/transaction/postTranStream` * /transaction/postTran只能在debug模式下使用,在jar部署模式下,该接口不能使用 - * 本脚本中根据transactionId获取交易数据使用的创世块中内置的交易,根据blockId获取块数据以及根据高度获取块数据都是获取的创世块示例。(即、对应于目前项目仓库中的/json/gensis.json) + * 本脚本中根据transactionId获取交易数据使用的创世块中内置的交易,根据blockId获取块数据以及根据高度获取块数据都是获取的创世块示例。(即、对应于目前项目仓库中的/json/genesis.json) 4. **TODO** 未完待续 \ No newline at end of file diff --git a/json/gensis.json b/json/genesis.json similarity index 100% rename from json/gensis.json rename to json/genesis.json diff --git a/src/main/scala/rep/network/consensus/util/BlockHelp.scala b/src/main/scala/rep/network/consensus/util/BlockHelp.scala index f27812ad..4c89032b 100644 --- a/src/main/scala/rep/network/consensus/util/BlockHelp.scala +++ b/src/main/scala/rep/network/consensus/util/BlockHelp.scala @@ -124,7 +124,7 @@ object BlockHelp { } def CreateGenesisBlock:Block={ - val blkJson = scala.io.Source.fromFile("json/gensis.json","UTF-8") + val blkJson = scala.io.Source.fromFile("json/genesis.json","UTF-8") val blkStr = try blkJson.mkString finally blkJson.close() val gen_blk = JsonFormat.fromJsonString[Block](blkStr) gen_blk diff --git a/src/main/scala/rep/utils/GenesisBuilder.scala b/src/main/scala/rep/utils/GenesisBuilder.scala index 97e95347..2629a791 100644 --- a/src/main/scala/rep/utils/GenesisBuilder.scala +++ b/src/main/scala/rep/utils/GenesisBuilder.scala @@ -141,7 +141,7 @@ object GenesisBuilder { val rstr = pretty(render(r)) println(rstr) - val pw = new PrintWriter("json/gensis.json","UTF-8") + val pw = new PrintWriter("json/genesis.json","UTF-8") pw.write(rstr) pw.flush() pw.close() diff --git a/src/main/scala/rep/utils/GenesisBuilderMulti.scala b/src/main/scala/rep/utils/GenesisBuilderMulti.scala index f72e6f99..11ba2bd2 100644 --- a/src/main/scala/rep/utils/GenesisBuilderMulti.scala +++ b/src/main/scala/rep/utils/GenesisBuilderMulti.scala @@ -19,18 +19,20 @@ package rep.utils import java.io.{File, FileFilter, FileWriter, PrintWriter} import java.util +import com.google.protobuf.timestamp.Timestamp import org.json4s.jackson.JsonMethods.{pretty, render} import org.json4s.{DefaultFormats, jackson} import rep.crypto.cert.SignTool import rep.network.autotransaction.PeerHelper import rep.protos.peer.{Block, ChaincodeId, Signer, Transaction} +import rep.sc.tpl.CertInfo import scalapb.json4s.JsonFormat import scala.collection.mutable /** - * 将整个jks下所有node的账户都注册上去(遍历node的jks),并为账户赋初值,证书暂时没有注册 + * 将整个jks下所有node的账户都注册上去(遍历node的jks),并为账户赋初值,以及注册相应的证书 * * @author zyf */ @@ -64,6 +66,11 @@ object GenesisBuilderMulti { transList.add(PeerHelper.createTransaction4Invoke("951002007l78123233.super_admin", cid1, "SignUpSigner", Seq(SerializeUtils.compactJson(signers(i))))) } + val certs = fillCerts(signers) + for (i <- certs.indices) { + transList.add(PeerHelper.createTransaction4Invoke("951002007l78123233.super_admin", cid1, "SignUpCert", Seq(SerializeUtils.compactJson(certs(i))))) + } + val sysName = "121000005l35120456.node1" val s2 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/ContractAssetsTPL.scala","UTF-8") val l2 = try s2.mkString finally s2.close() @@ -80,6 +87,14 @@ object GenesisBuilderMulti { transList.add(dep_set_trans) + // 可选的业务合约,如果没有,这里需要注释 +// val s4 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/CustomTPL.scala","UTF-8") +// val l4 = try s4.mkString finally s4.close() +// val cid4 = new ChaincodeId("CustomTPL", 1) +// val dep_process_proof = PeerHelper.createTransaction4Deploy(sysName, cid4, l4, "", 5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA) +// // 如果没有上述的业务合约,这里需要注释 +// transList.add(dep_process_proof) + var blk = new Block(1, 1, transList.toArray(new Array[Transaction](transList.size())), Seq(), _root_.com.google.protobuf.ByteString.EMPTY, _root_.com.google.protobuf.ByteString.EMPTY) @@ -89,7 +104,7 @@ object GenesisBuilderMulti { val rStr = pretty(render(r)) println(rStr) - val pw = new PrintWriter("json/gensis.json","UTF-8") + val pw = new PrintWriter("json/genesis.json","UTF-8") pw.write(rStr) pw.flush() pw.close() @@ -115,9 +130,21 @@ object GenesisBuilderMulti { for (i <- 1 until signers.length) { val fileNameSplit = files(i - 1).getName.split('.') signers(i) = Signer(fileNameSplit(1), fileNameSplit(0), "18912345678", List(fileNameSplit(1))) - setMap.put(fileNameSplit(0), 10000000) + setMap.put(fileNameSplit(0), 100000000) } signers } + def fillCerts(signers: Array[Signer]): Array[CertInfo] = { + val certInfos: Array[CertInfo] = new Array[CertInfo](signers.length) + for (i <- 0 until certInfos.length) { + val certfile = scala.io.Source.fromFile("jks/" + signers(i).creditCode + "." + signers(i).name + ".cer", "UTF-8") + val certstr = try certfile.mkString finally certfile.close() + val millis = System.currentTimeMillis() + val cert = rep.protos.peer.Certificate(certstr, "SHA1withECDSA", true, Option(Timestamp(millis / 1000, ((millis % 1000) * 1000000).toInt))) + certInfos(i) = CertInfo(signers(i).creditCode, signers(i).name, cert) + } + certInfos + } + } diff --git a/src/main/scala/rep/utils/GenesisBuilderTool.scala b/src/main/scala/rep/utils/GenesisBuilderTool.scala new file mode 100644 index 00000000..15af9503 --- /dev/null +++ b/src/main/scala/rep/utils/GenesisBuilderTool.scala @@ -0,0 +1,182 @@ +/* + * 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.utils + +import java.io.{File, FileFilter, PrintWriter} +import java.nio.file.Path +import java.util + +import com.google.common.io.Files +import com.google.protobuf.timestamp.Timestamp +import org.json4s.jackson.JsonMethods.{pretty, render} +import org.json4s.{DefaultFormats, jackson} +import rep.crypto.cert.SignTool +import rep.network.autotransaction.PeerHelper +import rep.protos.peer.{Block, ChaincodeId, Signer, Transaction} +import rep.sc.tpl.CertInfo +import scalapb.json4s.JsonFormat + +import scala.collection.mutable + + +/** + * 将整个jks下所有node的账户都注册上去(遍历node的jks),以及注册相应的证书 + * + * @author zyf + */ +object GenesisBuilderTool { + + implicit val serialization = jackson.Serialization // or native.Serialization + implicit val formats = DefaultFormats + private val setMap = new mutable.HashMap[String, Int]() + private var jksFile = new File("jks") + private var certsFile = new File("jks/certs") + private var contractFile = new File("src/main/scala/rep/sc/tpl/ContractCert.scala") + private var adminJksName = "" + + def main(args: Array[String]): Unit = { + + println("命令格式为:java -Dgenesis=./genesis.json -cp RepChain.jar rep.utils.GenesisBuilderTool ./jks ./jks/certs ./tpl/ContractCertTPL.scala ./tpl/CustomTPL.scala tpl/CustomTPL1.scala") + println("命令格式为:java '可选的设置genesis.json写入文件' -cp RepChain.jar rep.utils.GenesisBuilderTool 节点jks目录 节点证书目录 ‘ContractCert.scala’文件所在 可选的业务合约...") + + // 简单的校验 + if (args.length >= 3) { + jksFile = new File(args(0)) + certsFile = new File(args(1)) + contractFile = new File(args(2)) + if (!jksFile.isDirectory || !certsFile.isDirectory) { + throw new RuntimeException("节点jks或者certs参数输入为非目录") + } + } else if (args.length >= 1 && args.length <= 2) { + throw new RuntimeException("参数个数应该为0或者3个及以上") + } + + val signers = fillSigners() + val certs = fillCerts(signers) + + println(Path.of(jksFile.getPath, adminJksName).toString) + + // 导入管理员的私钥,进行签名操作 + SignTool.loadPrivateKey(adminJksName.substring(0, adminJksName.length - 4), "super_admin", Path.of(jksFile.getPath, adminJksName).toString) + + val transList = new util.ArrayList[Transaction] + + //交易发起人是超级管理员,注册系统必须的账户管理合约 + val s1 = scala.io.Source.fromFile(contractFile, "UTF-8") + val l1 = try s1.mkString finally s1.close() + val cid1 = new ChaincodeId("ContractCert", 1) + val dep_trans = PeerHelper.createTransaction4Deploy(adminJksName.substring(0, adminJksName.length - 4), cid1, l1, "", 5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA) + transList.add(dep_trans) + + val adminInfo = adminJksName.split("\\.") + // 注册节点与管理员的账户 + for (i <- signers.indices) { + transList.add(PeerHelper.createTransaction4Invoke(adminJksName.substring(0, adminJksName.length - 4), cid1, "SignUpSigner", Seq(JsonFormat.toJsonString(signers(i))))) + } + // 注册节点与管理员的证书 + for (i <- certs.indices) { + transList.add(PeerHelper.createTransaction4Invoke(adminJksName.substring(0, adminJksName.length - 4), cid1, "SignUpCert", Seq(SerializeUtils.compactJson(certs(i))))) + } + + // 可选的部署业务合约 + for (i <- 3 until args.length) { + val tplFile = new File(args(i)) + val s2 = scala.io.Source.fromFile(tplFile, "UTF-8") + val l2 = try s2.mkString finally s2.close() + val tplFileName = tplFile.getName.split("\\.")(0) + val cid4 = new ChaincodeId(tplFileName, 1) + val dep_custom_proof = PeerHelper.createTransaction4Deploy(adminJksName.substring(0, adminJksName.length - 4), cid4, l2, "", 5000, rep.protos.peer.ChaincodeDeploy.CodeType.CODE_SCALA) + transList.add(dep_custom_proof) + } + + // 构建Block + var blk = new Block(1, 1, transList.toArray(new Array[Transaction](transList.size())), Seq(), _root_.com.google.protobuf.ByteString.EMPTY, + _root_.com.google.protobuf.ByteString.EMPTY) + + blk = blk.clearEndorsements + blk = blk.clearTransactionResults + val r = JsonFormat.toJson(blk) + val rStr = pretty(render(r)) + println(rStr) + + // 从系统级属性中获取要存放的genesis.json路径,并写入 + val genesisPath = System.getProperty("genesis") match { + case null => + "./genesis.json" + case _ => System.getProperty("genesis") + } + + val pw = new PrintWriter({ + val genesisFile = new File(genesisPath) + if (!genesisFile.exists) { + Files.createParentDirs(genesisFile) + } + genesisFile + }, "UTF-8") + pw.write(rStr) + pw.flush() + pw.close() + } + + /** + * 将jks目录下的所有节点账户账户数组中 + * + * @return + */ + def fillSigners(): Array[Signer] = { + // 过滤掉非节点node的jks + val files = jksFile.listFiles(new FileFilter { + override def accept(file: File): Boolean = { + val fileName = file.getName + !file.isDirectory && fileName.endsWith("jks") && (fileName.contains("node") || fileName.contains("super_admin")) + } + }) + + val signers: Array[Signer] = new Array[Signer](files.length) + for (i <- 0 until signers.length) { + val fileName = files(i).getName + if (fileName.contains("super_admin")) { + adminJksName = fileName + } + val fileNameSplit = fileName.split('.') + signers(i) = Signer(fileNameSplit(1), fileNameSplit(0), "", List(fileNameSplit(1))) + } + signers + } + + def fillCerts(signers: Array[Signer]): Array[CertInfo] = { + val certInfos: Array[CertInfo] = new Array[CertInfo](signers.length) + // 过滤掉非节点node的cer + val files = certsFile.listFiles((pathname: File) => { + def foo(pathname: File) = { + val fileName = pathname.getName + !pathname.isDirectory && fileName.endsWith("cer") && (fileName.contains("node") || fileName.contains("super_admin")) + } + + foo(pathname) + }) + for (i <- 0 until certInfos.length) { + val certfile = scala.io.Source.fromFile(Path.of(certsFile.getPath, signers(i).creditCode + "." + signers(i).name + ".cer").toFile, "UTF-8") + val certstr = try certfile.mkString finally certfile.close() + val millis = System.currentTimeMillis() + val cert = rep.protos.peer.Certificate(certstr, "SHA1withECDSA", true, Option(Timestamp(millis / 1000, ((millis % 1000) * 1000000).toInt))) + certInfos(i) = CertInfo(signers(i).creditCode, signers(i).name, cert) + } + certInfos + } + +}