Transaction:
After starting the flow, I see the word "starting", but the command gets exited before it's completed and the transaction isn't stored in the vault. Let me know what are the possible reasons for this to happen. Thanks in advance!
Please make sure the FinalityFlow is called.
Since your screencap is the flow initiator, then that means your implemented flow does not record the transaction into its vault.
To do that, you may want to use the FinalityFlow after collecting all the signatures. For example,
subFlow(new FinalityFlow(fullySignedTransaction, singletonList(session)));
The sample project where this line comes from.
Related
If I have have multiple clients writing to the same document in a transaction, is every transaction triggering the snapshot listener? If yes is it guarenteed that the listener are triggered in the order the transactions are commited? I would expect yes, but am a bit unsure because:
If a document write is performed the local Snapshot gets notified immediately cause of latency concerns. Does this "local" notification only get triggered if the transaction is guranteed to be successfull? Otherwise order would not be guaranteed right?
There is a onSnapshotsInSync method. Out of the documentation I don't really get if this is related to my question, but the method irritates me a bit. When should this method be considered, is my question somehow related to it?
Thanks
I would assume that a listener is only triggered, when the transaction is actually completed. And after the transaction is finished, I'd expect all changes to be committed to the database at once.
onSnapshotInSync only ensures that multiple listeners are in sync with each other.
I've been working on some ideas to determine the initiator of a transaction in Corda. It's quite hard to prove since transactions can be signed by one (trivial to prove), or more (hard to prove) parties.
However I'm now wondering if there's something inherent to the transaction itself that can be used to trivially determine who initiated a transaction.
When a transaction that requires multiple signatures is created, we call the CollectSignaturesFlow to obtain counter-party signatures, however if we do this before signing the transaction ourselves, we get the following exception:
The Initiator of CollectSignaturesFlow must have signed the transaction.
Therefore I could assume that the first signature in the transaction must have some from the initiator. Is it safe to assume that SignedTransaction.sigs[0] is the transaction initiator?
Footnote 1: The code that throws the above exception is implemented as such:
require(partiallySignedTx.sigs.any { it.by in myKeys }) {
"The Initiator of CollectSignaturesFlow must have signed the transaction."
}
This would suggest that one (or specifically more) signatures applied to the transaction will belong to the initiator.
Footnote 2: Would transaction storage (serialization/deserialization) have any impact on the ordering of the sigs list? - If it's order isn't deterministic, then we cannot rely on sigs[0] being the initiator.
Phoned a friend from r3, from Alex Koller
I looked at the question and it's not very clear to me what is Matthew trying to achieve. AFAIK corda doesn't record who initiated a transaction and trying to devise that from the order of the signatures on the tx is probably prone to error now or in the future. A possibility would be to look at the notary and see who requested the notarisation. But that may be suitable in minority of use cases. If the holder of the tx should need to know who initiated it then it may have to be recorded in one of the states. But you obviously cannot prove the correctness of the value in the state from the tx contracts, so it would have to be atested to by the other signers on the tx (in the collect signature responding flow, before the counterparties sign). I think we would need to know more about what he's doing to be able to advise. He should get in touch with Professional Services.
From following document: https://cloud.google.com/datastore/docs/concepts/transactions
What would happen if transaction fails with no explicit rollback defined? For example, if we're performing put() operation on value arguments.
The document states that transaction should be idempotent, what does this mean with respect to put() operation? It is not clear how idempotency is applied in this context.
How do we detect failure if failure from commit is not reliable according to the documentation?
We are seeing some symptoms where put() against value argument is sometimes partially saving the data. Note we do not have explicit rollback defined.
As you may already know, Datastore transactions are guaranteed to be atomic, which means that it applies the all-or-nothing principle; either all operations succeed or they all fail. This ensures that the data in your database remains consistent over time.
Now, regardless whether you execute put or any other operation in your transaction, your implementation of the code should always ensure that your transaction has either successfully commited or rolled back. This means that if you aren't fully sure whether the commit succeeded, you should explicitly issue a rollback.
However, there may be some exceptions where a commit might fail, and this doesn't necessarily mean that no data was written to your database. The documentation even points out that "you can receive errors in cases where transactions have been committed."
The simple way to detect transaction failures would be to add a try/catch block in your code for when an Exception (failed transactional operation) or DatastoreException (errors related to Datastore - failed commit) are thrown. I believe that you may already have an answer in this Stackoverflow post about this particular question.
A good practice is to make your transactions idempotent whenever possible. In other words, if you're executing a transaction that includes a write operation put() to your database, if this operation were to fail and needed to be retried, the end result should ideally remain the same.
A real world example can be - you're trying to transfer some money to your friend; the transaction consists of withdrawing 20 USD from your bank account and depositing this same amount into your friend's bank account. If the transaction were to fail and had to be retried, the transaction should still operate with the same amount of money (20 USD) as the final result.
Keep in mind that the Datastore API doesn't retry transactions by default, but you can add your own retry logic to your code, as per the documentation.
In summary, if a transaction is interrupted and your logic doesn't handle the failure accordingly, you may eventually see inconsistencies in the data of your database.
How the receiver verify a proposed transaction before accepting to make sure its a valid proposal, ie how do they check the transaction chain to make sure the same.
If its going through all the previous transactions it going going be costly and affect the TPS.
Is it possible for the receiver to goto the notary and get it verified, by any chance?
Please clarify.
At the receiver end, the transaction is being validated in the
related responder flow. Example can be found here:
https://github.com/corda/samples/blob/release-V4/blacklist/src/main/kotlin/net/corda/examples/attachments/flow/ReachAgreementFlow.kt#L42
Speaking of the verification for the entire transaction chain, it is not handled by the receiver anyway. It is handled by the Notary (When you turn the validation feature on). More details can be found: https://docs.corda.net/key-concepts-notaries.html
How can I do a transaction rollback in corda. Let's say I've a complex flow which includes 2 flows. I want to rollback the previous transaction if the last one failed how can I do that in corda? Or I need to re-design my complex flow or invalidate the previous state created myself? eg: I've a main flow.in that I created subflow which creates a new state (or updates some state). now suppose for some reason the main flow fails how do I rollback transaction created by my previous subflow?
Once a transaction has been notarised, it is final and cannot be rolled back. However, depending on how the transaction's contracts are written, it may be possible to consume the newly created state to create the old state again.
Regarding your comment, the broadcast cannot "fail" in Corda unless one of the nodes permanently leaves the network. ACKs are used to ensure messages between nodes are always received.