Chaincode HLF store variables with additional info - couchdb

i am using a hlf system based on chaincode to show how smart contracts could be created.
Now i am stuck with (in my mind) a very easy problem i guess.
I want to store a data objects content as key-value pair on the chains couchDb state database.
I am doing this with a docker request looking like this:
COMMAND WRITE: docker exec -t Lane1_Zf4URs_cli peer chaincode invoke -o orderer.Zf4URs.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/Zf4URs.com/orderers/orderer.Zf4URs.com/msp/tlscacerts/tlsca.Zf4URs.com-cert.pem -C mychannel -n 9bc7cca8-1dcd-49b0-a25c-fb639a0403cf -c '{"Args":["set", "[D1]{P1}", "data4"]}'
So as you see my args are calling set method and store key="[Di]{P1}" value="data4" this is working fine with this "set" method.
func (s *SmartContract) set(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) != 2 {
return shim.Error("Incorrect arguments. Expecting a key and a value")
}
err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return shim.Error("Failed to set asset: " + string(args[0]))
}
return shim.Success([]byte(args[1]))
// return args[1]
}
Now when looking at state dB this is the stored result:
{
"_id": "[D1]{P1}",
"_rev": "2-a74269cadec50f97d34d165d60235e34",
"~version": "8:0",
"_attachments": {
"valueBytes": {
"content_type": "application/octet-stream",
"revpos": 2,
"digest": "md5-2cRbxPYpSEbldj1mVovx8Q==",
"length": 5,
"stub": true
}
}
}
Now what i want to have is to store an additional value on this state db request.
Beside of "_id" (key) i want to have another field called "_executor" which should have a value "{P1}"
Should look like this:
{
"_id": "[D1]{P1}",
"_rev": "2-a74269cadec50f97d34d165d60235e34",
"_executor": "{P1}",
"~version": "8:0",
"_attachments": {
"valueBytes": {
"content_type": "application/octet-stream",
"revpos": 2,
"digest": "md5-2cRbxPYpSEbldj1mVovx8Q==",
"length": 5,
"stub": true
}
}
}
How can i do that?
What do i have to change on the docker request or on the set method?
Is this even possible?
Many thanks for help

This should work!
You have no constrains on the second argument (args[1]) in your smart contract. And since this is a string it's stored in one column and hence doesn't depend on the table structure.

I have updated my code.
I tried to use a struct and store this.
`type DataObject struct {
Name string
Executor string
Data []byte} func (s *SmartContract) set(stub shim.ChaincodeStubInterface, args []string) peer.Response {
if len(args) != 2 {
return shim.Error("Incorrect arguments. Expecting a key and a value")
}
p := DataObject{
Name: args[0],
Executor: "p1",
Data: []byte(args[1]),
}
str, err2 := json.Marshal(p)
if err2 != nil {
fmt.Println(err2)
}
fmt.Println(string(str))
if(args[1] == "data4"){
err := stub.PutState(args[0], str)
if err != nil {
return shim.Error("Failed to set asset: " + string(args[0]))
}
return shim.Success(str)
} else {
err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return shim.Error("Failed to set asset: " + string(args[0]))
}
return shim.Success([]byte(args[1]))
}}`
Now i can store executor but my data variable gets not stored as before. I need the digest so as before it should be _attachments: [valueBytes: ....digest:md5-xxx].
It looks like this:
couchDb-doc
{
"_id": "[D1]{P1}",
"_rev": "1-69be87268fs88s788668f8s766fnkushof7",
"Data": "ZGF0YTQ=",
"Executor": "P1",
"Name": "[D1]{P1}",
"_version": "3:0"
}

Related

How to fix my comparison of two values in my OPA rules?

I would like to make comparison between two values in a OPA rule.
My OPA rule is :
package example
vm_name = input.planned_values.root_module.resources[0].values.name
vm_name_length = count(vm_name)
The output is :
~$ ./opa eval -i tfplan.json -d test1.rego "data.example"
{
"result": [
{
"expressions": [
{
"value": {
"vm_name": "XXXXXXXX",
"vm_name_length": 8
},
"text": "data.example",
"location": {
"row": 1,
"col": 1
}
}
]
}
]
}
I've tried to make a comparison between the length needed and the length of the VM name :
package example
vm_name = input.planned_values.root_module.resources[0].values.name
vm_name_length = count(vm_name)
if vm_name_length == 13 {
msg := "OK"
}
else {
msg := "Not ok"
}
But the output is :
{
"errors": [
{
"message": "unexpected assign token: non-terminated set",
"code": "rego_parse_error",
"location": {
"file": "test1.rego",
"row": 24,
"col": 7
},
"details": {
"line": " msg := \"OK\"",
"idx": 6
}
}
]
}
Does anyone know how to do that ?
Rego rules describe conditional assignment, so all conditions in the rule body (i.e. inside of the { ... }) will need to be true in order for the rule to evaluate the assignment.
package example
vm_name = input.planned_values.root_module.resources[0].values.name
vm_name_length = count(vm_name)
default msg := "Not ok"
msg := "OK" {
vm_name_length == 13
}

