mirror of
https://gitee.com/BTAJL/repchain.git
synced 2024-12-03 04:08:40 +08:00
去除交易检查的缓存机制,根据sandbox存储快照判断
This commit is contained in:
parent
e8ea049ce1
commit
fb2d091f18
@ -37,6 +37,9 @@ import rep.crypto.BytesHex
|
||||
import rep.network.tools.PeerExtension
|
||||
import rep.storage.IdxPrefix.WorldStateKeyPreFix
|
||||
import rep.sc.scalax.ActionResult
|
||||
import rep.storage._
|
||||
import rep.utils.SerializeUtils.deserialise
|
||||
import rep.utils.SerializeUtils.serialise
|
||||
|
||||
/** 合约容器的抽象类伴生对象,定义了交易执行结果的case类
|
||||
*
|
||||
@ -84,24 +87,7 @@ object Sandbox {
|
||||
def getTXCId(t: Transaction): String = {
|
||||
val t_cid = t.cid.get
|
||||
getChaincodeId(t_cid)
|
||||
}
|
||||
|
||||
val coderMap = collection.mutable.Map[String, String]()
|
||||
val stateMap = collection.mutable.Map[String, Boolean]()
|
||||
|
||||
def getContractCoder(cName:String)= {
|
||||
coderMap.get(cName)
|
||||
}
|
||||
def setContractCoder(cName:String, coder:String) = synchronized{
|
||||
coderMap += (cName -> coder)
|
||||
}
|
||||
def getContractState(cid:String)={
|
||||
stateMap.get(cid)
|
||||
}
|
||||
def setContractState(cid:String, state:Boolean) = synchronized{
|
||||
stateMap += (cid-> state)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** 合约容器的抽象类,提供与底层进行API交互的shim实例,用于与存储交互的实例pe
|
||||
@ -139,18 +125,34 @@ abstract class Sandbox(cid:ChaincodeId) extends Actor {
|
||||
def receive = {
|
||||
//交易处理请求
|
||||
case DoTransaction(t:Transaction,from:ActorRef, da:String) =>
|
||||
val tr = doTransaction(t,from,da)
|
||||
val tr = onTransaction(t,from,da)
|
||||
sender ! tr
|
||||
//交易预处理请求,指定接收者
|
||||
case PreTransaction(t:Transaction) =>
|
||||
val tr = doTransaction(t,null,t.id)
|
||||
shim.rollback()
|
||||
val tr = onTransaction(t,null,t.id)
|
||||
sender ! tr
|
||||
//恢复chainCode,不回消息
|
||||
case DeployTransaction(t:Transaction,from:ActorRef, da:String) =>
|
||||
val tr = doTransaction(t,from,da,true)
|
||||
shim.rollback()
|
||||
val tr = onTransaction(t,from,da,true)
|
||||
}
|
||||
|
||||
def onTransaction(t:Transaction,from:ActorRef, da:String, bRestore:Boolean=false):DoTransactionResult = {
|
||||
try{
|
||||
//要么上一份给result,重新建一份
|
||||
shim.sr = ImpDataPreloadMgr.GetImpDataPreload(sTag, da)
|
||||
checkTransaction(t, bRestore)
|
||||
shim.mb = scala.collection.mutable.Map[String,Array[Byte]]()
|
||||
shim.ol = new scala.collection.mutable.ListBuffer[Oper]
|
||||
doTransaction(t,from,da,bRestore)
|
||||
}catch{
|
||||
case e:Exception =>
|
||||
log.error(t.id, e)
|
||||
new DoTransactionResult(t,null, null, null,null,null,
|
||||
Option(akka.actor.Status.Failure(e)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 交易处理抽象方法,接受待处理交易,返回处理结果
|
||||
* @param t 待处理交易
|
||||
* @param from 发出交易请求的actor
|
||||
@ -158,5 +160,63 @@ abstract class Sandbox(cid:ChaincodeId) extends Actor {
|
||||
* @return 交易执行结果
|
||||
*/
|
||||
def doTransaction(t:Transaction,from:ActorRef, da:String, bRestore:Boolean=false):DoTransactionResult
|
||||
|
||||
|
||||
def checkTransaction(t: Transaction, bRestore:Boolean=false) = {
|
||||
val tx_cid = getTXCId(t)
|
||||
val sr = shim.sr
|
||||
t.`type` match {
|
||||
case Transaction.Type.CHAINCODE_INVOKE =>
|
||||
//cid不存在或状态为禁用抛出异常
|
||||
val key_tx_state = WorldStateKeyPreFix+ tx_cid + PRE_STATE
|
||||
val state_bytes = sr.Get(key_tx_state)
|
||||
//合约不存在
|
||||
if(state_bytes == null){
|
||||
throw new SandboxException(ERR_INVOKE_CHAINCODE_NOT_EXIST)
|
||||
}
|
||||
else{
|
||||
val state = deserialise(state_bytes).asInstanceOf[Boolean]
|
||||
if(!state){
|
||||
throw new SandboxException(ERR_DISABLE_CID)
|
||||
}
|
||||
}
|
||||
case Transaction.Type.CHAINCODE_DEPLOY =>
|
||||
//检查合约名+版本是否已存在,API预执行导致sandbox实例化,紧接着共识预执行
|
||||
val key_tx_state = WorldStateKeyPreFix+ tx_cid + PRE_STATE
|
||||
val state_bytes = sr.Get(key_tx_state)
|
||||
//合约已存在且并非恢复合约
|
||||
if(state_bytes != null && !bRestore){
|
||||
throw new SandboxException(ERR_REPEATED_CID)
|
||||
}
|
||||
//检查合约部署者
|
||||
val cn = t.cid.get.chaincodeName
|
||||
val key_coder = WorldStateKeyPreFix+ cn
|
||||
val coder_bytes = sr.Get(key_coder)
|
||||
if(coder_bytes != null){
|
||||
val coder = Some(deserialise(coder_bytes).asInstanceOf[String])
|
||||
//合约已存在且部署者并非当前交易签名者
|
||||
if(!t.signature.get.certId.get.creditCode.equals(coder.get))
|
||||
throw new SandboxException(ERR_CODER)
|
||||
}
|
||||
|
||||
case Transaction.Type.CHAINCODE_SET_STATE =>
|
||||
val cn = t.cid.get.chaincodeName
|
||||
val key_coder = WorldStateKeyPreFix+ cn
|
||||
val coder_bytes = sr.Get(key_coder)
|
||||
if(coder_bytes != null){
|
||||
val coder = Some(deserialise(coder_bytes).asInstanceOf[String])
|
||||
//合约已存在且部署者并非当前交易签名者
|
||||
println(s"cn:${key_coder} :: ${t.signature.get.certId.get.creditCode} :: ${coder.get}")
|
||||
if(!t.signature.get.certId.get.creditCode.equals(coder.get)){
|
||||
throw new SandboxException(ERR_CODER)
|
||||
}
|
||||
}
|
||||
//cid不存在抛出异常
|
||||
val key_tx_state = WorldStateKeyPreFix+ tx_cid + PRE_STATE
|
||||
val state_bytes = sr.Get(key_tx_state)
|
||||
//合约不存在
|
||||
if(state_bytes == null){
|
||||
throw new SandboxException(ERR_INVOKE_CHAINCODE_NOT_EXIST)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -39,7 +39,7 @@ import rep.sc.js.SandboxJS
|
||||
import rep.sc.scalax.SandboxScala
|
||||
import rep.utils.SerializeUtils.deserialise
|
||||
import rep.utils.SerializeUtils.serialise
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/** 伴生对象,预定义了交易处理的异常描述,传入消息的case类,以及静态方法
|
||||
* @author c4w
|
||||
@ -102,6 +102,7 @@ object TransProcessor {
|
||||
class TransProcessor(name: String, da:String, parent: ActorRef) extends Actor {
|
||||
import TransProcessor._
|
||||
|
||||
protected def log = LoggerFactory.getLogger(this.getClass)
|
||||
//获得所属于的actor system
|
||||
val pe = PeerExtension(context.system)
|
||||
val sTag = pe.getSysTag
|
||||
@ -120,7 +121,7 @@ class TransProcessor(name: String, da:String, parent: ActorRef) extends Actor {
|
||||
sb_actor ! ti
|
||||
}catch{
|
||||
case e:Exception =>
|
||||
e.printStackTrace()
|
||||
log.error(ti.t.id, e)
|
||||
val r = new DoTransactionResult(ti.t,null, null, null,null,null,
|
||||
Option(akka.actor.Status.Failure(e)))
|
||||
//向请求发送方返回包含执行异常的结果
|
||||
@ -175,7 +176,7 @@ class TransProcessor(name: String, da:String, parent: ActorRef) extends Actor {
|
||||
val cid = t.cid.get
|
||||
//检查交易是否有效,无效抛出异常
|
||||
//deploy之后紧接着调用同合约的invoke,会导致检查失败
|
||||
checkTransaction(t)
|
||||
//checkTransaction(t)
|
||||
|
||||
val sn = PRE_SUB_ACTOR+tx_cid
|
||||
//如果已经有对应的actor实例,复用之,否则建实例,actor name加字母前缀
|
||||
@ -206,102 +207,5 @@ class TransProcessor(name: String, da:String, parent: ActorRef) extends Actor {
|
||||
}
|
||||
}
|
||||
|
||||
def checkTransaction(t: Transaction) = {
|
||||
val tx_cid = getTXCId(t)
|
||||
t.`type` match {
|
||||
case Transaction.Type.CHAINCODE_INVOKE =>
|
||||
//cid不存在或状态为禁用抛出异常
|
||||
val state = Sandbox.getContractState(tx_cid)
|
||||
if(state != None ){
|
||||
if (!state.get)
|
||||
throw new SandboxException(ERR_DISABLE_CID)
|
||||
}else{
|
||||
val key_tx_state = WorldStateKeyPreFix+ tx_cid + PRE_STATE
|
||||
val sr = ImpDataAccess.GetDataAccess(sTag)
|
||||
val state_bytes = sr.Get(key_tx_state)
|
||||
//合约不存在
|
||||
if(state_bytes == null){
|
||||
//进一步检查sn对应actor,判断是否存在合约正在deploying
|
||||
val sn = PRE_SUB_ACTOR+tx_cid
|
||||
val cref = context.child(sn)
|
||||
if(cref == None)
|
||||
throw new SandboxException(ERR_INVOKE_CHAINCODE_NOT_EXIST)
|
||||
}
|
||||
else{
|
||||
val state = deserialise(state_bytes).asInstanceOf[Boolean]
|
||||
Sandbox.setContractState(tx_cid, state)
|
||||
if(!state){
|
||||
throw new SandboxException(ERR_DISABLE_CID)
|
||||
}
|
||||
}
|
||||
}
|
||||
case Transaction.Type.CHAINCODE_DEPLOY =>
|
||||
//检查合约名+版本是否已存在,API预执行导致sandbox实例化,紧接着共识预执行
|
||||
if(Sandbox.getContractState(tx_cid)!=None){
|
||||
throw new SandboxException(ERR_REPEATED_CID)
|
||||
}
|
||||
else{
|
||||
val key_tx_state = WorldStateKeyPreFix+ tx_cid + PRE_STATE
|
||||
val sr = ImpDataAccess.GetDataAccess(sTag)
|
||||
val state_bytes = sr.Get(key_tx_state)
|
||||
//合约已存在
|
||||
if(state_bytes != null){
|
||||
val state = deserialise(state_bytes).asInstanceOf[Boolean]
|
||||
Sandbox.setContractState(tx_cid, state)
|
||||
throw new SandboxException(ERR_DISABLE_CID)
|
||||
}
|
||||
}
|
||||
//检查合约部署者
|
||||
val cn = t.cid.get.chaincodeName
|
||||
var coder = Sandbox.getContractCoder(cn)
|
||||
if(coder == None){
|
||||
val key_coder = WorldStateKeyPreFix+ cn
|
||||
val sr = ImpDataAccess.GetDataAccess(sTag)
|
||||
val coder_bytes = sr.Get(key_coder)
|
||||
if(coder_bytes != null){
|
||||
coder = Some(deserialise(coder_bytes).asInstanceOf[String])
|
||||
Sandbox.setContractCoder(cn, coder.get)
|
||||
}
|
||||
}
|
||||
//合约已存在且部署者并非当前交易签名者
|
||||
if(coder!=None && !t.signature.get.certId.get.creditCode.equals(coder.get))
|
||||
throw new SandboxException(ERR_CODER)
|
||||
|
||||
case Transaction.Type.CHAINCODE_SET_STATE =>
|
||||
val cn = t.cid.get.chaincodeName
|
||||
var coder = Sandbox.getContractCoder(cn)
|
||||
if(coder == None){
|
||||
val key_coder = WorldStateKeyPreFix+ cn
|
||||
val sr = ImpDataAccess.GetDataAccess(sTag)
|
||||
val coder_bytes = sr.Get(key_coder)
|
||||
if(coder_bytes != null){
|
||||
coder = Some(deserialise(coder_bytes).asInstanceOf[String])
|
||||
Sandbox.setContractCoder(cn, coder.get)
|
||||
}
|
||||
}
|
||||
//合约已存在且部署者并非当前交易签名者
|
||||
if(coder!=None && !t.signature.get.certId.get.creditCode.equals(coder.get)){
|
||||
println(s"coder:${coder} signer:${t.signature.get.certId.get.creditCode}")
|
||||
throw new SandboxException(ERR_CODER)
|
||||
}
|
||||
//cid不存在抛出异常
|
||||
if(Sandbox.getContractState(tx_cid)==None){
|
||||
val key_tx_state = WorldStateKeyPreFix+ tx_cid + PRE_STATE
|
||||
val sr = ImpDataAccess.GetDataAccess(sTag)
|
||||
val state_bytes = sr.Get(key_tx_state)
|
||||
//合约不存在
|
||||
if(state_bytes == null){
|
||||
//进一步检查sn对应actor,判断是否存在合约正在deploying
|
||||
val sn = PRE_SUB_ACTOR+tx_cid
|
||||
val cref = context.child(sn)
|
||||
if(cref == None)
|
||||
throw new SandboxException(ERR_INVOKE_CHAINCODE_NOT_EXIST)
|
||||
}
|
||||
else{
|
||||
val state = deserialise(state_bytes).asInstanceOf[Boolean]
|
||||
Sandbox.setContractState(tx_cid, state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -41,10 +41,6 @@ class SandboxScala(cid:ChaincodeId) extends Sandbox(cid){
|
||||
|
||||
def doTransaction(t:Transaction,from:ActorRef, da:String, bRestore:Boolean):DoTransactionResult ={
|
||||
//上下文可获得交易
|
||||
//要么上一份给result,重新建一份
|
||||
shim.sr = ImpDataPreloadMgr.GetImpDataPreload(sTag, da)
|
||||
shim.mb = scala.collection.mutable.Map[String,Array[Byte]]()
|
||||
shim.ol = scala.collection.mutable.ListBuffer.empty[Oper]
|
||||
//构造和传入ctx
|
||||
val ctx = new ContractContext(shim,t)
|
||||
//如果执行中出现异常,返回异常
|
||||
|
Loading…
Reference in New Issue
Block a user