I am following a tutorial for hyperledger-fabric, below is the link.
http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html.
When I executed byfn.sh as per instructed by the link, it fails when trying to query the value after the invoke to transfer 10 value from a to b is executed. The query result is still 100 and not 90 despite the Success Response : 200 and no error returned from the ChainCode.
I've also proven this by going to CLI container and executed the command step-by-step.
I wonder if any of you faced this issue and moreover if there's any guidance how to debug this (e.g. how to see the chain in the blockchain, what log to check if the value fails to be updated but the response is success, etc.).
Thanks in advance
[Edit]: From the instruction (http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html), it is mentioned that we need to run (also part of byfn.sh)
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
to transfer the value from 'a' to 'b', and afterwards when we invoke a query to peers, the value of a should change to 90 from originally 100.
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
The chaincode installed to each peer can be found here: https://github.com/hyperledger/fabric-samples/blob/release/chaincode/chaincode_example02/chaincode_example02.go
Copy-paste the code that invokes to update the value
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A, B string // Entities
var Aval, Bval int // Asset holdings
var X int // Transaction value
var err error
if len(args) != 3 {
return shim.Error("Incorrect number of arguments. Expecting 3")
}
A = args[0]
B = args[1]
// Get the state from the ledger
// TODO: will be nice to have a GetAllState call to ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
return shim.Error("Failed to get state")
}
if Avalbytes == nil {
return shim.Error("Entity not found")
}
Aval, _ = strconv.Atoi(string(Avalbytes))
Bvalbytes, err := stub.GetState(B)
if err != nil {
return shim.Error("Failed to get state")
}
if Bvalbytes == nil {
return shim.Error("Entity not found")
}
Bval, _ = strconv.Atoi(string(Bvalbytes))
// Perform the execution
X, err = strconv.Atoi(args[2])
if err != nil {
return shim.Error("Invalid transaction amount, expecting a integer value")
}
Aval = Aval - X
Bval = Bval + X
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state back to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
I am pretty confused how it can fail to update the value and if someone can give me a hint how to debug the blockchain or fabric, that will be great.
Related
I am seeing this when querying data from implicit private data collection.
Please see code snippet below.
When I query individual key (using QueryBidPrivate/GetPrivateData), I get corresponding data.
But if I query the complete collection (using GetPrivateDataByRange(collection, "", "")), I get nothing from the Iterator.
peer chaincode query -C mychannel -n govtcontract -c '{"function":"QueryBidPrivate","Args":["100", "1035"]}'
{"bidamt":100,"biddate":"2022-05-04","contractid":"1035","salt":"4567ab4567","vendorid":"100"}
peer chaincode query -C mychannel -n govtcontract -c '{"function":"ListAllBids","Args":[]}'
No output
Is there anything I am missing here ?
// ListAllBids returns all Bids details from private state
func (s *SmartContract) ListAllBids(ctx contractapi.TransactionContextInterface) ([]VendorBid, error) {
// Get client org id and verify it matches peer org id.
// In this scenario, client is only authorized to read/write private data from its own peer.
clientOrgID, err := getClientOrgID(ctx, true)
if err != nil {
return nil, fmt.Errorf("failed to get verified OrgID: %s", err.Error())
}
collection := "_implicit_org_" + clientOrgID
BidIterator, err := ctx.GetStub().GetPrivateDataByRange(collection, "", "")
if err != nil {
logger.Infof("ListAllBids error: %s", err.Error())
return nil, fmt.Errorf("failed to read bid list : %s", err.Error())
}
if BidIterator == nil {
logger.Infof("ListAllBids : null iterator ")
return nil, fmt.Errorf("bid private details does not exist ")
}
defer BidIterator.Close()
logger.Infof("ListAllBids in govtcontract: no error")
var allbids []VendorBid
myMSPID, err := ctx.GetClientIdentity().GetMSPID()
logger.Infof("myMSPID: %s", myMSPID)
for BidIterator.HasNext() {
logger.Infof("Iterator has element: ")
entrybid, err := BidIterator.Next()
if err != nil {
return nil, err
}
var bidvar VendorBid
err = json.Unmarshal(entrybid.Value, &bidvar)
if err != nil {
return nil, err
}
allbids = append(allbids, bidvar)
logger.Infof("Iterator element: %s", entrybid.Value)
}
return allbids, nil
}
=========================================
// QueryBidPrivate returns the Bid details from owner's private data collection
func (s *SmartContract) QueryBidPrivate(ctx contractapi.TransactionContextInterface, vendorId string, contractId string) (string, error) {
// Get client org id and verify it matches peer org id.
// In this scenario, client is only authorized to read/write private data from its own peer.
clientOrgID, err := getClientOrgID(ctx, true)
if err != nil {
return "", fmt.Errorf("failed to get verified OrgID: %s", err.Error())
}
collection := "_implicit_org_" + clientOrgID
bidconkey, err := ctx.GetStub().CreateCompositeKey(vendorId, []string{contractId})
bidDetails, err := ctx.GetStub().GetPrivateData(collection, bidconkey)
if err != nil {
return "", fmt.Errorf("failed to read bid private properties from client org's collection: %s", err.Error())
}
if bidDetails == nil {
return "", fmt.Errorf("bid private details does not exist in client org's collection: %s", contractId)
}
return string(bidDetails), nil
}
GetPrivateDataByPartialCompositeKey() is the function for querying a range of private data that was stored using a composite key. GetPrivateDataByRange() won't retrieve the data stored with a composite key. I think in the above code snippet you have to replace the function call GetPrivateDataByRange(collection, "", "") with GetPrivateDataByPartialCompositeKey(collection, vendorId, []string{})
Sample usage can be found here.
I faced the same error in the smart contract. The issue here is because of storing data on the composite key.
Instead of below code :
for BidIterator.HasNext() {
logger.Infof("Iterator has element: ")
entrybid, err := BidIterator.Next()
if err != nil {
return nil, err
}
var bidvar VendorBid
err = json.Unmarshal(entrybid.Value, &bidvar)
if err != nil {
return nil, err
}
allbids = append(allbids, bidvar)
logger.Infof("Iterator element: %s", entrybid.Value)
}
Use the below function
func constructQueryResponseFromIterator(resultsIterator shim.StateQueryIteratorInterface)
(*bytes.Buffer, error)
{
// buffer is a JSON array containing QueryResults
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
queryResponse, err := resultsIterator.Next()
if err != nil {
return nil, err
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{")
//buffer.WriteString("{\"Key\":")
//buffer.WriteString("\"")
//buffer.WriteString(queryResponse.Key)
//buffer.WriteString("\"")
buffer.WriteString(", \"Record\":")
// Record is a JSON object, so we write as-is
buffer.WriteString(string(queryResponse.Value))
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")
return &buffer, nil
}
I'm using hyperledger fabric 1.4 to writing the chaincode named task.go.In the task.go, there is a function I wrote called transferBalance, which implements the transfer between two accounts.
func (t* TaskChaincode) transferBalance(stub shim.ChaincodeStubInterface,args[] string) pb.Response {
if len(args) != 3{
return shim.Error("Wrong number of given parameters")
}
source := args[0]
target := args[1]
amount,err := strconv.Atoi(args[2])
if err != nil{
return shim.Error("Format conversion failed")
}
if amount <= 0{
return shim.Error("The number of designated transfer tokens must be greater than 0")
}
sacc,err := stub.GetState(source)
if err != nil {
return shim.Error("Failed to obtain account information according to the specified account")
}
if sacc == nil {
return shim.Error("The source account does not exist")
}
tacc,err := stub.GetState(target)
if err != nil {
return shim.Error("Failed to obtain account information according to the specified account")
}
if tacc== nil {
return shim.Error("The source account does not exist")
}
sval,err := strconv.Atoi(string(sacc))
if err != nil {
return shim.Error("An error occurred while processing the source account balance")
}
tval,err := strconv.Atoi(string(tacc))
if err != nil {
return shim.Error("An error occurred while processing the target account balance")
}
if sval < amount{
return shim.Error("Insufficient balance")
}
sval = sval - amount
tval = tval + amount
err = stub.PutState(source,[]byte(strconv.Itoa(sval)))
if err != nil {
return shim.Error("Failed to save the status of the source account after the transfer")
}
err = stub.PutState(target,[]byte(strconv.Itoa(tval)))
if err != nil {
return shim.Error("Failed to save the status of the target account after the transfer")
}
return shim.Success([]byte("Successful tr"))
}
And I successfully installed the chain code, and executed the following command to call the above function.
peer chaincode invoke -n taskcc -c '{"Args":["transferBalance","user1_account","user2_account","2"]}' -C myc
I'm getting an error shown below:
Error: endorsement failure during invoke. response: status:500 message:"\345\244\204\347\220\206\345\216\237\350\264\246\346\210\267\344\275\231\351\242\235\346\227\266\345\217\221\347\224\237\351\224\231\350\257\257"
I don't know how to solve this problem. And I want to know what the numbers in the above error mean.
How should I try to find the source of the error and solve it. Please help me, thank you very much.
I have written the chaincode its in local system, now i need to install chaincode in hyperledger fabric peers.How it is done from local system to install the chaincode to my peer node. below code is taken from hyperledger fabric chaincode example.please suggest me
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface)
pb.Response {
fmt.Println("ex02 Init")
_, args := stub.GetFunctionAndParameters()
var A, B string // Entities
var Aval, Bval int // Asset holdings
var err error
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// Initialize the chaincode
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
B = args[2]
Bval, err = strconv.Atoi(args[3])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
You can install the chaincode in several ways
NodeSDK
JavaSDK
CLI
I would suggest you try with CLI first, fabric-samples has one example.
Behind the seen fabric compile and only binary file will be deployed to the peer
I'm using block-listener to listen transactions in one channel to send notification in another. But i haven't clue how to decode data that print block-listener.go example.
Not 100% sure what do you mean by decoding the data is the following block of the [block-lister.go][1] takes care to print transactions for you:
for {
select {
case b := <-a.notfy:
fmt.Println("")
fmt.Println("")
fmt.Println("Received block")
fmt.Println("--------------")
txsFltr := util.TxValidationFlags(b.Block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
for i, r := range b.Block.Data.Data {
tx, _ := getTxPayload(r)
if tx != nil {
chdr, err := utils.UnmarshalChannelHeader(tx.Header.ChannelHeader)
if err != nil {
fmt.Print("Error extracting channel header\n")
return
}
if txsFltr.IsInvalid(i) {
fmt.Println("")
fmt.Println("")
fmt.Printf("Received invalid transaction from channel '%s'\n", chdr.ChannelId)
fmt.Println("--------------")
fmt.Printf("Transaction invalid: TxID: %s\n", chdr.TxId)
} else {
fmt.Printf("Received transaction from channel '%s': \n\t[%v]\n", chdr.ChannelId, tx)
if event, err := getChainCodeEvents(r); err == nil {
if len(chaincodeID) != 0 && event.ChaincodeId == chaincodeID {
fmt.Println("")
fmt.Println("")
fmt.Printf("Received chaincode event from channel '%s'\n", chdr.ChannelId)
fmt.Println("------------------------")
fmt.Printf("Chaincode Event:%+v\n", event)
}
}
}
}
}
}
}
if you would like you can also use following function to get block printed in JSON format:
protolator.DeepMarshalJSON(os.Stdout, t.Block)
Based on hyperledger SDK doc, we can use nodeJS SDK to query for the block and the transaction info. Is it possible to use this SDK to query the latest world state, e.g, query the value for a given key?
To being able to query for latest world state your chaincode has to provide this capability, namely you have to implement this logic and incorporate it into your chaincode. Then it will simply require to execute the chaincode to get the value for the key you are interested it.
For example you can do something similar to this:
package main
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)
// Person
type Asset struct {
ID string `json:"id"`
Name string `json:"name"`
Price string `json:"price"`
}
// assetManagement the chaincode interface implementation to manage
// the ledger of person records
type assetManagement struct {
}
func (p *assetManagement) Init(stub shim.ChaincodeStubInterface) peer.Response {
return shim.Success(nil)
}
func (p *assetManagement) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
actionName, params := stub.GetFunctionAndParameters()
if actionName == "addAsset" {
return p.addAsset(stub)
} else if actionName == "getAsset" {
return p.getAsset(stub)
}
return shim.Error("Unknown function name")
}
func (p *assetManagement) getAsset(stub shim.ChaincodeStubInterface) peer.Response {
_, params := stub.GetFunctionAndParameters()
assetID := params[0]
state, err := stub.GetState(assetID)
if err != nil {
return shim.Error(fmt.Sprintf("%s", err))
}
return shim.Success(state)
}
func (p *assetManagement) addAsset(stub shim.ChaincodeStubInterface) peer.Response {
// TODO add loggic adding new asset
}
func main() {
err := shim.Start(new(assetManagement))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
Next all you need is to invoke chaincode passing function name getAsset with asset ID and will get latest state for that asset. Here is the code based on Go SDK:
// Skipped initialization.
txRequest := apitxn.ChaincodeInvokeRequest{
Targets: []apitxn.ProposalProcessor{p},
Fcn: "getAsset",
Args: []string{"42"},
TransientMap: map[string][]byte{},
ChaincodeID: "assetChaincode",
}
proposalResponse, _, err := ch.SendTransactionProposal(txRequest)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%v\n", proposalResponse[0].ProposalResponse)
tx, err := ch.CreateTransaction(proposalResponse)
if err != nil {
fmt.Println(err)
return
}
txResponse, err := ch.SendTransaction(tx)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(txResponse[0])