ArangoDB query returns extra items with diacritic marks

I have the question that is related to diacritic marks. For the sake of simplicity, let's assume, I have a document collection "c". I put two documents:
{"uri": "/c/de/aërotropismus/"}, {"uri": "/c/de/aerotropismus/"}
As you see, they are almost the same, except for the diacritic mark.
Then, I create a persistent index on the field "uri".
After this I do the query:
for doc in c
filter doc.uri >= "/c/de/aerotropismus/" and doc.uri < "/c/de/aerotropismus0"
return doc
I expect this query to return one result, but I get two results:
[
{
"_key": "37070873",
"_id": "c/37070873",
"_rev": "_bHsOMnm---",
"uri": "/c/de/aerotropismus/"
},
{
"_key": "37070853",
"_id": "c/37070853",
"_rev": "_bHsO_m6---",
"uri": "/c/de/aërotropismus/"
}
]
Why is that? And how can I fix it so that it returns just one result:
[
{
"_key": "37070873",
"_id": "c/37070873",
"_rev": "_bHsOMnm---",
"uri": "/c/de/aerotropismus/"
}
]
This indeed seems like a bug:
FOR doc IN c
SORT doc.uri DESC
RETURN KEEP(doc, ['uri'])
Results:
[
{
"uri": "/c/de/aerotropismus/1"
},
{
"uri": "/c/de/aërotropismus/"
},
{
"uri": "/c/de/aerotropismus/"
}
]
Workaround
You can create a user defined function inside ArangoDB to sort an array of strings.
More reading:
Registering an AQL user function
Workaround Implementation
You can execute the following code in aragosh to register your custom function:
const aqlfunctions = require("#arangodb/aql/functions");
function isBetween(elems, left, right) {
const sorted = elems.sort();
const leftIndex = sorted.findIndex((elem) => elem >= left);
if (leftIndex === -1) {
return [];
}
const rightIndexReversed = sorted.slice().reverse().findIndex((elem) => elem < right);
if (rightIndexReversed === -1) {
return [];
}
const rightIndex = sorted.length - rightIndexReversed - 1;
if (leftIndex > rightIndex) {
return [];
}
return sorted.slice(leftIndex, rightIndex + 1);
}
aqlfunctions.register("CUSTOM::IS_BETWEEN", isBetween, true);
You can later run your AQL as this:
RETURN CUSTOM::IS_BETWEEN((FOR rec IN c RETURN rec.uri), "/c/de/aerotropismus/", "/c/de/aerotropismus0")
It will return only one record for the dataset you provided.

how to query chaincode metada with hyperledger fabric network SDK

Is there a way to get the chaincode metadata using the NodeJS or Go fabric-network SDK?
Something similar to the peer lifecycle chaincode queryinstalled command:
{
"installed_chaincodes": [
{
"package_id": "testcc_1:75afd7c4c165c56e8b8f3bd4c53cea8b420f4d94a3d53093aa0ec0229f5c738a",
"label": "testcc_1",
"references": {
"mychannel": {
"chaincodes": [
{
"name": "testcc",
"version": "1"
}
]
}
}
}
]
}
If not, then how do clients ensure which version of the chaincode they are calling??
Every SDK implements almost all the methods available in cli.
In case of go-sdk, you can implement something like this.
import (
"fmt"
"strings"
"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
fabAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
lcpackager "github.com/hyperledger/fabric-sdk-go/pkg/fab/ccpackager/lifecycle"
"github.com/pkg/errors"
)
// QueryInstalledCC : query installed CC
func QueryInstalledCC(setup *OrgSetup, ccName, ccVersion, packageID string) (string, string, map[string][]resmgmt.CCReference, error) {
label, _, _ := PackageCC(ccName, ccVersion)
resp, err := setup.Resmgmt.LifecycleQueryInstalledCC(resmgmt.WithTargetEndpoints(peer1), resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
fmt.Printf("\n Error occurred in queryInstalledCC func and error is %s", err)
}
if !strings.EqualFold(packageID, resp[0].PackageID) {
fmt.Print("Unable to match packageID in QueryInstalledCC")
return "", "", nil, nil
}
if !strings.EqualFold(label, resp[0].Label) {
fmt.Print("Unable to match labels in QueryInstalledCC")
return "", "", nil, nil
}
ref := resp[0].References
return resp[0].Label, resp[0].PackageID, ref, nil
}

