Usage of Query System chaincode

2019-08-04 14:45发布

Hi I am trying to query a block by with these piece of code by importing ledger package which is part of QSCC but there are some errors when try to invoke please clarify whether this is correct way of doing it.

func (t *SimpleChaincode) expt(stub shim.ChaincodeStubInterface, args      []string) pb.Response{

var plp ledger.PeerLedgerProvider
var pl ledger.PeerLedger
lId,err:=plp.List()
if err != nil {
    return shim.Error("Invalid transaction amount, expecting a integer value")
}
fmt.Println(" List lists the ids of the existing ledgers")
fmt.Println(lId)

yesNO,err:=plp.Exists(lId[0])
if err != nil {
    return shim.Error("Invalid transaction amount, expecting a integer value")
}
fmt.Println(" tells whether the ledger with given id exists")
fmt.Println(yesNO)

txid:=args[0]
tx,err:=pl.GetTransactionByID(txid)
if err != nil {
    return shim.Error("Invalid transaction amount, expecting a integer value")
}
fmt.Println("transaction")
fmt.Println(tx)

return shim.Success(nil)
}

Errors is

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x40301b]
goroutine 7 [running]:
panic(0x9eb1a0, 0xc420016040)
/opt/go/src/runtime/panic.go:500 +0x1a1
 main.(*SimpleChaincode).expt(0xfaa000, 0xf71120, 0xc42016ae80, 0xc4202faad0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, ...)
/chaincode/input/src/github.com/example_cc/example_cc.go:191 +0x5b
main.(*SimpleChaincode).Invoke(0xfaa000, 0xf71120, 0xc42016ae80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/chaincode/input/src/github.com/example_cc/example_cc.go:98 +0x430
github.com/hyperledger/fabric/core/chaincode/shim.(*Handler).handleTransaction.func1(0xc4202389a0, 0xc4200119a0)
/opt/gopath/src/github.com/hyperledger/fabric/core/chaincode/shim/handler.go:317 +0x483
created by github.com/hyperledger/fabric/core/chaincode/shim.(*Handler).handleTransaction
/opt/gopath/src/github.com/hyperledger/fabric/core/chaincode/shim/handler.go:328 +0x49

1条回答
做个烂人
2楼-- · 2019-08-04 15:27

First of all to start with, you are not suppose to interact directly with a ledger structure from your chaincode, but rather to leverage existing APIs of ChaincodeStubInterface provided for Invoke and Init methods of chaincode.

Now, about the logic you are trying to achieve, one of the possible solutions would be to make use of CreateCompositeKey in the following way:

func (smartContract) Invoke(stub shim.ChaincodeStubInterface) peer.Response {

    funcName, params := stub.GetFunctionAndParameters()

    indexName := "txID~key"

    if funcName == "addNewKey" {

        key := params[0]
        value := params[1]

        keyTxIdKey, err := stub.CreateCompositeKey(indexName, []string{stub.GetTxID(), key})
        if err != nil {
            return shim.Error(err.Error())
        }

        creator, _ := stub.GetCreator()

        // Add key and value to the state
        stub.PutState(key, []byte(value))
        stub.PutState(keyTxIdKey, creator)

    } else if funcName == "checkTxID" {
        txID := params[0]

        it, _ := stub.GetStateByPartialCompositeKey(indexName, []string{txID})

        for it.HasNext() {
            keyTxIdRange, err := it.Next()
            if err != nil {
                return shim.Error(err.Error())
            }

            _, keyParts, _ := stub.SplitCompositeKey(keyTxIdRange.Key)
            key := keyParts[1]
            fmt.Printf("key affected by txID %s is %s\n", txID, key)
            txIDCreator := keyTxIdRange.Value

            sId := &msp.SerializedIdentity{}
            err := proto.Unmarshal(txIDCreator, sId)
            if err != nil {
                return shim.Error(fmt.Sprintf("Could not deserialize a SerializedIdentity, err %s", err))
            }

            bl, _ := pem.Decode(sId.IdBytes)
            if bl == nil {
                return shim.Error(fmt.Sprintf("Could not decode the PEM structure"))
            }
            cert, err := x509.ParseCertificate(bl.Bytes)
            if err != nil {
                return shim.Error(fmt.Sprintf("ParseCertificate failed %s", err))
            }

            fmt.Printf("Certificate of txID %s creator is %s", txID, cert)
        }
    }

    return shim.Success(nil)
}

Of course this is only an example and a lot of details missed, but the key idea is to leverage APIs available throughout the ChaincodeStubInterface rather than trying to access ledger directly from the chaincode by executing system chaincodes.

查看更多
登录 后发表回答