Hyperledger fabric: Querying implicit data collection - hyperledger-fabric

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
}

Related

List all Azure container registry images via Golang

I would like to list all images from Azure registry via Golang.
What I founded is this: https://github.com/Azure-Samples/azure-sdk-for-go-samples/tree/main/sdk/resourcemanager/containerregistry but nothing from there seems to help me.
Any ideas please?
LE:
I ended up with this code
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/runtime/2019-08-15-preview/containerregistry"
"github.com/Azure/go-autorest/autorest"
)
type ACRTokenProvider struct {
accessToken string
}
func (a *ACRTokenProvider) OAuthToken() string {
return a.accessToken
}
func newACRAuthorizer() (*autorest.BearerAuthorizer, error) {
tenantId := "TENANT_ID"
acrService := "servicename.azurecr.io"
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
panic(err)
}
ctx := context.Background()
aadToken, err := cred.GetToken(ctx, policy.TokenRequestOptions{Scopes: []string{"https://management.azure.com/"}})
if err != nil {
panic(err)
}
formData := url.Values{
"grant_type": {"access_token"},
"service": {acrService},
"tenant": {tenantId},
"access_token": {aadToken.Token},
}
jsonResponse, err := http.PostForm(fmt.Sprintf("https://%s/oauth2/exchange", acrService), formData)
if err != nil {
panic(err)
}
var response map[string]interface{}
json.NewDecoder(jsonResponse.Body).Decode(&response)
return autorest.NewBearerAuthorizer(&ACRTokenProvider{accessToken: fmt.Sprint(response["refresh_token"])}), nil
}
func main() {
client := containerregistry.NewRepositoryClient("https://servicename.azurecr.io")
authorizer, err := newACRAuthorizer()
if err != nil {
fmt.Println(err)
}
client.Authorizer = authorizer
// Do what you need to do with client here
attributes, err := client.GetList(context.Background(), "registryName", nil)
if err != nil {
log.Printf("Error while fetching attributes, %v ", err)
}
fmt.Print(attributes)
}
But the response is this
Original Error: autorest/azure: Service returned an error. Status=401 Code="Unknown" Message="Unknown service error" Details=[{"errors":[{"code":"UNAUTHORIZED","detail":[{"Action":"*","Name":"catalog","Type":"registry"}],"message":"authentication required, visit https://aka.ms/acr/authorization for more information."}]}]
What I'm missing?
i'm not sure about the GO SDK, but you can always consume the REST API directly:
GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.ContainerRegistry/registries?api-version=2019-05-01
https://learn.microsoft.com/en-us/rest/api/containerregistry/registries/list?tabs=HTTP

Error: endorsement failure during invoke. response: status:500 message:"\345\244\204\347\220\206\34...."

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.

Hyperledger Fabric Chaincode throws MVCC_READ_CONFLICT

I'm getting an error when I invoke a chaincode function. I've created two adaptations for the function. One uses a regular key, the other a composite key. I thought that using a composite key would solve any MVCC_READ_CONFLICT's since I'm no longer updating the same key.
However I get the error on both functions. Note that both function are contained in the same chaincode. I don't know if that can cause conflicts.
Here's the function with a regular key:
func (*AddTokenCallFunction) Start(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 2 {
s := fmt.Sprintf(ERROR_INCORRECT_AMOUNT_OF_ARGUMENTS, "add-tokens", 2, len(args))
return shim.Error(s)
}
account := args[0]
tokens := args[1]
currentTokensBytes, err := stub.GetState(account)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
currentAmountOfTokens := binary.LittleEndian.Uint64(currentTokensBytes)
tokensToAdd, err := strconv.ParseUint(tokens, 10, 64)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
currentAmountOfTokens += tokensToAdd
tokenBytes, err := UintToBytes(currentAmountOfTokens)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
err = stub.PutState(account, tokenBytes)
if err != nil {
s := fmt.Sprintf(ERROR_SYSTEM, err.Error())
return shim.Error(s)
}
return shim.Success(nil)
}
Here's the same function but with a composite-key:
func (*AddTokenCompositeCallFunction) Start(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 2 {
s := fmt.Sprintf(ERROR_INCORRECT_AMOUNT_OF_ARGUMENTS, "add-composite-tokens", 2, len(args))
return shim.Error(s)
}
account := args[0]
tokens := args[1]
// Retrieve info needed for the update procedure
txid := stub.GetTxID()
compositeIndexaccount := "account~tokens~txID"
// Create the composite key that will allow us to query for all deltas on a particular variable
compositeKey, compositeErr := stub.CreateCompositeKey(compositeIndexaccount, []string{account, tokens, txid})
if compositeErr != nil {
return shim.Error(fmt.Sprintf("Could not create a composite key for %s: %s", account, compositeErr.Error()))
}
// Save the composite key index
compositePutErr := stub.PutState(compositeKey, []byte{0x00})
if compositePutErr != nil {
return shim.Error(fmt.Sprintf("Could not put operation for %s in the ledger: %s", account, compositePutErr.Error()))
}
return shim.Success([]byte(fmt.Sprintf("Successfully added %s to %s", tokens, account)))
}
Could someone explain why I'm still getting a MVCC_READ_CONFLICT on the later implementation? What am I doing wrong? I'm benchmarking and sending the same accountID several times. Though I was under the impression that this would not matter when using a composite-key.
Thanks in advance.
I resolved this issue by removing my own implementation and replacing it with the one from the high-throughput sample [ https://github.com/hyperledger/fabric-samples/blob/release/high-throughput/chaincode/high-throughput.go ].
My guess is that I'm doing something in my implementation that Golang does not agree with. Since the implementations are not that different.

How to rightly decode data in block-listener.go example?

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)

Query latest world state using Hyperledger 1.0 Nodejs SDK

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])

Resources