去除交易检查的缓存机制,根据sandbox存储快照判断

This commit is contained in:
c4w 2019-03-27 20:45:53 +08:00
parent e8ea049ce1
commit fb2d091f18
3 changed files with 89 additions and 129 deletions

View File

@ -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)
}
}
}
}

View File

@ -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)
}
}
}
}
}

View File

@ -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)
//如果执行中出现异常,返回异常