fabric icon indicating copy to clipboard operation
fabric copied to clipboard

Transaction status tracking

Open manish-sethi opened this issue 9 years ago • 17 comments

A proper mechanism for application to track the status of a transaction is missing today. I was asked about this by one of my colleague at IRL (who is building a demo).

Initially, he planned to poll the rest api /transaction/{UUID}. However, it may have following issues

  • The transactions results are not included in this API. So, the user will not be able to find out whether the transaction failed or succeeded
  • Even if we extend the above API for including the tx result, user may run into another issue because this API pulls data from ledger and some tx may never appear on blockchain (e.g., a batch may be rolled back because the state hash did not match across peer).

@srderson and I discussed about this and felt that using event mechanism may be right for this - We may need to emit an additional event at the end of batch execution. May be a single event can contain a map of guid -> status (for all the transactions included in the batch) where status can be one of the {committed, failed, rolledback}.

Finally, ideally these events should be stored for answering queries on historical data (at least for some time in past). For instance, a user may submit a transaction and may come back to check the status the next day. I am not sure whether this (storing the events and answering queries) should be within the scope of obc or left to apps.

manish-sethi avatar Feb 02 '16 17:02 manish-sethi

How would this address potentially malicious NVPs or VPs that drop the transaction?

Does the failed status mean "commited (without state change), but error during chaincode execution"?

What part of the system decides to send an event on rollback? When we batch transactions, how does that affect transactions that have been batched together? If we want to single out non-deterministic transactions, and retry execution of the block without the one non-deterministic transaction, will the re-executed transactions get duplicate events?

corecode avatar Feb 03 '16 12:02 corecode

@corecode please see the comments below.

As per my understanding, in our current model - the clients connected to a malicious NVPs or VPs would be affected in many scenarios. Let me know if I am wrong here.

Yes, that's what I had in mind for the 'failed' status

No, in my opinion the multiple events for a single tx should be avoided - otherwise client is never sure whether he has received the final event (event at each stage could be useful for system monitoring point of view but not for the user). Keeping this in mind, I think that the consensus layer is the right place for generating this event.

manish-sethi avatar Feb 04 '16 04:02 manish-sethi

The tricky part here is that a contract invocation will return either a byte stream that goes nowhere, or an error, that again goes nowhere. If, for example, an event is create specifically to publish something like "invoke-result" carrying the same txn ID as the original async REST response then we have solved the "goes nowhere" half of the problem. If the client cares, then it can subscribe to that event. However, it might still be better to accept an end point to which the original invoke result should be sent so that the application has control of what it gets back. It does not then have to subscribe to some generic "invoke results" queue and get flooded in an active system.

Meanwhile, the invoke results side of the issue is still a problem. As I mentioned on Slack, we like the bulk interface pattern, where args is a set of JSON arguments that are the equivalent of individual invokes. In such a case, you can have 50% right and 50% wrong, but putting anything in the err side of the return causes the entire txn to be lost.

So I would like to see the txn succeed if the byte stream is not nil, even if there is also an error (which of course would enumerate the args that had errors.) It seems that rest_api.json contains the necessary definitions of return results with "OK" and "ERROR" and I see no reason why they cannot travel together in the same response.

{ "OK": { blah blah }, "ERROR": { blah blah } }

Edit: Bearing in mind that this is a pseudo-RPC interface buried inside a RESTful API. That's why we will need a richer format to communication to and from contracts than would otherwise be necessary.

kletkeman avatar Feb 29 '16 14:02 kletkeman

Hi All,

Is there a timeline to fix this bug? In the India Research Lab, we are developing a PoC application for client that depends on applications receiving timely notifications of successful transaction conclusion (Init, Invoke).

I tested both the REST API to fetch transaction info, and the event API to subscribe for and catch BLOCK events, and found that transactions were getting added to the blockchain (and events were getting generated) irrespective of whether the Invoke transaction succeeded or failed.

Adding @prjayach to track this bug.

Thank you, Rama

VRamakrishna avatar Apr 13 '16 20:04 VRamakrishna

@muralisrini Can you help suggest a solution please?

prjayach avatar Apr 13 '16 20:04 prjayach

@muralisrini can you please find me tomorrow to discuss this issue, and also the other issue wherein it seems tha ttrans both successful and failed, are being added to the ledger?

chetmurthy avatar Apr 14 '16 05:04 chetmurthy

We would like to know through the event mechanism which transactions successfully completed and which ones failed. Currently all transactions are being reported by the event mechanism, whether success of failed. A solution for #710 could partially of fully address this concern.

prjayach avatar Apr 22 '16 16:04 prjayach

This applies to #710 as well

Success of block is indicated by creation of block as received by events.

We cannot lose information about (1) failure of block or (2) failure of transactions. What we have today - send a block created event - fulfills only the case where a block succeeds consensus and all tx exec in the block succeed.

The sequence (@tuand27613 hope this is correct ) ?

  • consensus success
    • exec transcations (ignore success or failure)
    • commit block
      • send "block" event
  • consensus failure - drop the block and do nothing

