mirror of
https://gitee.com/BTAJL/repchain.git
synced 2024-12-02 19:58:55 +08:00
Merge branch 'dev_wuwei1972' into dev_supply
# Conflicts: # build.sbt # conf/system.conf # scripts/example_deploy.js # src/main/scala/ContractAssetsTPL.scala # src/main/scala/Contractback.txt # src/main/scala/NewContract.scala # src/main/scala/rep/api/SwaggerDocService.scala # src/main/scala/rep/api/rest/RestActor.scala # src/main/scala/rep/api/rest/RestService.scala # src/main/scala/rep/app/conf/SystemProfile.scala # src/main/scala/rep/crypto/ECDSASign.scala # src/main/scala/rep/crypto/Sha256.scala # src/main/scala/rep/crypto/SignFunc.scala # src/main/scala/rep/log/EventActor.scala # src/main/scala/rep/network/PeerHelper.scala # src/main/scala/rep/network/cache/TransactionPool.scala # src/main/scala/rep/network/consensus/block/BlockHelper.scala # src/main/scala/rep/network/consensus/block/BlockModule.scala # src/main/scala/rep/network/consensus/endorse/EndorsementModule.scala # src/main/scala/rep/network/consensus/vote/CRFDVoter.scala # src/main/scala/rep/network/consensus/vote/CRFDVoterModule.scala # src/main/scala/rep/network/consensus/vote/VoterBase.scala # src/main/scala/rep/network/tools/PeerExtension.scala # src/main/scala/rep/sc/Sandbox.scala # src/main/scala/rep/sc/Shim.scala # src/main/scala/rep/sc/contract/Compiler.scala # src/main/scala/rep/sc/scalax/SandboxScala.scala # src/main/scala/rep/storage/cfg/StoreConfig.java # src/main/scala/rep/storage/test/testmap.scala # src/main/scala/rep/storage/util/pathUtil.java # src/main/scala/rep/utils/SerializeUtils.scala # src/test/scala/rep/sc/SandboxSpec.scala
This commit is contained in:
commit
3235d348fc
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/bin/
|
@ -62,7 +62,7 @@ libraryDependencies ++= Seq(
|
||||
"de.heikoseeberger" % "akka-http-json4s_2.11" % "1.16.1",
|
||||
"org.json4s" %% "json4s-native" % "3.5.4",
|
||||
"org.json4s" %% "json4s-jackson" % "3.5.4",
|
||||
|
||||
|
||||
"ch.megard" %% "akka-http-cors" % "0.2.2"
|
||||
)
|
||||
|
||||
|
@ -70,14 +70,18 @@ akka.http {
|
||||
system {
|
||||
//api是否开启
|
||||
//如果是单机多节点测试模式(Repchain,则选择0,默认节点1会开启)
|
||||
ws_enable = 0//api 0,不开启;1,开启
|
||||
ws_enable = 1//api 0,不开启;1,开启
|
||||
//交易生产方式
|
||||
trans_create_type = 0 //0,手动;1,自动
|
||||
trans_create_type = 1 //0,手动;1,自动
|
||||
//是否进行TPS测试
|
||||
statistic_enable = 0 // 0,unable;able
|
||||
|
||||
httpServicePort = 8081//http服务的端口号,默认为8081
|
||||
|
||||
|
||||
checkCertValidate = 0//设置是否检查证书的有效性,默认为0 0=不校验,1=校验
|
||||
|
||||
contractOperationMode = 0//设置合约的运行方式,0=debug方式,1=deploy,默认为debug方式,如果发布部署,必须使用deploy方式。
|
||||
|
||||
block {
|
||||
//块内交易的最大数量
|
||||
trans_num_limit = 50
|
||||
@ -98,7 +102,7 @@ system {
|
||||
|
||||
transaction {
|
||||
//辅助自动创建交易的间隔
|
||||
tran_create_dur = 50 //millis
|
||||
tran_create_dur = 100 //millis
|
||||
//最大交易缓存量
|
||||
max_cache_num = 10000
|
||||
}
|
||||
|
@ -14,12 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import rep.sc.contract._
|
||||
import scala.reflect.ManifestFactory.classType
|
||||
|
||||
/**
|
||||
* 资产管理合约
|
||||
|
@ -14,12 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import rep.sc.contract._
|
||||
import scala.reflect.ManifestFactory.classType
|
||||
import rep.storage.FakeStorage.Key
|
||||
|
||||
/**
|
||||
* 资产管理合约
|
||||
|
@ -178,35 +178,23 @@ class RestActor extends Actor with ModuleHelper with RepLogging {
|
||||
val sig = txr.signature.toByteArray
|
||||
val tOutSig1 = txr.withSignature(ByteString.EMPTY)
|
||||
val tOutSig = tOutSig1.withMetadata(ByteString.EMPTY)
|
||||
val peercert = ECDSASign.getCertByBitcoinAddr(txr.cert.toStringUtf8) // 从信任列表中取得证书
|
||||
// TODO 把节点证书存放在worldstate中,然后再取出来还原,看是否和节点证书一样
|
||||
// val certF = CertificateFactory.getInstance("X.509")
|
||||
// val kvcer = certF.generateCertificate(new ByteArrayInputStream(cer.get)) // 从kv中获得相应的证书
|
||||
// val cid = txr.payload.get.chaincodeID.get.name
|
||||
val cid = ChaincodeID.fromAscii(txr.chaincodeID.toStringUtf8).name
|
||||
val certKey = WorldStateKeyPreFix + cid + "_" + PRE_CERT + txr.cert.toStringUtf8
|
||||
val cert = Option(sr.Get(certKey)) // 从worldstate中取证书,用户注册好像是以前缀形式写进去的
|
||||
try {
|
||||
if (peercert != None) {
|
||||
//TODO 验证签名
|
||||
ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), peercert.get.getPublicKey) match {
|
||||
try{
|
||||
var cert = ECDSASign.getCertWithCheck(txr.cert.toStringUtf8,certKey,pe.getSysTag)
|
||||
if(cert != None){
|
||||
ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), cert.get.getPublicKey) match {
|
||||
case true =>
|
||||
case false => throw new RuntimeException("验证签名出错")
|
||||
}
|
||||
} else if (cert != None){
|
||||
if (new String(cert.get) == "null") {
|
||||
throw new RuntimeException("该用户证书已注销")
|
||||
}
|
||||
val kvcert = SerializeUtils.deserialise(cert.get).asInstanceOf[Certificate] //rep序列化与反序列化字节数组
|
||||
ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), kvcert.getPublicKey) match {
|
||||
case true =>
|
||||
// ImpDataPreloadMgr.Free(pe.getSysTag, "preload")
|
||||
case false => throw new RuntimeException("验证签名出错")
|
||||
}
|
||||
} else {
|
||||
//TODO 没有找到证书的情况下,是直接抛出错误
|
||||
}else{
|
||||
throw new RuntimeException("没有证书")
|
||||
}
|
||||
}catch{
|
||||
case e : RuntimeException => throw e
|
||||
}
|
||||
|
||||
try {
|
||||
val future = sandbox ? PreTransaction(txr)
|
||||
val result = Await.result(future, timeout.duration).asInstanceOf[DoTransactionResult]
|
||||
val rv = result
|
||||
@ -242,6 +230,8 @@ class RestActor extends Actor with ModuleHelper with RepLogging {
|
||||
val result = Await.result(future, timeout.duration).asInstanceOf[DoTransactionResult]
|
||||
val rv = result
|
||||
|
||||
ImpDataPreloadMgr.Free(pe.getDBTag,t.txid)
|
||||
|
||||
rv.err match {
|
||||
case None =>
|
||||
//预执行正常,提交并广播交易
|
||||
|
@ -43,15 +43,27 @@ object SystemProfile {
|
||||
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 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 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
|
||||
@ -116,6 +128,8 @@ object SystemProfile {
|
||||
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"))
|
||||
}
|
||||
|
||||
|
||||
@ -137,4 +151,8 @@ object SystemProfile {
|
||||
def getDiskSpaceAlarm = DISKSPACE_ALARM_NUM
|
||||
|
||||
def getHttpServicePort = SERVERPORT
|
||||
|
||||
def getCheckCertValidate = CHECKCERTVALIDATE
|
||||
|
||||
def getContractOperationMode = CONTRACTOPERATIONMODE
|
||||
}
|
||||
|
@ -18,11 +18,11 @@ package rep.crypto
|
||||
import java.security._
|
||||
import java.io._
|
||||
import java.security.cert.{ Certificate, CertificateFactory }
|
||||
|
||||
import rep.app.conf.SystemProfile
|
||||
import com.google.protobuf.ByteString
|
||||
import fastparse.utils.Base64
|
||||
import rep.utils.SerializeUtils
|
||||
|
||||
import rep.storage._
|
||||
import scala.collection.mutable
|
||||
import com.fasterxml.jackson.core.Base64Variants
|
||||
import java.security.cert.X509Certificate
|
||||
@ -128,7 +128,14 @@ object ECDSASign extends ECDSASign {
|
||||
* @return
|
||||
*/
|
||||
def getCertByBitcoinAddr(addr: String): Option[Certificate] = {
|
||||
trustkeysPubAddrMap.get(addr)
|
||||
var tmpcert = trustkeysPubAddrMap.get(addr)
|
||||
if(checkCertificate(new java.util.Date(), tmpcert.get)){
|
||||
tmpcert
|
||||
}else{
|
||||
throw new RuntimeException("证书已经过期")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,8 +179,11 @@ object ECDSASign extends ECDSASign {
|
||||
def getKeyPair(alias: String): (PrivateKey, PublicKey, Array[Byte]) = {
|
||||
val sk = keyStore(alias).getKey(alias, password(alias).toCharArray)
|
||||
val cert = keyStore(alias).getCertificate(alias)
|
||||
// (sk.asInstanceOf[PrivateKey], cert.getPublicKey(), cert.getEncoded)
|
||||
(sk.asInstanceOf[PrivateKey], cert.getPublicKey(), SerializeUtils.serialise(cert))
|
||||
if(checkCertificate(new java.util.Date(), cert)){
|
||||
(sk.asInstanceOf[PrivateKey], cert.getPublicKey(), SerializeUtils.serialise(cert))
|
||||
}else{
|
||||
throw new RuntimeException("证书已经过期")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,4 +356,67 @@ class ECDSASign extends SignFunc {
|
||||
s2.verify(signature)
|
||||
}
|
||||
|
||||
def getCertWithCheck(certAddr:String,certKey:String,sysTag:String):Option[java.security.cert.Certificate]={
|
||||
val cert = ECDSASign.getCertByBitcoinAddr(certAddr)
|
||||
if(cert != None) {
|
||||
if(checkCertificate(new java.util.Date(), cert.get)){
|
||||
cert
|
||||
}else{
|
||||
throw new RuntimeException("证书已经过期")
|
||||
}
|
||||
}else{
|
||||
if(certKey == null || sysTag == null){
|
||||
throw new RuntimeException("没有证书")
|
||||
}else{
|
||||
try{
|
||||
val sr: ImpDataAccess = ImpDataAccess.GetDataAccess(sysTag)
|
||||
val cert = Option(sr.Get(certKey))
|
||||
if (cert != None){
|
||||
if (new String(cert.get) == "null") {
|
||||
throw new RuntimeException("用户证书已经注销")
|
||||
}else{
|
||||
val kvcert = SerializeUtils.deserialise(cert.get).asInstanceOf[Certificate]
|
||||
if(kvcert != null){
|
||||
if(checkCertificate(new java.util.Date(), kvcert)){
|
||||
Some(kvcert)
|
||||
}else{
|
||||
throw new RuntimeException("证书已经过期")
|
||||
}
|
||||
}else{
|
||||
throw new RuntimeException("证书内容错误")
|
||||
}
|
||||
}
|
||||
}else{
|
||||
throw new RuntimeException("没有证书")
|
||||
}
|
||||
}catch{
|
||||
case e : Exception =>throw new RuntimeException("证书获取过程中发生错误",e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def checkCertificate(date:java.util.Date, cert:Certificate):Boolean={
|
||||
var isValid :Boolean = false
|
||||
var start = System.currentTimeMillis()
|
||||
try {
|
||||
if(SystemProfile.getCheckCertValidate == 0){
|
||||
isValid = true
|
||||
}else if(SystemProfile.getCheckCertValidate == 1){
|
||||
if(cert.isInstanceOf[X509Certificate]){
|
||||
var x509cert :X509Certificate = cert.asInstanceOf[X509Certificate]
|
||||
x509cert.checkValidity(date)
|
||||
isValid = true
|
||||
}
|
||||
}else{
|
||||
isValid = true
|
||||
}
|
||||
} catch{
|
||||
case e : Exception => isValid = false
|
||||
}
|
||||
var end = System.currentTimeMillis()
|
||||
//println("check cert validate,spent time="+(end-start))
|
||||
isValid;
|
||||
}
|
||||
|
||||
}
|
@ -19,16 +19,24 @@ import com.google.protobuf.ByteString
|
||||
|
||||
/**
|
||||
* @author c4w
|
||||
* modify by jiangbuyun
|
||||
*/
|
||||
object Sha256 extends CryptographicHash{
|
||||
override val DigestSize: Int = 32
|
||||
def hash(input: Array[Byte]): Array[Byte] = MessageDigest.getInstance("SHA-256").digest(input)
|
||||
|
||||
def hashstr(input: Array[Byte]):String ={
|
||||
BytesHex.bytes2hex(hash(input))
|
||||
}
|
||||
|
||||
def hashstr(input: String):String ={
|
||||
val iptb = ByteString.copyFromUtf8(input)
|
||||
BytesHex.bytes2hex(hash(iptb.toByteArray()))
|
||||
}
|
||||
|
||||
def hashToBytes(input: String):Array[Byte] ={
|
||||
val iptb = ByteString.copyFromUtf8(input)
|
||||
hash(iptb.toByteArray())
|
||||
}
|
||||
|
||||
}
|
@ -23,4 +23,5 @@ import java.security._
|
||||
trait SignFunc {
|
||||
def sign(privateKey: PrivateKey, message: Array[Byte]): Array[Byte]
|
||||
def verify(signature: Array[Byte], message: Array[Byte], publicKey: PublicKey): Boolean
|
||||
def getCertWithCheck(certAddr:String,certKey:String,sysTag:String):Option[java.security.cert.Certificate]
|
||||
}
|
@ -123,11 +123,15 @@ object PeerHelper {
|
||||
}
|
||||
t = t.withTxid(txid)
|
||||
//Signature
|
||||
val (priKey, pubKey, cert) = ECDSASign.getKeyPair(nodeName)
|
||||
t = t.withCert(ByteString.copyFromUtf8(ECDSASign.getBitcoinAddrByCert(cert)))
|
||||
//Get signature with tx hash(include cert)
|
||||
val sig = ECDSASign.sign(priKey,getTxHash(t))
|
||||
t = t.withSignature(ByteString.copyFrom(sig))
|
||||
try{
|
||||
val (priKey, pubKey, cert) = ECDSASign.getKeyPair(nodeName)
|
||||
t = t.withCert(ByteString.copyFromUtf8(ECDSASign.getBitcoinAddrByCert(cert)))
|
||||
//Get signature with tx hash(include cert)
|
||||
val sig = ECDSASign.sign(priKey,getTxHash(t))
|
||||
t = t.withSignature(ByteString.copyFrom(sig))
|
||||
}catch{
|
||||
case e:RuntimeException => throw e
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
@ -191,13 +195,17 @@ class PeerHelper(name: String) extends ModuleBase(name) {
|
||||
case TickInvoke =>
|
||||
//invoke
|
||||
// val cname = t.payload.get.chaincodeID.get.name
|
||||
val t2 = transactionCreator(pe.getSysTag,rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE,
|
||||
"", li1 ,List(),"", Option(chaincode),rep.protos.peer.ChaincodeSpec.CodeType.CODE_JAVASCRIPT)
|
||||
//getActorRef(ActorType.TRANSACTION_POOL) ! t2
|
||||
val t3 = transactionCreator(pe.getSysTag,rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE,
|
||||
"", "transfer" ,Seq(li2),"", Option(chaincode),rep.protos.peer.ChaincodeSpec.CodeType.CODE_JAVASCRIPT)
|
||||
getActorRef(ActorType.TRANSACTION_POOL) ! t3
|
||||
scheduler.scheduleOnce(SystemProfile.getTranCreateDur.millis, self, TickInvoke)
|
||||
try{
|
||||
val t2 = transactionCreator(pe.getSysTag,rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE,
|
||||
"", li1 ,List(),"", Option(chaincode),rep.protos.peer.ChaincodeSpec.CodeType.CODE_JAVASCRIPT)
|
||||
//getActorRef(ActorType.TRANSACTION_POOL) ! t2
|
||||
val t3 = transactionCreator(pe.getSysTag,rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE,
|
||||
"", "transfer" ,Seq(li2),"", Option(chaincode),rep.protos.peer.ChaincodeSpec.CodeType.CODE_JAVASCRIPT)
|
||||
getActorRef(ActorType.TRANSACTION_POOL) ! t3
|
||||
scheduler.scheduleOnce(SystemProfile.getTranCreateDur.millis, self, TickInvoke)
|
||||
}catch{
|
||||
case e:RuntimeException => throw e
|
||||
}
|
||||
// println(sdf.format(System.currentTimeMillis())+" ########## "+pe.getSysTag+" ************* ")
|
||||
}
|
||||
}
|
||||
|
@ -74,45 +74,26 @@ class TransactionPool(moduleName: String) extends ModuleBase(moduleName) {
|
||||
var result = false
|
||||
val sig = t.signature.toByteArray
|
||||
val tOutSig = t.withSignature(ByteString.EMPTY)
|
||||
val certTx = ECDSASign.getCertByBitcoinAddr(t.cert.toStringUtf8)
|
||||
certTx.getOrElse(None) match {
|
||||
case None =>
|
||||
val cid = ChaincodeID.fromAscii(t.chaincodeID.toStringUtf8).name
|
||||
val certKey = WorldStateKeyPreFix + cid + "_" + "CERT_" + t.cert.toStringUtf8 // 普通用户证书的key
|
||||
val cert = Option(dataaccess.Get(certKey)) // 从worldstate中取证书,用户注册是以前缀形式写进去的
|
||||
cert.getOrElse(None) match {
|
||||
case None => resultMsg = s"The transaction(${t.txid}) is not trusted"
|
||||
case _ =>
|
||||
if (new String(cert.get) == "null") {
|
||||
throw new RuntimeException("该用户证书已注销")
|
||||
}
|
||||
//验证签名和内容hash
|
||||
val kvcert = SerializeUtils.deserialise(cert.get).asInstanceOf[Certificate] //rep序列化与反序列化字节数组
|
||||
ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), kvcert.getPublicKey) match {
|
||||
case true =>
|
||||
val cid = ChaincodeID.fromAscii(t.chaincodeID.toStringUtf8).name
|
||||
val certKey = WorldStateKeyPreFix + cid + "_" + "CERT_" + t.cert.toStringUtf8 // 普通用户证书的key
|
||||
try{
|
||||
var cert = ECDSASign.getCertWithCheck(t.cert.toStringUtf8,certKey,pe.getSysTag)
|
||||
if(cert != None){
|
||||
ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), cert.get.getPublicKey) match {
|
||||
case true =>
|
||||
dataAccess.getBlockByTxId(t.txid) match {
|
||||
case null => result = true
|
||||
case _ => resultMsg = s"The transaction(${t.txid}) is duplicated with txid"
|
||||
}
|
||||
case false => resultMsg = s"The transaction(${t.txid}) is not completed"
|
||||
}
|
||||
}
|
||||
}else{
|
||||
throw new RuntimeException("没有证书")
|
||||
}
|
||||
case _ =>
|
||||
val alias = ECDSASign.getAliasByCert(certTx.get).getOrElse(None)
|
||||
alias match {
|
||||
case None => resultMsg = s"The transaction(${t.txid}) is not trusted"
|
||||
case _ =>
|
||||
//验证签名和内容hash
|
||||
ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), certTx.get.getPublicKey) match {
|
||||
case false => resultMsg = s"The transaction(${t.txid}) is not completed"
|
||||
case true =>
|
||||
dataAccess.getBlockByTxId(t.txid) match {
|
||||
case null => result = true
|
||||
case _ => resultMsg = s"The transaction(${t.txid}) is duplicated with txid"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch{
|
||||
case e : RuntimeException => throw e
|
||||
}
|
||||
|
||||
CheckedTransactionResult(result, resultMsg)
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ import rep.storage._
|
||||
import java.security.cert.{ Certificate}
|
||||
import rep.network.PeerHelper
|
||||
import rep.utils.SerializeUtils
|
||||
import scala.util.control.Breaks
|
||||
|
||||
|
||||
/**
|
||||
@ -45,9 +46,13 @@ object BlockHelper {
|
||||
* @return
|
||||
*/
|
||||
def endorseBlock(blkHash:Array[Byte], alise:String):Endorsement ={
|
||||
val (priK, pubK, cert) = ECDSASign.getKeyPair(alise)
|
||||
Endorsement(ByteString.copyFromUtf8(ECDSASign.getBitcoinAddrByCert(cert)),
|
||||
try{
|
||||
val (priK, pubK, cert) = ECDSASign.getKeyPair(alise)
|
||||
Endorsement(ByteString.copyFromUtf8(ECDSASign.getBitcoinAddrByCert(cert)),
|
||||
ByteString.copyFrom(ECDSASign.sign(priK, blkHash)))
|
||||
}catch{
|
||||
case e:RuntimeException => throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,16 +62,21 @@ object BlockHelper {
|
||||
*/
|
||||
def checkBlockContent(endor:Endorsement, blkHash: Array[Byte]): Boolean = {
|
||||
//获取出块人的背书信息
|
||||
val certTx = ECDSASign.getCertByBitcoinAddr(endor.endorser.toStringUtf8)
|
||||
if(certTx.getOrElse(None)!=None){
|
||||
// val certTx = SerializeUtils.deserialise(endor.endorser.toByteArray).asInstanceOf[Certificate]
|
||||
val alias = ECDSASign.getAliasByCert(certTx.get).getOrElse(None)
|
||||
if (alias == None) false
|
||||
else {
|
||||
ECDSASign.verify(endor.signature.toByteArray, blkHash, certTx.get.getPublicKey)
|
||||
}
|
||||
try{
|
||||
val certTx = ECDSASign.getCertByBitcoinAddr(endor.endorser.toStringUtf8)
|
||||
if(certTx.getOrElse(None)!=None){
|
||||
// val certTx = SerializeUtils.deserialise(endor.endorser.toByteArray).asInstanceOf[Certificate]
|
||||
val alias = ECDSASign.getAliasByCert(certTx.get).getOrElse(None)
|
||||
if (alias == None) false
|
||||
else {
|
||||
ECDSASign.verify(endor.signature.toByteArray, blkHash, certTx.get.getPublicKey)
|
||||
}
|
||||
}
|
||||
else false
|
||||
}catch{
|
||||
case e : RuntimeException => false
|
||||
}
|
||||
else false
|
||||
|
||||
}
|
||||
|
||||
//用于对交易对签名验证
|
||||
@ -76,33 +86,19 @@ object BlockHelper {
|
||||
val sig = t.signature.toByteArray
|
||||
val tOutSig1 = t.withSignature(ByteString.EMPTY)
|
||||
val tOutSig = tOutSig1.withMetadata(ByteString.EMPTY)
|
||||
val certTx = ECDSASign.getCertByBitcoinAddr(t.cert.toStringUtf8)
|
||||
certTx.getOrElse(None) match {
|
||||
case None =>
|
||||
|
||||
try{
|
||||
val cid = ChaincodeID.fromAscii(t.chaincodeID.toStringUtf8).name
|
||||
val certKey = IdxPrefix.WorldStateKeyPreFix + cid + "_" + "CERT_" + t.cert.toStringUtf8 // 普通用户证书的key
|
||||
val cert = Option(dataAccess.Get(certKey)) // 从worldstate中取证书,用户注册是以前缀形式写进去的
|
||||
cert.getOrElse(None) match {
|
||||
case None => resultMsg = s"The transaction(${t.txid}) is not trusted"
|
||||
case _ =>
|
||||
if (new String(cert.get) == "null") {
|
||||
//throw new RuntimeException("该用户证书已注销")
|
||||
resultMsg = "该用户证书已注销"
|
||||
}
|
||||
//验证签名和内容hash
|
||||
val kvcert = SerializeUtils.deserialise(cert.get).asInstanceOf[Certificate] //rep序列化与反序列化字节数组
|
||||
result = ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), kvcert.getPublicKey)
|
||||
var cert = ECDSASign.getCertWithCheck(t.cert.toStringUtf8,certKey,dataAccess.getSystemName)
|
||||
if(cert != None){
|
||||
result = ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), cert.get.getPublicKey)
|
||||
}else{
|
||||
resultMsg = s"The transaction(${t.txid}) is not trusted"
|
||||
}
|
||||
case _ =>
|
||||
val alias = ECDSASign.getAliasByCert(certTx.get).getOrElse(None)
|
||||
alias match {
|
||||
case None => resultMsg = s"The transaction(${t.txid}) is not trusted"
|
||||
case _ =>
|
||||
//验证签名和内容hash
|
||||
result = ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), certTx.get.getPublicKey)
|
||||
}
|
||||
}
|
||||
//CheckedTransactionResult(result, resultMsg)
|
||||
}catch{
|
||||
case e : RuntimeException => resultMsg = s"The transaction(${t.txid}) is not trusted${e.getMessage}"
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
@ -170,4 +166,70 @@ object BlockHelper {
|
||||
Sha256.hashstr(blk.toByteArray)
|
||||
}
|
||||
|
||||
def isEndorserListSorted(srclist : Array[Endorsement]):Int={
|
||||
var b : Int = 0
|
||||
if (srclist == null || srclist.length < 2){
|
||||
b
|
||||
}else{
|
||||
if(srclist(0).endorser.toStringUtf8() < srclist(1).endorser.toStringUtf8() ){//升序
|
||||
b = 1
|
||||
}else{//降序
|
||||
b = -1
|
||||
}
|
||||
|
||||
val loopbreak = new Breaks
|
||||
loopbreak.breakable(
|
||||
for (i <- 1 to srclist.length-1){
|
||||
if(b == 1 && srclist(i).endorser.toStringUtf8() < srclist(i-1).endorser.toStringUtf8()){
|
||||
b = 0
|
||||
loopbreak.break
|
||||
}
|
||||
|
||||
if(b == -1 && srclist(i).endorser.toStringUtf8() > srclist(i-1).endorser.toStringUtf8()){
|
||||
b = 0
|
||||
loopbreak.break
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
b
|
||||
}
|
||||
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
var eas = new Array[Endorsement](4)
|
||||
var e1 = new Endorsement()
|
||||
e1 = e1.withEndorser(ByteString.copyFromUtf8("sdfsdfseqqooqoq"))
|
||||
e1 = e1.withSignature(ByteString.copyFromUtf8("sdfsdfseqqooqoq"))
|
||||
var e2 = new Endorsement()
|
||||
e2 = e2.withEndorser(ByteString.copyFromUtf8("hkg"))
|
||||
e2 = e2.withSignature(ByteString.copyFromUtf8("hkg"))
|
||||
var e3 = new Endorsement()
|
||||
e3 = e3.withEndorser(ByteString.copyFromUtf8("wre"))
|
||||
e3 = e3.withSignature(ByteString.copyFromUtf8("wre"))
|
||||
var e4 = new Endorsement()
|
||||
e4 = e4.withEndorser(ByteString.copyFromUtf8("yiu"))
|
||||
e4 = e4.withSignature(ByteString.copyFromUtf8("yiu"))
|
||||
|
||||
eas(0) = e4
|
||||
eas(1) = e1
|
||||
eas(2) = e2
|
||||
eas(3) = e3
|
||||
|
||||
if(isEndorserListSorted(eas) == -1 || isEndorserListSorted(eas) == 0){
|
||||
println("not sorted")
|
||||
}else{
|
||||
println("sorted")
|
||||
}
|
||||
|
||||
var tmpeas = eas.sortWith((endorser_left,endorser_right)=> endorser_left.endorser.toStringUtf8() < endorser_right.endorser.toStringUtf8())
|
||||
|
||||
if(isEndorserListSorted(tmpeas) == -1 || isEndorserListSorted(tmpeas) == 0){
|
||||
println("not sorted")
|
||||
}else{
|
||||
println("sorted")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -410,6 +410,10 @@ class BlockModule(moduleName: String) extends ModuleBase(moduleName) {
|
||||
if(blc.previousBlockHash.toStringUtf8() != pe.getCurrentBlockHash){
|
||||
resetVoteEnv
|
||||
}else{
|
||||
//调整确认块中的共识数据的顺序
|
||||
var consensus = blc.consensusMetadata.toArray[Endorsement]
|
||||
var tmpconsensus = consensus.sortWith((endorser_left,endorser_right)=> endorser_left.endorser.toStringUtf8() < endorser_right.endorser.toStringUtf8())
|
||||
blc = blc.withConsensusMetadata(tmpconsensus)
|
||||
//广播这个block
|
||||
logMsg(LOG_TYPE.INFO, s"new block,nodename=${pe.getSysTag},transaction size=${blc.transactions.size},identifier=${this.blkidentifier_str},${blkidentifier},current height=${dataaccess.getBlockChainInfo().height},previoushash=${blc.previousBlockHash.toStringUtf8()}")
|
||||
mediator ! Publish(Topic.Block, new ConfirmedBlock(blc, dataaccess.getBlockChainInfo().height + 1,
|
||||
@ -431,7 +435,7 @@ class BlockModule(moduleName: String) extends ModuleBase(moduleName) {
|
||||
//TODO kami 这是一个非常耗时的工作?后续需要完善
|
||||
if (!BlockHelper.checkBlockContent(endorse, Sha256.hash(blkOutEndorse.toByteArray))) isEndorsed = false
|
||||
}
|
||||
if (isEndorsed) {
|
||||
if (isEndorsed && BlockHelper.isEndorserListSorted(endors.toArray[Endorsement])==1) {
|
||||
logTime("New block, start to store", CRFD_STEP._13_NEW_BLK_START_STORE,
|
||||
getActorRef(ActorType.STATISTIC_COLLECTION))
|
||||
//c4w 广播接收到block事件
|
||||
@ -452,9 +456,8 @@ class BlockModule(moduleName: String) extends ModuleBase(moduleName) {
|
||||
logMsg(LOG_TYPE.INFO, "New block, store opt over ...")
|
||||
logTime("New block, store opt over", CRFD_STEP._14_NEW_BLK_STORE_END,
|
||||
getActorRef(ActorType.STATISTIC_COLLECTION))
|
||||
|
||||
}
|
||||
else logMsg(LOG_TYPE.WARN, s"The block endorsement info is wrong. Sender : ${sender()}")
|
||||
else logMsg(LOG_TYPE.WARN, s"The block endorsement info is wrong or endorser sort error. Sender : ${sender()}")
|
||||
}
|
||||
else logMsg(LOG_TYPE.WARN, s"The num of endorsement in block is not enough. Sender : ${sender()}")
|
||||
|
||||
|
@ -73,7 +73,29 @@ class EndorsementModule(moduleName: String) extends ModuleBase(moduleName) {
|
||||
)
|
||||
r
|
||||
}
|
||||
|
||||
private def hasRepeatOfTrans(trans:Seq[Transaction]):Boolean={
|
||||
var isRepeat : Boolean = false
|
||||
val aliaslist = trans.distinct
|
||||
if(aliaslist.size != trans.size){
|
||||
isRepeat = true
|
||||
}else{
|
||||
val sr: ImpDataAccess = ImpDataAccess.GetDataAccess(pe.getSysTag)
|
||||
val loopbreak = new Breaks
|
||||
loopbreak.breakable(
|
||||
trans.foreach(f=>{
|
||||
if(sr.getBlockByTxId(f.txid) != null){
|
||||
isRepeat = true
|
||||
loopbreak.break
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
isRepeat
|
||||
}
|
||||
|
||||
|
||||
|
||||
private def endorseForWork(blk:Block, actRef: ActorRef,blkidentifier:String)={
|
||||
val dbinstancename = "endorse_"+blk.transactions.head.txid
|
||||
val preload: ImpDataPreload = ImpDataPreloadMgr.GetImpDataPreload(pe.getSysTag,dbinstancename)
|
||||
@ -81,21 +103,30 @@ class EndorsementModule(moduleName: String) extends ModuleBase(moduleName) {
|
||||
val blkData = blk.withConsensusMetadata(Seq())
|
||||
val blkInfo = Sha256.hash(blkData.toByteArray)
|
||||
if (BlockHelper.checkBlockContent(blk.consensusMetadata.head, blkInfo)) {
|
||||
if(verifyTransSign(blk.transactions)){
|
||||
if(preload.VerifyForEndorsement(blk)){
|
||||
logMsg(LOG_TYPE.WARN, s"Block endorse success,current height=${pe.getCacheHeight()},identifier=${blkidentifier}")
|
||||
actRef ! EndorsedBlock(true, blkData, BlockHelper.endorseBlock(blkInfo, pe.getSysTag),blkidentifier)
|
||||
//广播发送背书信息的事件(背书成功)
|
||||
sendEvent(EventType.PUBLISH_INFO, mediator, selfAddr, Topic.Block, Event.Action.ENDORSEMENT)
|
||||
}else{
|
||||
logMsg(LOG_TYPE.WARN, "Transcation preload failed,Block endorse failed")
|
||||
actRef! EndorsedBlock(false, blkData, BlockHelper.endorseBlock(blkInfo, pe.getSysTag),blkidentifier)
|
||||
}
|
||||
if(!hasRepeatOfTrans(blk.transactions)){
|
||||
if(verifyTransSign(blk.transactions)){
|
||||
if(preload.VerifyForEndorsement(blk)){
|
||||
logMsg(LOG_TYPE.WARN, s"Block endorse success,current height=${pe.getCacheHeight()},identifier=${blkidentifier}")
|
||||
actRef ! EndorsedBlock(true, blkData, BlockHelper.endorseBlock(blkInfo, pe.getSysTag),blkidentifier)
|
||||
//广播发送背书信息的事件(背书成功)
|
||||
sendEvent(EventType.PUBLISH_INFO, mediator, selfAddr, Topic.Block, Event.Action.ENDORSEMENT)
|
||||
}else{
|
||||
logMsg(LOG_TYPE.WARN, "Transcation preload failed,Block endorse failed")
|
||||
actRef! EndorsedBlock(false, blkData, BlockHelper.endorseBlock(blkInfo, pe.getSysTag),blkidentifier)
|
||||
}
|
||||
}else{
|
||||
logMsg(LOG_TYPE.WARN, "Transcation Certification vertified failed")
|
||||
actRef! EndorsedBlock(false, blkData, BlockHelper.endorseBlock(blkInfo, pe.getSysTag),blkidentifier)
|
||||
}
|
||||
}else{
|
||||
logMsg(LOG_TYPE.WARN, "Transcation Certification vertified failed")
|
||||
logMsg(LOG_TYPE.WARN, "Transcation vertified failed,found same Transcation")
|
||||
actRef! EndorsedBlock(false, blkData, BlockHelper.endorseBlock(blkInfo, pe.getSysTag),blkidentifier)
|
||||
}
|
||||
}
|
||||
else logMsg(LOG_TYPE.WARN, "Blocker Certification vertified failed")
|
||||
else {
|
||||
logMsg(LOG_TYPE.WARN, "Blocker Certification vertified failed")
|
||||
actRef! EndorsedBlock(false, blkData, BlockHelper.endorseBlock(blkInfo, pe.getSysTag),blkidentifier)
|
||||
}
|
||||
logTime("Endorse end", CRFD_STEP._9_ENDORSE_END, getActorRef(ActorType.STATISTIC_COLLECTION))
|
||||
logMsg(LOG_TYPE.WARN, s"Block endorse finish,current height=${pe.getCacheHeight()},identifier=${blkidentifier}")
|
||||
} catch {
|
||||
|
@ -17,6 +17,7 @@ package rep.network.consensus.vote
|
||||
|
||||
import rep.crypto.Sha256
|
||||
import scala.collection.mutable
|
||||
import rep.storage.util.pathUtil
|
||||
|
||||
/**
|
||||
* 系统默认
|
||||
@ -28,23 +29,50 @@ import scala.collection.mutable
|
||||
*/
|
||||
//TODO kami 应该在init的时候载入一个实现函数或者类。然后调用方法。写的更通用一些
|
||||
trait CRFDVoter extends VoterBase {
|
||||
|
||||
override def blocker(nodes: Set[String], position:Int): Option[String] = {
|
||||
//if (nodes.nonEmpty&&position<nodes.size) Option(nodes.head) else None
|
||||
case class randomNumber(var number:Long,var generateSerial:Int,var sortPos:Int)
|
||||
|
||||
override def blocker(nodes: Array[String], position:Int): String = {
|
||||
if(nodes.nonEmpty){
|
||||
var pos = position
|
||||
if(position >= nodes.size){
|
||||
pos = position % nodes.size
|
||||
}
|
||||
val a = nodes.toList
|
||||
Option(a(pos))
|
||||
nodes(pos)
|
||||
}else{
|
||||
None
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override def candidators(nodes: Set[String], seed: Array[Byte]): Set[String] = {
|
||||
var nodesSeq = nodes.toSeq.sortBy(f=>(f.toString()))//nodes.toSeq
|
||||
|
||||
private def getRandomList(seed:Long,candidatorLen:Int,candidatorTotal:Int):Array[randomNumber]={
|
||||
val m = 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
|
||||
val a = 2045
|
||||
val b = 1
|
||||
var randomArray = new Array[randomNumber](candidatorTotal)
|
||||
var hashSeed = seed.abs
|
||||
for(i<-0 to candidatorTotal-1){
|
||||
var tmpSeed = (a * hashSeed + b) % m
|
||||
tmpSeed = tmpSeed.abs
|
||||
if(tmpSeed == hashSeed) tmpSeed = tmpSeed + 1
|
||||
hashSeed = tmpSeed
|
||||
var randomobj = new randomNumber(hashSeed,i,-1)
|
||||
randomArray(i) = randomobj
|
||||
}
|
||||
|
||||
randomArray = randomArray.sortWith(
|
||||
(randomNumber_left,randomNumber_right)=> randomNumber_left.number < randomNumber_right.number)
|
||||
|
||||
for(i<-0 to randomArray.size-1){
|
||||
randomArray(i).sortPos = i
|
||||
}
|
||||
|
||||
randomArray = randomArray.sortWith(
|
||||
(randomNumber_left,randomNumber_right)=> randomNumber_left.generateSerial < randomNumber_right.generateSerial)
|
||||
|
||||
randomArray
|
||||
}
|
||||
|
||||
override def candidators(nodes: Set[String], seed: Array[Byte]): Array[String] = {
|
||||
var nodesSeq = nodes.toSeq.sortBy(f=>(f.toString()))
|
||||
var len = nodes.size / 2 + 1
|
||||
val min_len = 4
|
||||
len = if(len<min_len){
|
||||
@ -53,27 +81,21 @@ trait CRFDVoter extends VoterBase {
|
||||
}
|
||||
else len
|
||||
if(len<4){
|
||||
Set.empty
|
||||
null
|
||||
}
|
||||
else{
|
||||
var candidate = mutable.Seq.empty[String]
|
||||
var index = 0
|
||||
var hashSeed = seed
|
||||
|
||||
while (candidate.size < len) {
|
||||
if (index >= hashSeed.size) {
|
||||
hashSeed = Sha256.hash(hashSeed)
|
||||
index = 0
|
||||
}
|
||||
//应该按位来计算
|
||||
if ((hashSeed(index) & 1) == 1) {
|
||||
candidate = (candidate :+ nodesSeq(index % (nodesSeq.size)))
|
||||
nodesSeq = (nodesSeq.toSet - nodesSeq(index % (nodesSeq.size))).toSeq
|
||||
}
|
||||
index += 1
|
||||
var candidate = new Array[String](len)
|
||||
var hashSeed:Long = pathUtil.bytesToInt(seed)
|
||||
var randomList = getRandomList(hashSeed,len,nodes.size)
|
||||
//PrintRandomArray(randomList)
|
||||
println(randomList(0).sortPos)
|
||||
for(j<-0 to len-1){
|
||||
var e = randomList(j)
|
||||
candidate(j) = nodesSeq(e.sortPos)
|
||||
}
|
||||
candidate.toSet
|
||||
candidate
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ class CRFDVoterModule(moduleName: String) extends ModuleBase(moduleName) with CR
|
||||
|
||||
def rnd = ThreadLocalRandom.current
|
||||
|
||||
var candidatorCur = Set.empty[ String ]
|
||||
var candidatorCur : Array[ String ] = null
|
||||
|
||||
var isWaiting = false
|
||||
|
||||
@ -167,15 +167,15 @@ class CRFDVoterModule(moduleName: String) extends ModuleBase(moduleName) with CR
|
||||
val seed = pe.getVoteBlockHash//pe.getCurrentBlockHash
|
||||
|
||||
candidatorCur = candidators(SystemCertList.getSystemCertList, Sha256.hash(seed))
|
||||
if (!candidatorCur.isEmpty) {
|
||||
if (candidatorCur != null) {
|
||||
pe.resetCandidator(candidatorCur)
|
||||
if(pe.getCacheHeight() >= 1){
|
||||
val blo = blocker(candidatorCur, pe.getBlker_index)
|
||||
if (blo != None) {
|
||||
pe.resetBlocker(blo.get)
|
||||
if (blo != null) {
|
||||
pe.resetBlocker(blo)
|
||||
//暂时只找到该方法能够明确标识一个在网络中(有网络地址)的节点,后续发现好方法可以完善
|
||||
logMsg(LOG_TYPE.INFO, s"Select in getCacheHeight=${pe.getCacheHeight()} Candidates : ${candidatorCur} ~ Blocker : ${blo},currenthash=${pe.getCurrentBlockHash},index=${pe.getBlker_index}")
|
||||
if (pe.getSysTag == blo.get.toString()) {
|
||||
if (pe.getSysTag == blo) {
|
||||
getActorRef(ActorType.BLOCK_MODULE) ! (BlockEvent.CREATE_BLOCK, "")
|
||||
logMsg(LOG_TYPE.INFO, s"Select in getCacheHeight=${pe.getCacheHeight()} Candidates : ${candidatorCur} ,send Create cmd~ Blocker : ${blo},currenthash=${pe.getCurrentBlockHash},index=${pe.getBlker_index}")
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ trait VoterBase {
|
||||
* @return
|
||||
*/
|
||||
//def blocker[T](nodes:Set[T], position:Int):Option[T]
|
||||
def blocker(nodes:Set[String], position:Int):Option[String]
|
||||
def blocker(nodes:Array[String], position:Int):String
|
||||
|
||||
/**
|
||||
* 获取候选人节点
|
||||
@ -45,5 +45,5 @@ trait VoterBase {
|
||||
* @return
|
||||
*/
|
||||
//def candidators[T](nodes:Set[T], seed:Array[Byte]):Set[T]
|
||||
def candidators(nodes:Set[String], seed:Array[Byte]):Set[String]
|
||||
def candidators(nodes:Set[String], seed:Array[Byte]):Array[String]
|
||||
}
|
||||
|
@ -259,8 +259,8 @@ class PeerExtensionImpl extends Extension {
|
||||
candidatorLock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
def resetCandidator(nds: Set[ String ]): Unit = {
|
||||
|
||||
def resetCandidator(nds: Array[ String ]): Unit = {
|
||||
candidatorLock.lock()
|
||||
try{
|
||||
candidator = immutable.TreeMap.empty[String,String]
|
||||
|
@ -100,7 +100,7 @@ abstract class Sandbox(cid:String) extends Actor with RepLogging{
|
||||
sender ! tr
|
||||
//交易预处理请求,指定接收者
|
||||
case PreTransaction(t:Transaction) =>
|
||||
val tr = doTransaction(t,null,null)
|
||||
val tr = doTransaction(t,null,t.txid)
|
||||
shim.rollback()
|
||||
sender ! tr
|
||||
//恢复chainCode,不回消息
|
||||
|
@ -213,12 +213,15 @@ class Shim(system: ActorSystem, cid: String) {
|
||||
val sig = tx.signature.toByteArray
|
||||
val tOutSig1 = tx.withSignature(ByteString.EMPTY)
|
||||
val tOutSig = tOutSig1.withMetadata(ByteString.EMPTY)
|
||||
val peercer = ECDSASign.getCertByBitcoinAddr(bitcoinaddr)
|
||||
if (peercer == None)
|
||||
throw new Exception(NOT_PERR_CERT)
|
||||
ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), peercer.get.getPublicKey) match {
|
||||
case true =>
|
||||
case false => throw new Exception("节点签名验证错误")
|
||||
|
||||
try{
|
||||
val peercer = ECDSASign.getCertByBitcoinAddr(bitcoinaddr)
|
||||
ECDSASign.verify(sig, PeerHelper.getTxHash(tOutSig), peercer.get.getPublicKey) match {
|
||||
case true =>
|
||||
case false => throw new Exception("节点签名验证错误")
|
||||
}
|
||||
}catch{
|
||||
case e : RuntimeException => throw e
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,9 +28,10 @@ import org.json4s._
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import rep.crypto.Sha256
|
||||
|
||||
import rep.app.conf.SystemProfile
|
||||
import scala.reflect.runtime.currentMirror
|
||||
import scala.tools.reflect.ToolBox
|
||||
import scala.util.matching.Regex
|
||||
import rep.storage.util.pathUtil
|
||||
|
||||
/**
|
||||
* 动态编译工具类的伴生对象,提供静态方法
|
||||
@ -38,7 +39,13 @@ import scala.util.matching.Regex
|
||||
*/
|
||||
object Compiler{
|
||||
//建立动态编译工具类实例
|
||||
val cp = new Compiler(None, true)
|
||||
val contractOperationMode = SystemProfile.getContractOperationMode
|
||||
var isDebug = true
|
||||
contractOperationMode match{
|
||||
case 0 => isDebug = true
|
||||
case 1 => isDebug = false
|
||||
}
|
||||
val cp = new Compiler(None, isDebug)
|
||||
/** 根据传入的合约代码,以及指定的合约类唯一标识,生成合约类,并动态编译
|
||||
* @param pcode 合约代码主体部分
|
||||
* @cid 合约类唯一标识
|
||||
@ -61,7 +68,7 @@ class Compiler(targetDir: Option[File], bDebug:Boolean) {
|
||||
//反射工具对象
|
||||
val tb = currentMirror.mkToolBox()
|
||||
//源文件路径
|
||||
val path_source = if(bDebug) getSourcePath else null
|
||||
val path_source = if(bDebug) getSourcePath else pathUtil.getPath("custom_contract")
|
||||
//目标文件路径
|
||||
val target = targetDir match {
|
||||
case Some(dir) => AbstractFile.getDirectory(dir)
|
||||
|
@ -156,13 +156,13 @@ public class StoreConfig {
|
||||
|
||||
public long getFreeDiskSpace(){
|
||||
String bpath = this.getBlockPath();
|
||||
/*try {
|
||||
try {
|
||||
if(pathUtil.FileExists(bpath) == -1){
|
||||
pathUtil.MkdirAll(bpath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
}
|
||||
File f = new File(bpath);
|
||||
long l = f.getFreeSpace();
|
||||
return l;
|
||||
|
207
src/main/scala/rep/storage/test/testRandomVote.scala
Normal file
207
src/main/scala/rep/storage/test/testRandomVote.scala
Normal file
@ -0,0 +1,207 @@
|
||||
package rep.storage.test
|
||||
|
||||
import scala.collection.mutable
|
||||
import rep.crypto.Sha256
|
||||
import rep.storage.util.pathUtil
|
||||
|
||||
object testRandomVote {
|
||||
case class randomstatis(listsize:Int,clist:scala.collection.mutable.ArrayBuffer[String])
|
||||
case class randomNumber(var number:Long,var generateSerial:Int,var sortPos:Int)
|
||||
|
||||
var statisvar:randomstatis = null
|
||||
var statis:Array[Int] = null
|
||||
|
||||
|
||||
def getRandomList(seed:Long,candidatorLen:Int,candidatorTotal:Int):Array[randomNumber]={
|
||||
val m = 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
|
||||
val a = 2045
|
||||
val b = 1
|
||||
var randomArray = new Array[randomNumber](candidatorTotal)
|
||||
var hashSeed = seed.abs
|
||||
for(i<-0 to candidatorTotal-1){
|
||||
var tmpSeed = (a * hashSeed + b) % m
|
||||
tmpSeed = tmpSeed.abs
|
||||
if(tmpSeed == hashSeed) tmpSeed = tmpSeed + 1
|
||||
hashSeed = tmpSeed
|
||||
var randomobj = new randomNumber(hashSeed,i,-1)
|
||||
randomArray(i) = randomobj
|
||||
}
|
||||
|
||||
randomArray = randomArray.sortWith(
|
||||
(randomNumber_left,randomNumber_right)=> randomNumber_left.number < randomNumber_right.number)
|
||||
|
||||
for(i<-0 to randomArray.size-1){
|
||||
randomArray(i).sortPos = i
|
||||
}
|
||||
|
||||
randomArray = randomArray.sortWith(
|
||||
(randomNumber_left,randomNumber_right)=> randomNumber_left.generateSerial < randomNumber_right.generateSerial)
|
||||
|
||||
randomArray
|
||||
}
|
||||
|
||||
def PrintRandomArray(ra : Array[randomNumber])={
|
||||
if(ra == null) println("no data,input is null")
|
||||
if(ra.size == 0) println("no data, input length is zero")
|
||||
for(i<-0 to (ra.length-1)){
|
||||
println("randomnumber="+ra(i).number+",generateSerial="+ra(i).generateSerial+",sortpos="+ra(i).sortPos+"|||")
|
||||
}
|
||||
}
|
||||
|
||||
def getRandomString(length:Int):String={
|
||||
val str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
var random=new util.Random()
|
||||
var sb=new StringBuffer()
|
||||
for( i<-0 to length-1){
|
||||
val number= random.nextInt(62)
|
||||
sb.append(str.charAt(number))
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
|
||||
def getRandomSha256String(length:Int): Array[Byte]={
|
||||
val s = getRandomString(length)
|
||||
//println(Sha256.hashstr(s))
|
||||
Sha256.hashToBytes(s)
|
||||
}
|
||||
|
||||
def findIndex(indexs:Array[Int],idx:Int):Boolean={
|
||||
var b = false
|
||||
for( i<-0 to indexs.length-1){
|
||||
if(indexs(i) == idx){
|
||||
b = true
|
||||
}
|
||||
}
|
||||
b
|
||||
}
|
||||
|
||||
def candidators(nodes: Set[String], seed: Array[Byte]): Array[String] = {
|
||||
var nodesSeq = nodes.toSeq.sortBy(f=>(Integer.parseInt(f.toString())))
|
||||
var len = nodes.size / 2 + 1
|
||||
val min_len = 4
|
||||
len = if(len<min_len){
|
||||
if(nodes.size < min_len) nodes.size
|
||||
else min_len
|
||||
}
|
||||
else len
|
||||
if(len<4){
|
||||
null
|
||||
}
|
||||
else{
|
||||
//var candidate = mutable.Seq.empty[String]
|
||||
var candidate = new Array[String](len)
|
||||
var hashSeed:Long = pathUtil.bytesToInt(seed)
|
||||
var randomList = getRandomList(hashSeed,len,nodes.size)
|
||||
//PrintRandomArray(randomList)
|
||||
println(randomList(0).sortPos)
|
||||
for(j<-0 to len-1){
|
||||
var e = randomList(j)
|
||||
//candidate = (candidate :+ nodesSeq(e.sortPos))
|
||||
candidate(j) = nodesSeq(e.sortPos)
|
||||
|
||||
}
|
||||
//candidate.toSet
|
||||
candidate
|
||||
}
|
||||
}
|
||||
|
||||
def blocker(nodes: Array[String], position:Int): String = {
|
||||
if(nodes.nonEmpty){
|
||||
var pos = position
|
||||
if(position >= nodes.size){
|
||||
pos = position % nodes.size
|
||||
}
|
||||
val a = nodes.toList
|
||||
nodes(pos)
|
||||
}else{
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
def getStableNodes(length:Int) :Set[String] = {
|
||||
var source = Set.empty[String]
|
||||
for(i <- 0 to length-1){
|
||||
source += i.toString()
|
||||
}
|
||||
|
||||
source
|
||||
}
|
||||
|
||||
|
||||
|
||||
def checkblker(nodecount:Int,pos:Int)={
|
||||
val c = getStableNodes(nodecount)
|
||||
val hashbytes = getRandomSha256String(500)
|
||||
val cs = candidators(c, hashbytes)
|
||||
|
||||
val blo = blocker(cs, pos)
|
||||
//statisvar.clist += blo.toString()
|
||||
//println(cs.toString()+"\t"+blo.toString())
|
||||
val idx = Integer.parseInt(blo)
|
||||
statis(idx) = statis(idx) + 1
|
||||
//println(blo.toString())
|
||||
}
|
||||
|
||||
def testRandomBlocker(count:Int,nodes:Int,pos:Int){
|
||||
//statisvar = new randomstatis(count,new scala.collection.mutable.ArrayBuffer[String](count))
|
||||
statis = new Array[Int](nodes)
|
||||
for(i<-0 to count-1){
|
||||
checkblker(nodes,pos)
|
||||
}
|
||||
//println(statisvar.clist.toString())
|
||||
for(j<-0 to statis.length-1) print(","+"blocker="+j+"("+statis(j).toString()+")")
|
||||
}
|
||||
|
||||
def printRandom(size:Int){
|
||||
for(j<-0 to 1000){
|
||||
val istr = getRandomSha256String(500)
|
||||
var i = pathUtil.bytesToInt(istr)
|
||||
if(i < 0){
|
||||
i = i.abs
|
||||
}
|
||||
println("\t"+i % size)
|
||||
}
|
||||
}
|
||||
|
||||
def testPrintRandomArray(len:Int,size:Int){
|
||||
for(j<-0 to 1000){
|
||||
val istr = getRandomSha256String(500)
|
||||
var seed = pathUtil.bytesToInt(istr)
|
||||
var ra = getRandomList(seed,len,size)
|
||||
PrintRandomArray(ra)
|
||||
println("-------------------")
|
||||
}
|
||||
}
|
||||
|
||||
def printRandomlist(size:Int){
|
||||
val m = 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2//43112609
|
||||
val a = 2045//12477 // a = 4p + 1 3119
|
||||
val b = 1//4667 // b = 2q + 1 2333
|
||||
var tmpstatis = new Array[Int](size)
|
||||
val istr = getRandomSha256String(500)
|
||||
var l = pathUtil.bytesToInt(istr)
|
||||
if(l < 0){
|
||||
l = l.abs
|
||||
}
|
||||
|
||||
for(i<-0 to 1000){
|
||||
l = a*l+b
|
||||
if(l < 0) l = l.abs
|
||||
tmpstatis(l % size) = tmpstatis(l % size) +1
|
||||
println("\t"+l % size)
|
||||
}
|
||||
|
||||
for(j<-0 to tmpstatis.length-1)
|
||||
print(","+tmpstatis(j))
|
||||
}
|
||||
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
//println(pathUtil.IsPrime(2333))
|
||||
testRandomBlocker(100000,5,0)
|
||||
//printRandom(4)
|
||||
//printRandomlist(30)
|
||||
//testPrintRandomArray(16,30)
|
||||
}
|
||||
}
|
||||
|
@ -256,9 +256,21 @@ def testTreeMapclear{
|
||||
|
||||
println(tm)
|
||||
}
|
||||
|
||||
|
||||
case class myobject(txid:String,name:String)
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
//testTreeMap
|
||||
testTreeMapclear
|
||||
//testTreeMapclear
|
||||
var as = new Array[myobject](5)
|
||||
as(0) = new myobject("1","name1")
|
||||
as(1) = new myobject("2","name2")
|
||||
as(2) = new myobject("3","name3")
|
||||
as(3) = new myobject("2","name2")
|
||||
as(4) = new myobject("5","name5")
|
||||
|
||||
val tmp = as.distinct
|
||||
println("tmpsize="+tmp.length+",assize="+as.length)
|
||||
|
||||
}
|
||||
}
|
@ -119,4 +119,40 @@ public class pathUtil {
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
public static int bytesToInt(byte[] inputs){
|
||||
if(inputs == null) return 0;
|
||||
if(inputs.length < 4) return 0;
|
||||
return (inputs[0] & 0xff) << 24
|
||||
| (inputs[1] & 0xff) << 16
|
||||
| (inputs[2] & 0xff) << 8
|
||||
| (inputs[3] & 0xff) << 0 ;
|
||||
}
|
||||
|
||||
public static boolean IsPrime(int n){
|
||||
if (n <= 3) {
|
||||
return n > 1;
|
||||
}
|
||||
|
||||
for(int i=2;i<=Math.sqrt(n);i++){
|
||||
if(n%i == 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String getPath(String spath) {
|
||||
String p = spath;
|
||||
try {
|
||||
File f = new File(spath);
|
||||
if(!f.exists()){
|
||||
MkdirAll(f.getAbsolutePath());
|
||||
}
|
||||
p = f.getAbsolutePath();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ object SerializeUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Json对象反序列化,由于没有给出造型类型,无法胜任复杂对象
|
||||
* Json对象反序列化
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
|
@ -116,7 +116,7 @@ class SandboxSpec(_system: ActorSystem)
|
||||
val dbTag = "1"
|
||||
//加载合约脚本
|
||||
// val s1 = scala.io.Source.fromFile("src/main/scala/ContractAssetsTPL.scala")
|
||||
val s1 = scala.io.Source.fromFile("src/main/scala/rep/sc/tpl/NewContract.scala")
|
||||
val s1 = scala.io.Source.fromFile("src/main/scala/NewContract.scala")
|
||||
val l1 = try s1.mkString finally s1.close()
|
||||
|
||||
//val clazz = Compiler.compilef(l1,null)
|
||||
@ -197,4 +197,90 @@ class SandboxSpec(_system: ActorSystem)
|
||||
re3 should be("transfer ok")
|
||||
}
|
||||
}
|
||||
|
||||
//JavaScript的合约实现,同一个合约串行执行测试
|
||||
"sandbox" should "process trasactions Synchronously" in {
|
||||
val sysName = "1"
|
||||
//建立PeerManager实例是为了调用transactionCreator(需要用到密钥签名),无他
|
||||
|
||||
val f1 =
|
||||
"""
|
||||
var Thread = Java.type("java.lang.Thread");
|
||||
function waitprint(span,output) {
|
||||
Thread.sleep(span);
|
||||
print(output);
|
||||
return output
|
||||
}
|
||||
"""
|
||||
val s1 =
|
||||
"""
|
||||
waitprint(5000,"FirstPrint");
|
||||
"""
|
||||
val s2 =
|
||||
"""
|
||||
waitprint(5,"SecondPrint");
|
||||
"""
|
||||
|
||||
val probe = TestProbe()
|
||||
val db = ImpDataAccess.GetDataAccess(sysName)
|
||||
var sandbox = system.actorOf(TransProcessor.props("sandbox", "", probe.ref))
|
||||
//deploy
|
||||
val t1 = transactionCreator(sysName, rep.protos.peer.Transaction.Type.CHAINCODE_DEPLOY,
|
||||
"", "", List(), f1, None)
|
||||
val msg_send1 = new DoTransaction(t1, probe.ref, "")
|
||||
probe.send(sandbox, msg_send1)
|
||||
val msg_recv1 = probe.expectMsgType[Sandbox.DoTransactionResult](10000.seconds)
|
||||
|
||||
//invoke
|
||||
val cname = t1.payload.get.chaincodeID.get.name
|
||||
val t2 = transactionCreator(sysName, rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE,
|
||||
"", s1, List(), "", Option(cname))
|
||||
val msg_send2 = new DoTransaction(t2, probe.ref, "")
|
||||
probe.send(sandbox, msg_send2)
|
||||
val msg_recv2 = probe.expectMsgType[Sandbox.DoTransactionResult](10000.seconds)
|
||||
val rv2 = msg_recv2.r.asInstanceOf[JValue]
|
||||
val re2 = rv2.extract[String]
|
||||
re2 should be("FirstPrint")
|
||||
|
||||
val t3 = transactionCreator(sysName, rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE,
|
||||
"", s2, List(), "", Option(cname))
|
||||
val msg_send3 = new DoTransaction(t3, probe.ref, "")
|
||||
probe.send(sandbox, msg_send3)
|
||||
val msg_recv3 = probe.expectMsgType[Sandbox.DoTransactionResult](10000.seconds)
|
||||
val rv3 = msg_recv3.r.asInstanceOf[JValue]
|
||||
rv3.extract[String] should be("SecondPrint")
|
||||
}
|
||||
|
||||
//在合约脚本中访问正在处理的签名交易测试
|
||||
"sandbox scripts" should "can access the Trasaction being processed" in {
|
||||
val sysName = "1"
|
||||
val f1 =
|
||||
"""
|
||||
print(tx);
|
||||
"""
|
||||
val s1 =
|
||||
"""
|
||||
r=tx;
|
||||
"""
|
||||
val probe = TestProbe()
|
||||
val db = ImpDataAccess.GetDataAccess(sysName)
|
||||
var sandbox = system.actorOf(TransProcessor.props("sandbox", "", probe.ref))
|
||||
//deploy
|
||||
val t1 = transactionCreator(sysName, rep.protos.peer.Transaction.Type.CHAINCODE_DEPLOY,
|
||||
"", "", List(), f1, None)
|
||||
val msg_send1 = new DoTransaction(t1, probe.ref, "")
|
||||
probe.send(sandbox, msg_send1)
|
||||
val msg_recv1 = probe.expectMsgType[Sandbox.DoTransactionResult](10000.seconds)
|
||||
//invoke
|
||||
val cname = t1.payload.get.chaincodeID.get.name
|
||||
val t2 = transactionCreator(sysName, rep.protos.peer.Transaction.Type.CHAINCODE_INVOKE,
|
||||
"", s1, List(), "", Option(cname))
|
||||
val msg_send2 = new DoTransaction(t2, probe.ref, "")
|
||||
probe.send(sandbox, msg_send2)
|
||||
val msg_recv2 = probe.expectMsgType[Sandbox.DoTransactionResult](10000.seconds)
|
||||
val rv2 = msg_recv2.r.asInstanceOf[JValue]
|
||||
val re2 = rv2.extract[Transaction]
|
||||
re2.txid should be(t2.txid)
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user