Currently I'm working with Hyperledger Fabric chaincode and trying to get the hash of last block but I haven't found any way to get it. I need my chaincode to access this hash to do a security check.
I have tried to invoke qscc from my chaincode, which from a client does return blockchain and hash block information, but in this way access is restricted.
Code
#Transaction()
public String getBlockHash(final Context ctx) {
ChaincodeStub stub = ctx.getStub();
String[] argsQscc = {"GetChainInfo","mychannel"};
Response response = stub.invokeChaincodeWithStringArgs("qscc", argsQscc);
System.out.println("Result"+response.getMessage());
return response.getMessage();
}
Error
Rejecting invoke of QSCC from another chaincode because of potential for deadlocks, original invocation for 'mychaincode'.
It is not possible to get from within chaincode. I'm not sure you would want to anyways, because different peers may be at different heights and you would get different endorsement results leading to an invalidation of your transaction.
I'd suggest to have client query this information and pass it into the invoked chaincode as an input.
Related
I deploy a java chaincode in "fabric-sample" testnetwork. All the life cycles are sucessfully executed like (peer clifecycle chaincode package|install|approve|commit).After that chaincode is instantiaed successfully.But when try to access the chain code functions, I get the below error :
**Error: endorsement failure during invoke. response: status:500 message:"Undefined contract called" **
I used the below code to access chain code function "addNewCar" and get the following error :
The "Undefined contract called" message is returned by the Java chaincode runtime if the contract namespace specified does not exist within the chaincode. A chaincode may contain multiple smart contract definitions, each identified by a namespace. It may also contain one default smart contract, which does not have a namespace (or whose namespace is empty).
Just for reference, and by way of explanation, programmatically in a Java client application you would obtain the default smart contract for a chaincode by calling Network.getContract(String chaincodeName). You would obtain a specific named (or namespaced) smart contract within a chaincode by calling Network.getContract(String chaincodeName, String contractName).
When actually invoking the chaincode, the contract name (or namespace) is prepended to the transaction function name so that the chaincode runtime can identify which smart contract should be invoked. The actual transaction name passed to invoke the AddCar transaction function on a smart contract named car would be car:AddCar. The AddCar transaction on the default (no namespace) smart contract would be invoked just using the name AddCar.
Using the peer CLI command, you need to prepend the correct smart contract name to your transaction function name in order to invoke a specific named smart contract. Your screenshot does not capture the complete CLI command you invoked but I suspect that the transaction function name you supplied does not correctly include the name of the smart contract providing that transaction function.
I am currently running hyperledger fabric v2.2. I have developed the chaincode using the contractapi and developing the application using fabric-sdk-go/pkg/gateway
How can i get the transaction status and the transaction payload? I am aware of the GetHistoryByKey() which is available in the contractapi but that doesn't works out for my application.
I know there is hyperledger-explorer which can be used to search transactions by TxID but my use-case is my application will be querying by TxID and then it will verify the status of that particular transaction (TxID).
Also, i have tried to achieve this using the fabsdk but i am getting an error when i try to create instantiate the fabsdk using the fabsdk.New(). There seems to be some compatibility issue with the connection-profile.json which i am using the fabric-sample project.
The error which i am getting is:
failed to create identity manager provider: failed to initialize identity manager for organization: MyOrgName: Either a cryptopath or an embedded list of users is required
The same connection-profile has been used in getting the network up and running, and everything seems to be working all good. I am able to submit and evaluate transactions.
SOLUTION
The system chaincodes are embedded in the peer itself. so we need to set the target otherwise it would just give the discovery error since the contract QSCC is not explicitly deployed on the channel.
Make sure to check the core.yaml file channel.system - the system chaincode should be enabled channel.system.qscc: enable
qsccContract := network.GetContract("qscc")
txn, err := qsccContract.CreateTransaction("GetTransactionByID", gateway.WithEndorsingPeers("peer0.org1.com:8051"))
if err != nil {
fmt.Printf("Failed to create transaction: %s\n", err)
return
}
result, err := txn.Evaluate("mychannel", "4b1175335bdfe074d516a69df180ed6bc14591543eb26c10e21df2c67602b2dc")
if err != nil {
fmt.Printf("Failed to submit transaction: %s\n", err)
return
}
fmt.Println(string(result))
Note: The result needs to decoded to be human readable
Your client application can use the client SDK appropriate to your pogramming language to evaluate the GetTransactionByID transaction function on the qscc system chaincode, which is available on all peers. This transaction function takes a transaction ID as its only argument and returns a peer.ProcessedTransaction protobuf, which contains the transaction envelope and a validation code.
I have assets whose state get updated and I want get history of that asset with previous_hash and current Block_hash. I am using CouchDB as State DB of Hyperledger Fabric.
I tried fabcar example function 'getHistoryForAsset' but it can give me only TxID but I need Block hash with this.
Can anybody help me how can we do it.
Thanks
Using the transaction ID you can call (evaluate) the GetBlockByTxID transaction function on the system qscc chaincode to get the block that contained that transaction. It expects a transaction ID as an argument and returns a common.Block protobuf response payload.
https://github.com/hyperledger/fabric-protos/blob/f44816d6f621f1f7615cb4fc65643791eb6d8ce6/common/common.proto#L142
Note that a block only contains the hash of the previous block, not the hash of itself.
I am using client.channel.Execute API in fabric-sdk-go to invoke the ledger update Txs in chaincode.
I know my chaincode for ledger update is correct because invoke Tx when run from cli container command line is working perfectly all the times.
Few times, randomly, ledger updates are not reflecting when executed as REST API call from POSTMAN like below. In those cases, response code is 200 with correct response payload suggestive of successful chaincode running.
`
chaincodeID := "hcc"
fcn := "GiftToken"
args := [][]byte{
[]byte(reqBody.TokenID),
[]byte(reqBody.GiftToUserID),
[]byte(GiftTokenCountAsString),
}
setup := lib.GetFabricSetup()
transientDataMap := make(map[string][]byte)
transientDataMap["result"] = []byte("Transient data in GiftToken invoke")
response, err := setup.Client.Execute(channel.Request{ChaincodeID: chaincodeID, Fcn: fcn, Args: args, TransientMap: transientDataMap})
I am running Fabric 1.4.4 images in docker containers. My network has 1 org with 4 peer nodes.
Surely missing some aspect which is leading to this sort of behaviour.
Thanks in advance.
It takes time for all peers to sync their blocks. Once peers receive these blocks they update their world state, so you can see your change via querying.
When you query for the "just executed" transaction, you may hit one of other peers. If you want immediate result, ensure that you're querying the same peer(s) where you actually executed your transaction. You may try putting some delay to see other peers as well get the block.
The reason why you see the change immediately on CLI, is about the way of the client implementation. On CLI command execution, you specify the peer explicitly. So transaction is executed on one peer and queried on the same peer (no issues). You may prove this behavior by immediately querying (via CLI) another organization's peer just after you execute the transaction (via CLI).
However with your client, probably since you don't explicitly specify the peer, your client SDK uses peers' discovery service and find a peer in the network for you and use it.
Due to this reason, when endorsement policy is formed like "AND(org1, org2)", client SDK actually queries 2 peers (one each org) and compare results.
I am facing a performance issue while using Hyperledger fabric node.js sdk.
When I issue the invocation request to sdk and consume the response given by the chaincode by using the following code
var proposalResponse = results[0];
var proposal = results[1];
let isProposalGood = false;
if(proposalResponse
&& proposalResponse[0].response
&& proposalResponse[0].response.status === 200){
isProposalGood = true;
var res = JSON.parse(proposalResponse[0].response.payload.toString());
res.event_status = 'VALID'
resolve(res);
}else{
reject(createErrorResponse(proposalResponse[0].message,500))
return
}
The api responds within 50ms as you can see the screenshot below:
But, when I wait for orderer to confirm the transaction by using the following code:
if (code === 'VALID'){
//get payload from proposal response
var res = JSON.parse(proposalResponse[0].response.payload.toString());
res.event_status = 'VALID'
resolve(res);
}else{
var return_status = createErrorResponse("Transaction was not valid", 500);
return_status.tx_id = transaction_id_string
reject(return_status)
return
}
It takes nearby 2500ms to response as you can see the screenshot of postman below:
Correct me if I am wrong
I know it takes time because the orderer confirms the transaction and commits into the ledger. But don't you think we should proceed only if the orderer agrees to transaction and commits into the ledger. If yes, then it will take 2.5 seconds to response (network is running on docker in local machine & sdk on same machine) which is a performance issue.
What happen if data is written into the chaincode and after that orderers deny to write the transaction into the ledger?
Any help would be appreciated
the orderer confirms the transaction and commits into the ledger.
The task for the Ordering service (As the name suggests) is only to order the received endorsed transactions chronologically by channel and then deliver them to all the peers in the channel. Orderers don't actually commit the transactions into the ledger.
The Committer Peers do. And committing is a time-taking process since all the peers validate all the transactions within the block to ensure endorsement policy is fulfilled and to ensure that there have been no changes to ledger state for read set variables since the read set was generated by the transaction execution. Transactions in the block are tagged as being valid or invalid. Then Each peer appends the block to the channel’s chain, and for each valid transaction the write sets are committed to current state database. An event is emitted, to notify the client application that the transaction (invocation) has been immutably appended to the chain, as well as notification of whether the transaction was validated or invalidated.
So after knowing all these details in the Transaction Flow, It should be noted that the client application shouldn't wait for the response received by the orderer. Instead it should just request the orderer to deliver the endorsed transactions and the application should be subscribed to the events emitted by the peers so that it should know or be notified that the transactions are actually immutably committed in the channel's chain.
You can have further help regarding event subscription in the Fabric Node SDK docs.
What happen if data is written into the chaincode and after that
orderers deny to write the transaction into the ledger?
This is simply impossible as data is appended to the chain only when the transaction is validated through proper endorsements from the endorser peers (specified by the endorsement policy) and then finally delivered to the committer peers to append the new values in the chain and update the world state. Data is only written in the chain after it passes all the validations and hence an orderer can never deny for the changes made in the data.
I found another reason for this delay.
The batchtimeout variable in configtx.yaml is set to 2 seconds. So it will do its processing and then wait for 2 seconds and then cut a block. So for write operation it takes approximately 2.5 seconds.