Hyperledger Fabric 2.0 Unable to parse results from evaluateTransaction - hyperledger-fabric

Using Hyperledger Fabric 2.0 as of, I'm trying to evaluate a transaction result like so:
const network = await gateway.getNetwork('evm');
// Get the contract from the network.
const contract = network.getContract('cc');
const result = await contract.evaluateTransaction('getEVMAddress') ;
And the getEVMAddress function is defined as follows:
async getEVMAddress(stub) {
console.info('============= START : getEVMAddress ===========');
const evmAsBytes = await stub.getState('EVMADDRESS');
if (!evmAsBytes || evmAsBytes.length === 0) {
throw new Error(`EVMADDRESS does not exist`);
}
var evmAddress = JSON.parse(evmAsBytes);
console.info('============= END : getEVMAddress ===========');
return JSON.stringify(evmAddress);
}
Which is storing a single simple string. I don't know what's happening, I already tried decoding with BlockDecoder but I seem unable to query results outside the ledger. Do note that there are no errors if we brint the string from inside the chain code, its results are just fine, but outside the chain code I only receive a Buffer with extraneous data within which I'm unable to parse correctly.
Thanks in advance.

while retrieving data from the ledger you will by default receive buffered data which you must covert to string.
Try to convert your output to string using toString() method.
var s= result.toString(). // converts buffer to string.
After that use var object = JSON.parse(s). //converts your string to JSON object.
Finally you can view a specific column of EVM table using,
var c= s['coulmn_name']; //column name is the name of the column in your record that you want in your EVM table.

The solution was to send the string back from a Buffer with Buffer.from(string)

Related

(Node.js) Create Egypt ITIDA CAdES-BES Signature with Automatic JSON Canonicalization

I am using an example (Node.js Create Egypt ITIDA CAdES-BES Signature with Automatic JSON Canonicalization) but I always get this error ( 4043 4043:message-digest attribute value does not match calculated value[message-digest attribute value does not match calculated value] ).
Can you help me with the solution?
Code Used:
// This example assumes the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
var crypt = new chilkat.Crypt2();
crypt.VerboseLogging = true;
var cert = new chilkat.Cert();
cert.VerboseLogging = true;
// Set the smart card PIN, which will be needed for signing.
cert.SmartCardPin = "12345678";
// There are many ways to load the certificate.
// This example was created for a customer using an ePass2003 USB token.
// Assuming the USB token is the only source of a hardware-based private key..
var success = cert.LoadFromSmartcard("");
if (success !== true) {
console.log(cert.LastErrorText);
return;
}
// Tell the crypt class to use this cert.
success = crypt.SetSigningCert(cert);
if (success !== true) {
console.log(crypt.LastErrorText);
return;
}
var cmsOptions = new chilkat.JsonObject();
// Setting "DigestData" causes OID 1.2.840.113549.1.7.5 (digestData) to be used.
cmsOptions.UpdateBool("DigestData",true);
cmsOptions.UpdateBool("OmitAlgorithmIdNull",true);
// Indicate that we are passing normal JSON and we want Chilkat do automatically
// do the ITIDA JSON canonicalization:
cmsOptions.UpdateBool("CanonicalizeITIDA",true);
crypt.CmsOptions = cmsOptions.Emit();
// The CadesEnabled property applies to all methods that create CMS/PKCS7 signatures.
// To create a CAdES-BES signature, set this property equal to true.
crypt.CadesEnabled = true;
crypt.HashAlgorithm = "sha256";
var jsonSigningAttrs = new chilkat.JsonObject();
jsonSigningAttrs.UpdateInt("contentType",1);
jsonSigningAttrs.UpdateInt("signingTime",1);
jsonSigningAttrs.UpdateInt("messageDigest",1);
jsonSigningAttrs.UpdateInt("signingCertificateV2",1);
crypt.SigningAttributes = jsonSigningAttrs.Emit();
// By default, all the certs in the chain of authentication are included in the signature.
// If desired, we can choose to only include the signing certificate:
crypt.IncludeCertChain = false;
var jsonToSign = "{ ... }";
// Create the CAdES-BES signature.
crypt.EncodingMode = "base64";
// Make sure we sign the utf-8 byte representation of the JSON string
crypt.Charset = "utf-8";
var sigBase64 = crypt.SignStringENC(jsonToSign);
if (crypt.LastMethodSuccess == false) {
console.log(crypt.LastErrorText);
return;
}
console.log("Base64 signature:");
console.log(sigBase64);
Check to see if the information at this Chilkat blog post helps: https://cknotes.com/itida-4043message-digest-attribute-value-does-not-match-calculated-value/
See this example for details about debugging and what you can send to Chilkat: https://www.example-code.com/nodejs/itida_egypt_debug.asp
We were having this error, until we were advised of not using any null values in the json file. So, pls try to replace any null values in json file with "".

