Why is that fetch results in a ledger update and query does not? I understand that fetch is part of a choice where as query is in the script, but both of them are doing the same thing - looking for something in the ledger. So why is one recorded and the other not? I feel I am missing something big here.
The key difference is whether it is performed on the ledger versus off the ledger. A Daml script runs the Daml interpreter but connected to the ledger via the gRPC ledger API. We record actions taken on the ledger (thatâs the fundamental concepts behind a it) but not those taken off the ledger.
This is not precise, they are both looking for an active contract on the ledger. One could also look at the ledger for the previous transactions that took place.
Lastly, notice the different types (for now ignoring the type class constraints):
- fetch :: ContractId t â Update t
- query :: p â Script [(ContractId t, t)]
- queryContractId :: p â ContractId t â Script (Optional t)
- Notice how
fetch
does not take aParty
argument, the visibility is implied by the authorization inside of anUpdate
. We always know who is performing an action on the ledger. Not off-ledger. queryContractId
is the more appropriate parallel for an off-ledgerfetch
. Notice how there isnât anything likefetchAll : -> Update [(ContractId, t)]
. That is intentional, anUpdate
is âevaluatedâ twice as part of submission and then validation. AFAIU, it is not easy to make the result of a potentialfetchAll
consistent across the two.
Thanks @Leonid_Rozenberg. Your answer does help, but I think I am unable to understand the difference between on-ledger vs. off-ledger. Does on-ledger mean invoking choices written in the template and off-ledger means any code outside of templates?
For example, we can do things such as createCmd or exerciseCmd in script, both of which result in ledger updates. It is only query which doesnât. And I notice the difference that createCmd and exerciseCmd are invoking template-code where as query statement stands on its own. So is âqueryâ provided as a tool to query the ledger without updating it possibly for debugging purposes?
And please pardon my imprecise language as I am trying to abstract out the details!
Yes, and no. On vs off ledger is just where is the code being executed. Daml uses specific types to denote where your code is being executed, Update
for on, Script
for off.
They result in a ledger update because they first construct a Command that is executed there.
I wouldnât think of it as a tool but as the things that one could do off ledger (for now as provided via Daml Script). I can send commands or I can find contracts among my ACS. Thereâs other stuff but, within Script, it is a function of what portion of the Ledger API has been wrapped.
One other important thing to note is that fetch
is a ledger event, it is recorded on the ledger. For example, if you need to look up a price to determine what to charge me, you could fetch that contract and I would need to verify that it is one that we previously agreed upon. It is a long standing TODO to expose that over the LedgerAPI, but it is an event in the sense that we charge for it.
So what I understand is this: fetch is always part of a choice that is executed as a Command by exerciseCmd. Since choices can change the ledger, their actions - including fetch - are recorded in a transaction tree.
But query is not submitted as a Command, and hence cannot change the ledger, and hence not recorded.
I hope I got that right.
Yes, makes sense.