fabric-sdk-go Execute Not always updating ledger - couchdb

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.

Related

How to get block hash inside chaincode hyperledger fabric

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.

Hyperledger Fabric : Impact on transaction when we migrate Orderer

Migration of Ordering service from Kafka to Raft.
As we understand the Ordering service never signs the transaction in Fabric. Dose this migration will effect anything on old transaction ordered by old ordere?
Also when we query transaction(local peer query), why do we set the orderer flag?
As long as you have successfully migrated consensus type from kafka >> raft
You are allowed to proceed with transactions.
Question1: Ordering service never signs the transaction in Fabric
Endorsing peers alone will sign transactions & orderer signs the blocks
Question2: Dose this migration will effect anything on old transaction ordered by old ordere?
No, If migration is successful then you are OK to proceed
If you would have followed this link and complete without errors https://hyperledger-fabric.readthedocs.io/en/release-1.4/kafka_raft_migration.html
THEN OK, dont worry about previous data, All SAFE.
However, let me know if you need any assistance in migration. Feel free to create another question reg: migration.
If you want to see old blocks after migration
check this snippet
// keep the block_reg to unregister with later if needed
block_reg = channel_event_hub.registerBlockEvent((block) => {
console.log('Successfully received the block event');
<do something with the block>
}, (error)=> {
console.log('Failed to receive the block event ::'+error);
<do something with the error>
},
{startBlock:23}
);
startBlock:{can be any Block No}
check > https://fabric-sdk-node.github.io/tutorial-channel-events.html
you will get complete block as json format, you will have orderer signature so that you can check which orderer has sealed this block.

Understanding the interaction between the chaincode / peer and the local copy of the ledger

question 1:
The chaincode (hyperledger/fabric/examples/chaincode/go/examplexx/chaincode.go) accesses the ledger via the ChaincodeStubInterface, e.g. stub.GetState(.), stub.PutState(.).
ChaincodeStubInterface is implemented by hyperledger/fabric/core/chaincode/shim/chaincode.go.
If I see it correctly, the stubused for PutStateand GetStategets created by handleInit(.) of hyperledger/fabric/core/chaincode/shim/handler.go:
stub := new(ChaincodeStub)
handleInit is called by handleReady which is called by handleMessage which is called by chatWithPeer which is called by Start (hyperledger/fabric/core/chaincode/shim/chaincode.go) which is called by the main function of hyperledger/fabric/examples/chaincode/go/examplexx/cmd/main.go
a) With which command does this main function get invoked? By $peer chaincode install?
b) And where in the fabric code gets this mainfunction then called (I would be glad about some pointers).
question 2:
Assume $peer chaincode invoke .. '{"Args":["yy","a","b","10"]}' calls the yytransaction method in the chaincode.go (hyperledger/fabric/examples/chaincode/go/examplexx/chaincode.go) file. Assume this transaction excutes a stub.GetState(.) which calls stub.handler.handleGetState(.).
a) Is this Handler kind of an intermediate between the chaincode and the peer/ledger?
b) Does a handler belong to a peer? If yes, is there one handler per peer or are there multiple handlers (one for each chaincode)?
c) When does this Handler get instantiated?
d) When does the local ledger copy for the peer gets instantiated?
I know these are lots of questions. But I would be very glad about some hints so that I can figure out how the local copy of the ledger gets created and how the chaincode / peer communicates with it. Thank you!
a) With which command does this main function get invoked? By $peer
chaincode install?
b) And where in the fabric code gets this mainfunction then called (I
would be glad about some pointers).
The main function is defined in the peer code. When the peer decides to run the chaincode container, it just runs a docker image of the chaincode shim (golang,java,node.js) and just runs the command according to the chaincode language.
switch ccType {
case pb.ChaincodeSpec_GOLANG.String(), pb.ChaincodeSpec_CAR.String():
lc.Args = []string{"chaincode", fmt.Sprintf("-peer.address=%s", c.PeerAddress)}
case pb.ChaincodeSpec_JAVA.String():
lc.Args = []string{"/root/chaincode-java/start", "--peerAddress", c.PeerAddress}
case pb.ChaincodeSpec_NODE.String():
lc.Args = []string{"/bin/sh", "-c", fmt.Sprintf("cd /usr/local/src; npm start -- --peer.address %s", c.PeerAddress)}
default:
a) Is this Handler kind of an intermediate between the chaincode and
the peer/ledger?
b) Does a handler belong to a peer? If yes, is there one handler per
peer or are there multiple handlers (one for each chaincode)?
c) When does this Handler get instantiated?
d) When does the local ledger copy for the peer gets instantiated?
No, the the GetState actually calls a function on the local chaincode shim, not on the peer. Then, the chaincode shim (running in its container) sends a message to the peer via a dedicated gRPC stream, and the peer then reads from the database the value for the key, and returns the result to the chaincode shim, by sending it back to the gRPC stream, where the chaincode shim waits for the result.
As for handlers - there is a handler on the peer, for each chaincode.
Now, this all takes care during the endorsement time (computation of the chaincode) - but the local database is never updated during endorsement.
When the chaincode execution is finished, the client sends the transaction to the orderer, and then the orderer makes a new block and writes it to its filesystem.
The peer then pulls the block, checks the signature (from the endorsement) of the peer that executed the chaincode, and if the signature is valid then it updates its local database.

