I’m trying to write a choice that allows its controller to fetch a contract as a non-stakeholder. I assume it’s possible because of the following documentation, but I can’t get the code to work.
The documentation here says: “if the fetch appears in an update block of a choice ch on a contract c1, and the fetched contract ID resolves to a contract c2, then the actors are defined as the intersection of (1) the signatories of c1 union the controllers of ch with (2) the stakeholders of c2.”
The corner case I’m trying to achieve is that the resulting intersection only contains the signatory of c1. Here is the template and test script I came up with:
template Iou
with
bank: Party
owner: Party
where
signatory bank
observer owner
template IouSharing
with
owner: Party
painter: Party
where
signatory owner
observer painter
nonconsuming choice RequestIou: Iou
with
iouID: ContractId Iou
controller painter
do fetch iouID
iou <- submit bank do
createCmd Iou with
bank = bank
owner = alice
iouSharing <- submit alice do
createCmd IouSharing with owner = alice; painter
submit painter do
exerciseCmd iouSharing RequestIou with iouID = iou
(this is a tweaked version of this example. Instead of showIou to the painter, I’m letting the painter to proactively request the iou.)
I expect the last line of the script to work because the intersection for determining the fetch actors is nonempty (the intersection is “Alice” who is the signatory of iouSharing and stakeholder of iou). However, the code results in the following runtime error:
Attempt to fetch or exercise a contract not visible to the reading parties.
Contract: #0:0 (Main:Iou)
actAs: 'Painter'
readAs:
Disclosed to: 'Alice', 'Bank'
Could anyone explain what I’m missing or is this a bug in DAML? Thanks a lot!
The problem in your example is that the painter has no visibility of the original IOU and so cannot fetch it as the error implies.
It would need to be the owner (alice) who fetches the IOU contract. In this case the IOU would then be divulged to the Painter as per the example in the docs.
Thank you @b_heather ! I’ve got a followup question.
Now my question is the documentation above says “the actors are defined as the intersection of (1) the signatories of c1 union the controllers of ch with …”. According to your answer, ‘Alice’ must be the controller of the RequestIou choice, then shouldn’t the documentation be corrected to “the actors are defined as the intersection of (1) the controllers of ch with …”?
Another way to put that question is: what’s the scenario where the fetch actor is signatory of c1 but NOT the controller of ch? Because according to the current documentation, there should exist such a scenario. I’m trying to implement that scenario with the template and script above. If that implementation doesn’t work, I feel the documentation is saying something that DAML doesn’t support.
In summary, I understand the rationale of reporting that runtime error, but that rationale seems to break what the documentation is promising.
I believe the misunderstanding is in the fact that it is always the controller of the choice that is actually calling the fetch. Therefore the fetched contract must be visible to the controller prior to fetching.
Let’s change your example slightly to better understand the documentation:
template RequestIou
with
owner: Party
painter: Party
where
signatory painter
observer owner
nonconsuming choice ShareIou: Iou
with
iouID: ContractId Iou
controller owner
do fetch iouID
iou <- submit bank do
createCmd Iou with
bank = bank
owner = alice
iouSharing <- submit painter do
createCmd RequestIou with owner = alice; painter
submit alice do
exerciseCmd iouSharing ShareIou with iouID = iou
if the fetch appears in an update block of a choice ch on a contract (RequestIou), and the fetched contract ID resolves to a contract (Iou), then the actors are defined as the intersection of (1) the signatories of c1 (painter) union the controllers of ch (alice) with (2) the stakeholders of c2 (bank,alice).
the signatories of c1 (painter) union the controllers of ch (alice)
Hi @b_heather , if “it is always the controller of the choice that is actually calling the fetch”, then there is no point mentioning that union operation. so I think the documentation should be updated. I can create a pull request in the docs github repo. Let me know if you have a different opinion:)
Hi @b_heather , I figured out the problem now. The union is useful when the controller is the divulgee of c2. In my original example, I need to divulge the Iou to the painter before the painter can exercise RequestIou successfully.