How to get data (state) using txID Hyperledger fabric

async createEntity(ctx, entityNumber, entityType, data) {
const entity = {
data,
};
await ctx.stub.putState(entityType + entityNumber, Buffer.from(JSON.stringify(entity)));
return ctx.stub.getTxID();
}
There is such code in chaincode, in response I get for example
612d6a6b5919fbc511e7a7b691cd349eb932f4e8d84ab9394885d3220f2e169a
And having written down some information there, the question is, how do I get this data back using the received txId?
ctx.stub.GetState and ctx.stub.PutState these function write state to levelDB's. if you want to access your data by txID one of workaround which i have used is to store data against that txID. ie
let txID = ctx.stub.getTxID();
await ctx.stub.putState(txID, Buffer.from(JSON.stringify(entity)));
With getState, as you could have expected: https://hyperledger.github.io/fabric-chaincode-node/release-2.0/api/fabric-shim.ChaincodeStub.html#getState__anchor.
A workaround would be to compare the transaction id you get as return value of ctx.stub.getTxID() with all the transaction ids you get using getHistoryForKey(entityType + entityNumber). And the match in txnid is obviously your desired data (state).
But this is still a cumbersome process. Please post if you find a direct way to get data using just the txnId. Would be a treat if such any exists.

In Hyperledger Fabric NodeJS smart contract, should all parameters be passed as a string?

In the fabric-sample repository of Hyperledger Fabric, specifically the sample application of commercial paper:
https://github.com/hyperledger/fabric-samples/blob/release-1.4/commercial-paper/organization/magnetocorp/application/issue.js
There is a line that calls the issue function:
const issueResponse = await contract.submitTransaction('issue', 'MagnetoCorp', '00001', '2020-05-31', '2020-11-30', '5000000');
The last parameter is supposedly an integer but the value 5000000 is passed as a string.
Is this a requirement in writing a NodeJS smart contract in Hyperledger Fabric that all parameters should be passed as a string?
Yes, the function parameters must be passed as string.
If you want to pass a JSON to a function you can stringify your data and parse it inside the method.
For example:
data = "{\"field1\":\"value1\",\"field2\":\"value2\"}"
var response = await contract.submitTransaction('myFunction', data);
And then in your chaincode
async myFunction(ctx, data){
data = JSON.parse(data);
//... your logics
}

Kusto Query from c#

I want to retrieve data from Kusto DB from c# app can any one help me on this.
I have knowledge on writing the Kusto queries but I need some help on pulling data from Azure Kusto DB hosted in Azure.
I tried the following code but it's not working:
var client = Kusto.Data.Net.Client.KustoClientFactory.CreateCslQueryProvider("https://help.kusto.windows.net/Samples;Fed=true");
var reader = client.ExecuteQuery("MyTable | count");
// Read the first row from reader -- it's 0'th column is the count of records in MyTable
// Don't forget to dispose of reader when done.
Could you please elaborate what's not working (what is the error message you're getting) with the code above?
In addition, a full (though simple) example can be found below:
// This sample illustrates how to query Kusto using the Kusto.Data .NET library.
//
// For the purpose of demonstration, the query being sent retrieves multiple result sets.
//
// The program should execute in an interactive context (so that on first run the user
// will get asked to sign in to Azure AD to access the Kusto service).
class Program
{
const string Cluster = "https://help.kusto.windows.net";
const string Database = "Samples";
static void Main()
{
// The query provider is the main interface to use when querying Kusto.
// It is recommended that the provider be created once for a specific target database,
// and then be reused many times (potentially across threads) until it is disposed-of.
var kcsb = new KustoConnectionStringBuilder(Cluster, Database)
.WithAadUserPromptAuthentication();
using (var queryProvider = KustoClientFactory.CreateCslQueryProvider(kcsb))
{
// The query -- Note that for demonstration purposes, we send a query that asks for two different
// result sets (HowManyRecords and SampleRecords).
var query = "StormEvents | count | as HowManyRecords; StormEvents | limit 10 | project StartTime, EventType, State | as SampleRecords";
// It is strongly recommended that each request has its own unique
// request identifier. This is mandatory for some scenarios (such as cancelling queries)
// and will make troubleshooting easier in others.
var clientRequestProperties = new ClientRequestProperties() { ClientRequestId = Guid.NewGuid().ToString() };
using (var reader = queryProvider.ExecuteQuery(query, clientRequestProperties))
{
// Read HowManyRecords
while (reader.Read())
{
var howManyRecords = reader.GetInt64(0);
Console.WriteLine($"There are {howManyRecords} records in the table");
}
// Move on to the next result set, SampleRecords
reader.NextResult();
Console.WriteLine();
while (reader.Read())
{
// Important note: For demonstration purposes we show how to read the data
// using the "bare bones" IDataReader interface. In a production environment
// one would normally use some ORM library to automatically map the data from
// IDataReader into a strongly-typed record type (e.g. Dapper.Net, AutoMapper, etc.)
DateTime time = reader.GetDateTime(0);
string type = reader.GetString(1);
string state = reader.GetString(2);
Console.WriteLine("{0}\t{1,-20}\t{2}", time, type, state);
}
}
}
}
}