Hyperledger fabric 1.2 service discovery error

I use Hyperledger Fabric 1.2 to build a blockchain cluster, which contains 3 peers and 3 orderers. I can successfully deploy and invoke the chaincode via both CLI and Java SDK. Everything works fine. However, when I notice the service discovery function and try to use it, I met two problems. First, after I build the discover tool and try to use it to get some discovered information, I can't access the peer and get the message as follow
"failed connecting to discovery service: failed to create new
connection: context deadline exceeded"
The config command is
discover --configFile conf.yaml --userKey ./crypto-config/peerOrganizations/org1.forchain.com/peers/peer0.org1.forchain.com/msp/keystore/7458b29b1fb6a89768585430dbf0e522a40ff4aefe600fc1e4fafe62c3c972e4_sk --userCert ./crypto-config/peerOrganizations/org1.forchain.com/peers/peer0.org1.forchain.com/msp/signcerts/peer0.org1.forchain.com-cert.pem --MSP Org1MSP saveConfig
The query command is
discover --configFile conf.yaml peers --channel lajiao --server localhost:6051
I guess it may be caused by the TLS config so I canceled the TLS and tried again. This time I successfully access the peer and get some messages, but I met another problem. When I use 'discover peers xxx ' command, I always get null result, in fact there are two peers in that channel. When I use 'discover endorsers xxx' command, I always get the following error message
'failed constructing descriptor for chaincodes:'
In the meantime, the peer log outputs the following message:
'Principal set computation failed: chaincode isn't installed on
sufficient organizations required by the endorsement policy 2018-08-01
10:21:50.860 UTC [discovery] chaincodeQuery -> ERRO 1441 Failed
constructing descriptor for chaincode chaincodes:
,: chaincode isn't installed on sufficient organizations required by
the endorsement policy'
I can assure that the chaincode is successfully installed in all peers. And I didn't use the endorsement policy when I instantiated the chaincode. I think it is not the policy problem because I still can invoke the chaincode and propose a transaction.
I also tried to use the Java SDK and found that I can get the orderer nodes info but I can't get the other peer nodes or chaincode info. The log always output: "Discover of chaincode names was empty.". But the chaincode is definitely instantiated and can be invoke via SDK. I refered to the test code in "org.hyperledger.fabric.sdkintegration.ServiceDiscoveryIT" and some key Java code is as follow:
channel.addPeer(peer, createPeerOptions().setPeerRoles(EnumSet.of(Peer.PeerRole.SERVICE_DISCOVERY,Peer.PeerRole.LEDGER_QUERY, Peer.PeerRole.EVENT_SOURCE,Peer.PeerRole.CHAINCODE_QUERY)));
channel.initialize();
System.out.println("================ orderer ===============");
for (Orderer orderer : channel.getOrderers()) {
System.out.println(orderer.getName());
}
System.out.println("================ peer ===============");
for (Peer p: channel.getPeers()) {
System.out.println(p.getName());
}
System.out.println("================ chaincode ===============");
for (String s: channel.getDiscoveredChaincodeNames()) {
System.out.println(s);
}
So, how can I use the 'discover' command under TLS configuration and how can I get the discovered information?
For the config command - you need to pass a TLS root CA, via --peerTLSCA. Please look at the examples in the documentation and act accordingly.
Now - for the second problem, I think that the peers might not know each other in the channel.
Make sure you have anchor peers defined in the channel and that both peers have external endpoints configured.
Feel free to bug me (yacovm) on chat.hyperledger.org if you're struggling for too long and can't solve the problem.
You must add an anchor peer from each organization in the channel, this solved the problem for me. Anchor peers are required for the service discovery since the service discovery uses gossip protocol- thanks #yacovm
I stumbled a similar error (regarding to service discovery) as below.
Go Fabric Client logs:
Failed to get endorsing peers: error getting channel response for channel [myc]:
Discovery status Code: (11) UNKNOWN. Description: error received from Discovery Server:
failed constructing descriptor for chaincodes:<name:"mycc">
Peer logs:
Failed constructing descriptor for chaincode chaincodes:<name:"mycc" > ,:
cannot satisfy any principal combination
It's fixed when I provide CORE_PEER_GOSSIP_EXTERNALENDPOINT environment attribute with a correct value on peer's configuration (in docker yaml file in my case).
As I understood since this attribute is missing, discovery services running on peers failed to communicate with each other to have a conclusion of what current network looks like.

Hyperledger Fabric nodejs sdk performance issue

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.

Resources