1 Star 1 Fork 0

陈文甲 / 学习Hyperledger Fabric 实战联盟链

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
query.go 6.73 KB
一键复制 编辑 原始数据 按行查看 历史
陈文甲 提交于 2023-02-06 10:51 . 把所有文件添加
/*
Copyright IBM Corp. 2017 All Rights Reserved.
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" BASIS,
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 qscc
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/peer"
"github.com/hyperledger/fabric/core/policy"
"github.com/hyperledger/fabric/msp/mgmt"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protos/utils"
)
// LedgerQuerier implements the ledger query functions, including:
// - GetChainInfo returns BlockchainInfo
// - GetBlockByNumber returns a block
// - GetBlockByHash returns a block
// - GetTransactionByID returns a transaction
type LedgerQuerier struct {
policyChecker policy.PolicyChecker
}
var qscclogger = flogging.MustGetLogger("qscc")
// These are function names from Invoke first parameter
const (
GetChainInfo string = "GetChainInfo"
GetBlockByNumber string = "GetBlockByNumber"
GetBlockByHash string = "GetBlockByHash"
GetTransactionByID string = "GetTransactionByID"
GetBlockByTxID string = "GetBlockByTxID"
)
// Init is called once per chain when the chain is created.
// This allows the chaincode to initialize any variables on the ledger prior
// to any transaction execution on the chain.
func (e *LedgerQuerier) Init(stub shim.ChaincodeStubInterface) pb.Response {
qscclogger.Info("Init QSCC")
// Init policy checker for access control
e.policyChecker = policy.NewPolicyChecker(
peer.NewChannelPolicyManagerGetter(),
mgmt.GetLocalMSP(),
mgmt.NewLocalMSPPrincipalGetter(),
)
return shim.Success(nil)
}
// Invoke is called with args[0] contains the query function name, args[1]
// contains the chain ID, which is temporary for now until it is part of stub.
// Each function requires additional parameters as described below:
// # GetChainInfo: Return a BlockchainInfo object marshalled in bytes
// # GetBlockByNumber: Return the block specified by block number in args[2]
// # GetBlockByHash: Return the block specified by block hash in args[2]
// # GetTransactionByID: Return the transaction specified by ID in args[2]
func (e *LedgerQuerier) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
args := stub.GetArgs()
if len(args) < 2 {
return shim.Error(fmt.Sprintf("Incorrect number of arguments, %d", len(args)))
}
fname := string(args[0])
cid := string(args[1])
if fname != GetChainInfo && len(args) < 3 {
return shim.Error(fmt.Sprintf("missing 3rd argument for %s", fname))
}
targetLedger := peer.GetLedger(cid)
if targetLedger == nil {
return shim.Error(fmt.Sprintf("Invalid chain ID, %s", cid))
}
qscclogger.Debugf("Invoke function: %s on chain: %s", fname, cid)
// Handle ACL:
// 1. get the signed proposal
sp, err := stub.GetSignedProposal()
if err != nil {
return shim.Error(fmt.Sprintf("Failed getting signed proposal from stub, %s: %s", cid, err))
}
// 2. check the channel reader policy
if err = e.policyChecker.CheckPolicy(cid, policies.ChannelApplicationReaders, sp); err != nil {
return shim.Error(fmt.Sprintf("Authorization request failed %s: %s", cid, err))
}
switch fname {
case GetTransactionByID:
return getTransactionByID(targetLedger, args[2])
case GetBlockByNumber:
return getBlockByNumber(targetLedger, args[2])
case GetBlockByHash:
return getBlockByHash(targetLedger, args[2])
case GetChainInfo:
return getChainInfo(targetLedger)
case GetBlockByTxID:
return getBlockByTxID(targetLedger, args[2])
}
return shim.Error(fmt.Sprintf("Requested function %s not found.", fname))
}
func getTransactionByID(vledger ledger.PeerLedger, tid []byte) pb.Response {
if tid == nil {
return shim.Error("Transaction ID must not be nil.")
}
processedTran, err := vledger.GetTransactionByID(string(tid))
if err != nil {
return shim.Error(fmt.Sprintf("Failed to get transaction with id %s, error %s", string(tid), err))
}
bytes, err := utils.Marshal(processedTran)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(bytes)
}
func getBlockByNumber(vledger ledger.PeerLedger, number []byte) pb.Response {
if number == nil {
return shim.Error("Block number must not be nil.")
}
bnum, err := strconv.ParseUint(string(number), 10, 64)
if err != nil {
return shim.Error(fmt.Sprintf("Failed to parse block number with error %s", err))
}
block, err := vledger.GetBlockByNumber(bnum)
if err != nil {
return shim.Error(fmt.Sprintf("Failed to get block number %d, error %s", bnum, err))
}
// TODO: consider trim block content before returning
// Specifically, trim transaction 'data' out of the transaction array Payloads
// This will preserve the transaction Payload header,
// and client can do GetTransactionByID() if they want the full transaction details
bytes, err := utils.Marshal(block)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(bytes)
}
func getBlockByHash(vledger ledger.PeerLedger, hash []byte) pb.Response {
if hash == nil {
return shim.Error("Block hash must not be nil.")
}
block, err := vledger.GetBlockByHash(hash)
if err != nil {
return shim.Error(fmt.Sprintf("Failed to get block hash %s, error %s", string(hash), err))
}
// TODO: consider trim block content before returning
// Specifically, trim transaction 'data' out of the transaction array Payloads
// This will preserve the transaction Payload header,
// and client can do GetTransactionByID() if they want the full transaction details
bytes, err := utils.Marshal(block)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(bytes)
}
func getChainInfo(vledger ledger.PeerLedger) pb.Response {
binfo, err := vledger.GetBlockchainInfo()
if err != nil {
return shim.Error(fmt.Sprintf("Failed to get block info with error %s", err))
}
bytes, err := utils.Marshal(binfo)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(bytes)
}
func getBlockByTxID(vledger ledger.PeerLedger, rawTxID []byte) pb.Response {
txID := string(rawTxID)
block, err := vledger.GetBlockByTxID(txID)
if err != nil {
return shim.Error(fmt.Sprintf("Failed to get block for txID %s, error %s", txID, err))
}
bytes, err := utils.Marshal(block)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(bytes)
}
1
https://gitee.com/venjia/coding-268.git
git@gitee.com:venjia/coding-268.git
venjia
coding-268
学习Hyperledger Fabric 实战联盟链
b3df94c7d330

搜索帮助