Why isn't there an archive node in the transaction graph on a (consuming) choice
In the following code Transfer1 transaction graph doesn’t have an archive node, while Transfer2 transaction graph does. Why the difference?
module Main where
import Daml.Script
template Asset
with
owner : Party
where
signatory owner
choice Transfer1 : ContractId Asset
controller owner
do
create this
nonconsuming choice Transfer2 : ContractId Asset
controller owner
do
archive self
create this
demo = script do
alice <- allocateParty "Alice"
asset1 <- submit alice do
createCmd Asset with owner = alice
asset2 <- submit alice do
exerciseCmd asset1 Transfer1
asset3 <- submit alice do
exerciseCmd asset2 Transfer2
return ()
Transaction graph:
Show table viewTransactions:
TX 0 1970-01-01T00:00:00Z (Main:26:13)
#0:0
│ consumed by: #1:0
│ referenced by #1:0
│ known to (since): 'Alice' (0)
└─> create Main:Asset
with
owner = 'Alice'
TX 1 1970-01-01T00:00:00Z (Main:29:13)
#1:0
│ known to (since): 'Alice' (1)
└─> 'Alice' exercises Transfer1 on #0:0 (Main:Asset)
with
children:
#1:1
│ consumed by: #2:1
│ referenced by #2:0, #2:1
│ known to (since): 'Alice' (1)
└─> create Main:Asset
with
owner = 'Alice'
TX 2 1970-01-01T00:00:00Z (Main:32:13)
#2:0
│ known to (since): 'Alice' (2)
└─> 'Alice' exercises Transfer2 on #1:1 (Main:Asset)
with
children:
#2:1
│ known to (since): 'Alice' (2)
└─> 'Alice' exercises Archive on #1:1 (Main:Asset)
with
#2:2
│ known to (since): 'Alice' (2)
└─> create Main:Asset
with
owner = 'Alice'
Active contracts: #2:2
Return value: {}
Transaction trees in DAML (both in the transaction tree service as well as in the transaction graph in DAML Studio) only know about 4 types of nodes:
- Create
- Exercise (consuming and non-consuming)
- Fetch (not exposed in the transaction tree service atm)
- LookupByKey (not exposed in the transaction tree service atm)
There is no Archive node here. So how does archiveCmd cid or exerciseCmd cid Archive work? The DAML compiler automatically generates a consuming choice called Archive with the signatories as the controllers for every template.
So the only way to archive a contract is to call a consuming choice and that’s exactly what you are seeing here: In the first example you only see the exercise of the consuming Transfer1 choice. In the second example, you see the exercise of the nonconsuming Transfer2 choice which as a consequence exercises the consuming Archive choice injected by the compiler. In neither of those examples do you see a node representing the actual archive.
Now there are imho 2 issues here that we should address:
- In the short term, the transaction graph in DAML Studio should indicate which choices are consuming and which are nonconsuming.
- In the long term, we should imho try to change the primitives. Instead of having consuming and nonconsuming choices, only provide nonconsuming choices and a primitive for archiving. If needed, you can still have syntactic sugar in the compiler similar to how we have the
preconsumingkeyword atm. As a basis, archive + nonconsuming choices is much easier to grasp imho than consuming + nonconsuming.
One missing detail is that there are archive events in the Ledger API, but those are a simplified form of an consuming exercise event that is available through the methods that expose the “flat” transaction stream rather then full transaction trees.