Create a Commit object for a given transaction ID
As an application developer I want to create a Commit object directly from a specified transaction ID So that I can obtain the validation code for an arbitrary transaction
Currently Commit objects are only obtained by submitting a transaction. It is convenient to be able to check the commit status of a given transaction, which may not have been previously submitted by the current client application process.
Suggested implementation is to provide a newCommit() method on Network that takes a transaction ID as a parameter. Gateway already has a newSignedCommit() method for use in off-line signing, and this would mirror the pattern for Proposal, which has both newProposal on Contract and newSignedProposal on Gateway.
Tasks:
- [ ] Go implementation of
NewCommit()receiver function for Network, with unit tests and Godoc. - [ ] Node implementation of
newCommit()method on Network, with unit tests and Typedoc. - [ ] Java implementation of
newCommit()method on Network, with unit tests and Javadoc.
The qscc chaincode already offers a GetTransactionByID transaction function that does not block waiting for a commit, but could be polled until a transaction is committed, so that capability may be good enough that this feature does not need to be included in the Fabric Gateway API.
The qscc chaincode already offers a GetTransactionByID transaction function that does not block waiting for a commit, but could be polled until a transaction is committed, so that capability may be good enough that this feature does not need to be included in the Fabric Gateway API.
@bestbeforetoday We are currently going with the above approach to query the transaction state before re-submission and decode the response with BlockDecoder from fabric-common.
Suggested implementation is to provide a newCommit() method on Network that takes a transaction ID as a parameter
But I think it would be helpful to have the above suggested implementation as a part of Gateway SDK itself.
FYR @bviswana101
@tskvivekmani One other option for you, if you are checking for a transaction you submit and using the finer-grained transaction flow, is to keep hold of the Commit object you get back from calling submit() on the Transaction. You can call getStatus() on that Commit object at any point to make a blocking call for the transaction commit status. I would recommend specifying a timeout so you don't block forever.
The Commit object can be serialized for use in a different application run by calling its getBytes() method, then deserialized to a Commit object again by calling newCommit() on a Gateway object.
Using Node.js as an example, the code might look something like this, although the flow is similar in all client languages:
const proposal = contract.newProposal('transactionName');
const transaction = await proposal.endorse();
const commit = await transaction.submit();
const serializedCommit = commit.getBytes();
// Store the serialized commit bytes for later use
const deserializedCommit = gateway.newCommit(serializedCommit);
const status = await deserializedCommit.getStatus();
This capability was included as part of a general pattern of supporting recovery from application failures by allowing objects at each stage of the transaction flow to be persisted (issue #394).
Thanks for the reply @bestbeforetoday.
We're currently persisting proposal bytes in order to re-submit (w/ same proposal to eliminate version bumps) if encountered any errors.
So wouldn't it be an overhead to persist commit object to query txn state.
-- Or lets say, we
- Persist commit object
- Got validation code as
DUPLICATE_TXIDas commit status
In this case, To know of the response/result of the transaction, we would still need to query the TxnID right.
You are correct that the serialized Commit object does not store the transaction result. Neither does the serialized Proposal object. You do see the transaction result on the Transaction object returned from proposal.endorse(). It really depends what you need to do and which steps in the transaction submit flow you might need to retry. The serialization of the objects at each step in the flow just allows you to persist them and reuse those objects again if your client application is terminated or is restarted.
A transaction recorded on the blockchain is only assigned a DUPLICATE_TXID validation code if a transaction is submitted that has the same ID as a transaction already recorded on the blockchain. I suspect you will not see this happen when checking the commit status since you will likely be returned the first transaction with that ID, which will not be a duplicate and will have some other validation code.
To get the result of a transaction that is actually recorded on the blockchain, re-endorsing the same proposal is not a good approach since the ledger state may be different from when the original transaction was endorsed and therefore you may get a different result. To see the transaction result you should probably either store the transaction result you received when doing the first endorsement, or use the qscc system chaincode to get the transaction and interrogate its protocol buffer message to check the result.
I should add that this issue is just intended to allow use of the CommitStatus capability offered by Fabric Gateway as an alternative to using the qscc chaincode, for cases where you didn't submit a given transaction have no access to the Commit object created as part of that flow.