Replacing a value for JSON object in Node.js

I tried replacing the value for the key "Information" from the below JSON Object using the code
"itsmdata.incidentParamsJSON.IncidentContainerJson.replace("Information",option);"
but getting error as object is not defined (Attachment)
{
"ServiceName": "IM_LogOrUpdateIncident",
"objCommonParameters": {
"_ProxyDetails": {
"ProxyID": 0,
"ReturnType": "JSON",
"OrgID": 1,
"TokenID": null
},
"incidentParamsJSON": {
"IncidentContainerJson": "{\"SelectedAssets\":null,\"Ticket\":{\"Caller_EmailID\":null,\"Closure_Code_Name\":null,\"Description_Name\":\"Account Unlock\",\"Instance\":null},\"TicketInformation\":{\"Information\":\"account locked out\"},\"CustomFields\":null}"
},
"RequestType": "RemoteCall"
}
}
If you try to update properties of itsmdata you can try this
let str = itsmdata.objCommonParameters.incidentParamsJSON.IncidentContainerJson;
itsmdata.objCommonParameters.incidentParamsJSON.IncidentContainerJson = str.replace(/Information/gi, option);

remove objects from array elastic search

I have required to remove object from array that satisfies the condition, I am able to update the object of array on the basis of condition, which is as follow:
PUT twitter/twit/1
{"list":
[
{
"tweet_id": "1",
"a": "b"
},
{
"tweet_id": "123",
"a": "f"
}
]
}
POST /twitter/twit/1/_update
{"script":"foreach (item :ctx._source.list) {
if item['tweet_id'] == tweet_id) {
item['new_field'] = 'ghi';
}
}",
"params": {tweet_id": 123"}
}
this is working
for remove i am doing this
POST /twitter/twit/1/_update
{ "script": "foreach (item : ctx._source.list) {
if item['tweet_id'] == tweet_id) {
ctx._source.list.remove(item);
}
}",
"params": { tweet_id": "123" }
}
but this is not working and giving this error,
ElasticsearchIllegalArgumentException[failed to execute script];
nested: ConcurrentModificationException; Error:
ElasticsearchIllegalArgumentException[failed to execute script];
nested: ConcurrentModificationException
I am able to remove whole array or whole field using
"script": "ctx._source.remove('list')"
I am also able to remove object from array by specifying all the keys of an object using
"script":"ctx._source.list.remove(tag)",
"params" : {
"tag" : {"tweet_id": "123","a": "f"}
my node module elastic search version is 2.4.2 elastic search server is 1.3.2
You get that because you are trying to modify a list while iterating through it, meaning you want to change a list of object and, at the same time, listing those objects.
You instead need to do this:
POST /twitter/twit/1/_update
{
"script": "item_to_remove = nil; foreach (item : ctx._source.list) { if (item['tweet_id'] == tweet_id) { item_to_remove=item; } } if (item_to_remove != nil) ctx._source.list.remove(item_to_remove);",
"params": {"tweet_id": "123"}
}
If you have more than one item that matches the criteria, use a list instead:
POST /twitter/twit/1/_update
{
"script": "items_to_remove = []; foreach (item : ctx._source.list) { if (item['tweet_id'] == tweet_id) { items_to_remove.add(item); } } foreach (item : items_to_remove) {ctx._source.list.remove(item);}",
"params": {"tweet_id": "123"}
}
For people that need this working in elasticsearch 2.0 and up, the nil and foreach don't get recognized by groovy.
So here's a updated version, including a option to replace a item with the same id by a new object.
and also passing it the upsert will make sure the item gets added even if the document doesn't exist yet
{
"script": "item_to_remove = null; ctx._source.delivery.each { elem -> if (elem.id == item_to_add.id) { item_to_remove=elem; } }; if (item_to_remove != null) ctx._source.delivery.remove(item_to_remove); if (item_to_add.size() > 1) ctx._source.delivery += item_to_add;",
"params": {"item_to_add": {"id": "5", "title": "New item"}},
"upsert": [{"id": "5", "title": "New item"}]
}

Resources