The docs here says that ‘Key assertions’ is one of the four actions in a transaction tree. However, there is no one ‘key assertion’ function or keyword in Daml. So what does this refer to? Is it any assertion involving keys, or is it a set of statements such as exerciseByKey, lookupByKey, NoSuchKey… etc?
Key assertion here refers to a negative lookupByKey. A positive key lookup is implicitly recorded as part of a fetch or exercise of a contract with the given key but we need a special primitive to record that there is no contract with a given key.
However, in practice, this is a case where the ledger model is slightly out of sync with the implementation. In the implementation, we don’t use NoSuchKey assertions but instead we have a separate LookupByKey node which can result both negative and positive assertions (fetchByKey and exerciseByKey are still recorded through regular fetch/exercise). We track that mismatch in Align Ledger Model docs to implementation · Issue #7113 · digital-asset/daml · GitHub.
So is it correct to say that the key assertion here means lookupByKey, and just that?
In the ledger model, it’s even more restrictive. It’s only a negative lookupByKey so one that returns None or in other words a NoSuchKey assertion.
Thanks @cocreature! For some reason, I am still having a hard time wrapping my head around this. Can you please point me to some code that uses this concept of ‘key assertion’?
Consider this Daml choice:
template T
with
…
choice C : ()
with
k : SomeKeyType
do None <- lookupByKey @SomeOtherTemplate k
pure ()
And now let’s say we do something like exercise cid (C yourkey)
.
The resulting transaction in the ledger model will look something like this:
exercise cid (C yourkey) -- That’s the exercise node as the root
- NoSuchKey @SomeTemplate yourkey -- That’s the key assertion which is a child node of the exercise
Another way of looking at this is to take a look at the transaction graph in Daml studio. As I mentioned above the implementation uses LookupByKey nodes rather than “NoSuchKey” assertions but if you mentally replace a key lookup with “not found” by “NoSuchKey” you will see the same structure:
module Main where
import Daml.Script
data SomeKeyType = SomeKeyType
with
p : Party
deriving (Eq, Show)
template SomeTemplate
with
p : Party
where
signatory p
key (SomeKeyType p) : SomeKeyType
maintainer key.p
template T
with
p : Party
where
signatory p
choice C : ()
with
k : SomeKeyType
controller p
do None <- lookupByKey @SomeTemplate k
pure ()
script = do
p <- allocateParty "p"
c <- submit p $ createCmd (T p)
submit p $ exerciseCmd c (C (SomeKeyType p))
Wow! Got it! Thanks a ton!