Can we do the following :

  1. add fields to Transaction * int systemerror // system error while executing the transaction 0 or errval * int chaincodeRetVal //return value from chaincode if systemerror =
  2. New event type "blockfailure"

New sequence (assuming original sequence above is correct)

  • consensus success
    • exec transcations
      • for each tran set (systemerror, chaincodeRetval)
    • commit block
      • send "block" event
  • consensus failure
    • send "blockfailure" event

muralisrini avatar Apr 22 '16 18:04 muralisrini

Note that since transaction results happen after consensus, any changes to the transaction cannot be made on the transaction itself currently.

With that in mind, the above proposal is modified

. use protos.NonHashData to store transaction results

. create a new event type "blockfailure"

Original sequence:

  • consensus success
    • exec transcations (ignore success or failure)
    • commit block
      • send "block" event
  • consensus failure - drop the block and do nothing

New sequence:

  • consensus success
    • exec transcations
      • for each tran set (systemerror, chaincodeRetval) on block NonHashData
    • commit block
      • send "block" event
  • consensus failure
    • send "blockfailure" event

Notes :

  1. protos.Block has protos.NonHashData and provision for setting TransactionResults. I believe it is not being used by consensus today but all the underpinnings for doing this is there
  2. Storing in Block.NonHashData is a temporary solution. It would be ideal - indeed necessary - for transaction results to be part of Transaction (and hence consented upon).
  3. @binhn pointed out this proposal is necessary but not sufficient for complete Transaction Status Tracking. While we have to do the above to keep track of all transaction states and report them, this is not sufficient for "client facing" error scenarios. E.g., what happens if client side connectivity is lost and application cannot get back a transaction UUID ?

@VRamakrishna @prjayach : this does sound like it will cover most of your scenarios ?

@kletkeman : it sounds like it will also address your concerns of transactions and their errors going nowhere - at least to some extent ? We still cannot report back any "return values" from a invoke transactions but we will be able to signify success/failures.

muralisrini avatar Apr 23 '16 17:04 muralisrini

We should look at an end to end tx path and see where we can introduce additional capabilities to help in tracking the tx status, so let's try to enumerate them:

  1. We have to assume that the tx could be lost along the way and the application would have to resubmit. To prevent duplicate tx's, we would need a unique ID (uuid) as part of the submitted tx. Currently the validator returns the uuid if successfully verifies the tx or error. We can continue with this as a confirmation that the tx received and verified. The client SDK could generate the uuid when creating a tx so the application would have the uuid at the start of the tx and would use it to discover the tx status.
  2. The application might not receive the response from the validator nor the event adapter to track the progress of the tx, so there must be some kind of polling on the app side via the tx uuid. Again the client SDK could automate this in coordination with an event listener to provide a call back for the app. If the tx is found in the event within a configured timeout, the timer would be cancelled; otherwise the polling would occur and might result in Not Found uuid. The timeout would be depending on the app and the tx type.
  3. Assuming we will reimplement the REST API to be part of the application layer using the SDK, the tx would be automatically tracked with 1 and 2 above.
  4. The successful scenarios would be covered in @muralisrini 's comments, and as noted, the results recorded by the tx in the block must not be included in the block hash due to potential differences in the execution results -- different error conditions.

binhn avatar Apr 24 '16 16:04 binhn

Looks good to me.

prjayach avatar Apr 24 '16 16:04 prjayach

@prjayach you're referring to @muralisrini 's comment or @binhn 's ?

tuand27613 avatar Apr 26 '16 18:04 tuand27613

I understood @binhn's comment as inclusive of @muralisrini's. @binhn's comments include additional failure handling, which look good to me. So, was referring to both :)

prjayach avatar Apr 26 '16 18:04 prjayach

To prioritize, just the happy path suggested by @muralisrini will serve our immediate requirement. If the block can show success/failed transactions and we can get that through the event listener, that will do. Thanks for considering taking this up on priority!

prjayach avatar Apr 26 '16 19:04 prjayach

Item approximately 3 weeks of work

ibmmark avatar May 02 '16 14:05 ibmmark

@ibmmark this needs to be decomposed into small discrete patches that ultimately yield the desired function.

christo4ferris avatar May 03 '16 15:05 christo4ferris

Is there a plan to add the transaction status API endpoint (whose response will include success/failure) for polling, per @binhn 's comment:

The application might not receive the response from the validator nor the event adapter to track the progress of the tx, so there must be some kind of polling on the app side via the tx uuid.

The REST API has /transactions/{UUID} but it currently doesn't contain the transaction status (as the OP said).

Also, I looked for an equivalent API in grpc (something like rpc getTransaction(txUUID)) but couldn't find it (in protos/*.proto); am I looking in the wrong place?

dubek avatar Jun 08 '16 19:06 dubek

@ibmmark @christo4ferris

Is this item still being considered? Is there a matching user story in Jira for this? Thanks.

angrbrd avatar Aug 16 '16 18:08 angrbrd