Hyperledger Fabric - invokeChaincode in NodeSDK returning [Object object]

I am trying to perform a query on a chaincode(cc02) from another chaincode (cc01), both residing on the same channel. When I try invoking the query function by calling stub.invokeChaincode(...), the command is returning a [Object object] instead of the result of the query. Can someone please tell what the mistake in this is?
More details
Minimal version of the querying function in cc01 reads:
async queryOtherContract(stub, args) {
let chaincodeName = args[0]; //cc02
let fcn = args[1]; //query
let fcnArgs = args[2]; //key
let channel = args[3]; //defaultchannel
let queryResponse = await stub.invokeChaincode(chaincodeName, [fcn, fcnArgs], channel);
console.log('Query response: ', JSON.stringify(queryResponse));
}
Output:
Query response: {"status":200,"message":"","payload":{"buffer":{"type":"Buffer","data":[8,6...108]},"offset":9,"markedOffset":-1,"limit":59,"littleEndian":true,"noAssert":false}}
The payload Buffer decodes to [Object object]
The queried function from cc02 is as follows:
async query(stub, args) {
let key = args[0]; //key
let valueAsBytes = await stub.getState(key);
let valString = valueAsBytes.toString('utf8');
console.log('Value String: ', valString);
return shim.success(Buffer.from(valString));
}
Output: Value String: Value001
I have tried different variations as well including sending valueAsBytes directly as well as returning valString directly instead of wrapping it in the shim function. What am I doing wrong in this?
It is returning a buffer so you need to do the following:
Replace the following line:
return shim.success(valString);
with:
return shim.success(Buffer.from(valString));
The first chaincode (cc01) gets an object response and not a string.
I encountered a similar issue while calling chaincode invoke query from another chaincode in a network with only a single channel. It seems that calls to invokeChaincode:
var response = stub.invokeChaincode("MyChaincode", ["query", key])
Return not just the payload of the query but also modify the query by appending the transaction id and the channel along with the read/write set. (This is with v1.2 packages and network.)
response.payload.toString() was returning for me:
�{"carId":"CAR_0001"}"#48147a5a84e591671363053e58e4c56fe5d3e42c4adce1ecb2ce92f9922fd5b6:mychannel
Where the transaction id for the query is: 48147a5a84e591671363053e58e4c56fe5d3e42c4adce1ecb2ce92f9922fd5b6
and my channel name: mychannel. Not really sure what � represents.
Even though the payload passed to shim.success(payload) I confirmed to be:
{"carId":"CAR_0001"}
This was incredibly confusing, since I do not know why it modifies the actual payload string. My workaround was to extract my json string with indexOf and lastIndexOf bracket from the response.
According to the docs:
If the called chaincode is on the same channel, it simply adds the
called chaincode read set and write set to the calling transaction.
But the documentation does not mention modifying the payload or anything about the transaction id or channel name.
Hope this helps with querying chaincode from other chaincode on the same channel. Please correct me if I have incorrectly said something.

Resources