长安链源码分析之交易过程分析(2)
作者:李
- 2022-10-25 湖南
本文字数:2186 字
阅读完需:约 7 分钟
本文已参与「开源摘星计划」,欢迎正在阅读的你加入。活动链接:https://github.com/weopenprojects/WeOpen-Star
处理合约查询请求,整个逻辑非常清晰
这里面有些细节,比如合约虚拟机到底怎么执行的,有待研究
//处理查询合约
func (s *ApiService) dealQuery(tx *commonPb.Transaction, source protocol.TxSource) *commonPb.TxResponse {
var (
err error
errMsg string
errCode commonErr.ErrCode
store protocol.BlockchainStore
vmMgr protocol.VmManager
resp = &commonPb.TxResponse{TxId: tx.Payload.TxId}
)
//获取链id
chainId := tx.Payload.ChainId
//获取存储模块
if store, err = s.chainMakerServer.GetStore(chainId); err != nil {
errCode = commonErr.ERR_CODE_GET_STORE
errMsg = s.getErrMsg(errCode, err)
s.log.Error(errMsg)
resp.Code = commonPb.TxStatusCode_INTERNAL_ERROR
resp.Message = errMsg
resp.TxId = tx.Payload.TxId
return resp
}
//获取虚拟机管理模块
if vmMgr, err = s.chainMakerServer.GetVmManager(chainId); err != nil {
errCode = commonErr.ERR_CODE_GET_VM_MGR
errMsg = s.getErrMsg(errCode, err)
s.log.Error(errMsg)
resp.Code = commonPb.TxStatusCode_INTERNAL_ERROR
resp.Message = errMsg
resp.TxId = tx.Payload.TxId
return resp
}
//如果是系统内部链,调用系统链查询
if chainId == SYSTEM_CHAIN {
return s.dealSystemChainQuery(tx, vmMgr)
}
//获取快照日志模块
var log = logger.GetLoggerByChain(logger.MODULE_SNAPSHOT, chainId)
//基于存储模块和日志模块创建一个快照模块
var snap protocol.Snapshot
snap, err = snapshot.NewQuerySnapshot(store, log)
if err != nil {
s.log.Error(err)
resp.Code = commonPb.TxStatusCode_INTERNAL_ERROR
resp.Message = err.Error()
resp.TxId = tx.Payload.TxId
return resp
}
//创建一个交易上下文
ctx := vm.NewTxSimContext(vmMgr, snap, tx, protocol.DefaultBlockVersion, log)
//根据合约名称获取合约
contract, err := store.GetContractByName(tx.Payload.ContractName)
if err != nil {
s.log.Error(err)
resp.Code = commonPb.TxStatusCode_INTERNAL_ERROR
resp.Message = err.Error()
resp.TxId = tx.Payload.TxId
return resp
}
//判断合约类型,如果合约运行时不是本地运行时
var bytecode []byte
if contract.RuntimeType != commonPb.RuntimeType_NATIVE {
//获取合约的字节信息
bytecode, err = store.GetContractBytecode(contract.Name)
if err != nil {
s.log.Error(err)
resp.Code = commonPb.TxStatusCode_INTERNAL_ERROR
resp.Message = err.Error()
resp.TxId = tx.Payload.TxId
return resp
}
}
//虚拟机管理器运行合约
txResult, _, txStatusCode := vmMgr.RunContract(contract, tx.Payload.Method,
bytecode, s.kvPair2Map(tx.Payload.Parameters), ctx, 0, tx.Payload.TxType)
s.log.DebugDynamic(func() string {
contractJson, _ := json.Marshal(contract)
return fmt.Sprintf("vmMgr.RunContract: txStatusCode:%d, resultCode:%d, contractName[%s](%s), "+
"method[%s], txType[%s], message[%s],result len: %d",
txStatusCode, txResult.Code, tx.Payload.ContractName, string(contractJson), tx.Payload.Method,
tx.Payload.TxType, txResult.Message, len(txResult.Result))
})
//如果监控已经打开,发送监控信息
if localconf.ChainMakerConfig.MonitorConfig.Enabled {
if txStatusCode == commonPb.TxStatusCode_SUCCESS && txResult.Code != 1 {
s.metricQueryCounter.WithLabelValues(chainId, "true").Inc()
} else {
s.metricQueryCounter.WithLabelValues(chainId, "false").Inc()
}
}
//执行合约失败
if txStatusCode != commonPb.TxStatusCode_SUCCESS {
errMsg = fmt.Sprintf("txStatusCode:%d, resultCode:%d, contractName[%s] method[%s] txType[%s], %s",
txStatusCode, txResult.Code, tx.Payload.ContractName, tx.Payload.Method, tx.Payload.TxType, txResult.Message)
s.log.Warn(errMsg)
resp.Code = txStatusCode
if txResult.Message == archive.ErrArchivedBlock.Error() {
resp.Code = commonPb.TxStatusCode_ARCHIVED_BLOCK
} else if txResult.Message == archive.ErrArchivedTx.Error() {
resp.Code = commonPb.TxStatusCode_ARCHIVED_TX
}
resp.Message = errMsg
resp.ContractResult = txResult
resp.TxId = tx.Payload.TxId
return resp
}
//执行合约超时
if txResult.Code == 1 {
resp.Code = commonPb.TxStatusCode_CONTRACT_FAIL
resp.Message = commonPb.TxStatusCode_CONTRACT_FAIL.String()
resp.ContractResult = txResult
resp.TxId = tx.Payload.TxId
return resp
}
//执行合约成功
resp.Code = commonPb.TxStatusCode_SUCCESS
resp.Message = commonPb.TxStatusCode_SUCCESS.String()
resp.ContractResult = txResult
resp.TxId = tx.Payload.TxId
return resp
}
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 4
李
关注
还未添加个人签名 2018-05-04 加入
还未添加个人简介
评论