diff --git a/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors.daml b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors.daml new file mode 100644 index 00000000000..1ab6e27b2a8 --- /dev/null +++ b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors.daml @@ -0,0 +1,123 @@ +-- Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +-- Regression test for https://github.com/digital-asset/daml/issues/17729 +-- The last node in the resulting transaction view should be a fetch node, +-- with the divulging stakeholder as acting party. In particular, when +-- the divulging party is a non-signatory observer of the divulged contract +-- (alice), none of the signatories (bank) should appear as acting parties +-- of the fetch node. +module DivulgeFetchNodeActors where + +import Daml.Script + +data TestData = TestData + { alice : Party + , bank : Party + , divulgee : Party + , iou : ContractId Iou + } + +data TestCase t c = TestCase + { divulgeContractCreator : Party + , divulgeContract : t + , divulgeSubmitter : Party + , divulgeChoice : c + } + +buildScript : (Choice t c r, HasAgreement t) => (TestData -> TestCase t c) -> Script () +buildScript mkTestCase = do + alice <- allocateParty "alice" + bank <- allocateParty "bank" + divulgee <- allocateParty "divulgee" + + iou <- submit bank do + createCmd Iou with + bank = bank + owner = alice + + let TestCase {..} = mkTestCase TestData {..} + + divulgeCid <- submit divulgeContractCreator do + createCmd divulgeContract + + submit divulgeSubmitter do + exerciseCmd divulgeCid divulgeChoice + + pure () + +-- @LEDGER observerDivulges DivulgeFetchNodeActors/observerDivulges.EXPECTED.ledger +observerDivulges : Script () +observerDivulges = + buildScript \TestData {..} -> TestCase + { divulgeContractCreator = alice + , divulgeContract = DivulgeTo with stakeholder = alice, divulgee + , divulgeSubmitter = alice + , divulgeChoice = ExeDivulgeTo with cid = iou + } + +-- @LEDGER signatoryDivulges DivulgeFetchNodeActors/signatoryDivulges.EXPECTED.ledger +signatoryDivulges : Script () +signatoryDivulges = do + buildScript \TestData {..} -> TestCase + { divulgeContractCreator = bank + , divulgeContract = DivulgeTo with stakeholder = bank, divulgee + , divulgeSubmitter = bank + , divulgeChoice = ExeDivulgeTo with cid = iou + } + +-- @LEDGER observerAskedToDivulge DivulgeFetchNodeActors/observerAskedToDivulge.EXPECTED.ledger +observerAskedToDivulge : Script () +observerAskedToDivulge = do + buildScript \TestData {..} -> TestCase + { divulgeContractCreator = divulgee + , divulgeContract = DivulgeFrom with stakeholder = alice, divulgee + , divulgeSubmitter = alice + , divulgeChoice = ExeDivulgeFrom with cid = iou + } + +-- @LEDGER signatoryAskedToDivulge DivulgeFetchNodeActors/signatoryAskedToDivulge.EXPECTED.ledger +signatoryAskedToDivulge : Script () +signatoryAskedToDivulge = do + buildScript \TestData {..} -> TestCase + { divulgeContractCreator = divulgee + , divulgeContract = DivulgeFrom with stakeholder = bank, divulgee + , divulgeSubmitter = bank + , divulgeChoice = ExeDivulgeFrom with cid = iou + } + +template Iou + with + bank : Party + owner : Party + where + signatory bank + observer owner + +template DivulgeTo + with + stakeholder : Party + divulgee : Party + where + signatory stakeholder + observer divulgee + + choice ExeDivulgeTo : Iou + with + cid : ContractId Iou + controller stakeholder + do fetch cid + +template DivulgeFrom + with + stakeholder : Party + divulgee : Party + where + signatory divulgee + observer stakeholder + + choice ExeDivulgeFrom : Iou + with + cid : ContractId Iou + controller stakeholder + do fetch cid diff --git a/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/observerAskedToDivulge.EXPECTED.ledger b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/observerAskedToDivulge.EXPECTED.ledger new file mode 100644 index 00000000000..b713cdbdc5a --- /dev/null +++ b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/observerAskedToDivulge.EXPECTED.ledger @@ -0,0 +1,33 @@ +Transactions: + TX 0 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:34:10) + #0:0 + │ referenced by #2:1 + │ disclosed to (since): 'alice' (0), 'bank' (0) + │ divulged to (since): 'divulgee' (2) + └─> 'bank' creates DivulgeFetchNodeActors:Iou + with + bank = 'bank'; owner = 'alice' + + TX 1 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:41:17) + #1:0 + │ consumed by: #2:0 + │ referenced by #2:0 + │ disclosed to (since): 'alice' (1), 'divulgee' (1) + └─> 'divulgee' creates DivulgeFetchNodeActors:DivulgeFrom + with + stakeholder = 'alice'; divulgee = 'divulgee' + + TX 2 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:44:3) + #2:0 + │ disclosed to (since): 'alice' (2), 'divulgee' (2) + └─> 'alice' exercises ExeDivulgeFrom on #1:0 (DivulgeFetchNodeActors:DivulgeFrom) + with + cid = #0:0 + children: + #2:1 + │ disclosed to (since): 'alice' (2), 'divulgee' (2), 'bank' (2) + └─> 'alice' fetches #0:0 (DivulgeFetchNodeActors:Iou) + +Active contracts: #0:0 + +Return value: {} diff --git a/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/observerDivulges.EXPECTED.ledger b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/observerDivulges.EXPECTED.ledger new file mode 100644 index 00000000000..ff1a5d9cb35 --- /dev/null +++ b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/observerDivulges.EXPECTED.ledger @@ -0,0 +1,33 @@ +Transactions: + TX 0 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:34:10) + #0:0 + │ referenced by #2:1 + │ disclosed to (since): 'alice' (0), 'bank' (0) + │ divulged to (since): 'divulgee' (2) + └─> 'bank' creates DivulgeFetchNodeActors:Iou + with + bank = 'bank'; owner = 'alice' + + TX 1 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:41:17) + #1:0 + │ consumed by: #2:0 + │ referenced by #2:0 + │ disclosed to (since): 'alice' (1), 'divulgee' (1) + └─> 'alice' creates DivulgeFetchNodeActors:DivulgeTo + with + stakeholder = 'alice'; divulgee = 'divulgee' + + TX 2 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:44:3) + #2:0 + │ disclosed to (since): 'alice' (2), 'divulgee' (2) + └─> 'alice' exercises ExeDivulgeTo on #1:0 (DivulgeFetchNodeActors:DivulgeTo) + with + cid = #0:0 + children: + #2:1 + │ disclosed to (since): 'alice' (2), 'divulgee' (2), 'bank' (2) + └─> 'alice' fetches #0:0 (DivulgeFetchNodeActors:Iou) + +Active contracts: #0:0 + +Return value: {} diff --git a/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/signatoryAskedToDivulge.EXPECTED.ledger b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/signatoryAskedToDivulge.EXPECTED.ledger new file mode 100644 index 00000000000..5263de9621c --- /dev/null +++ b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/signatoryAskedToDivulge.EXPECTED.ledger @@ -0,0 +1,33 @@ +Transactions: + TX 0 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:34:10) + #0:0 + │ referenced by #2:1 + │ disclosed to (since): 'alice' (0), 'bank' (0) + │ divulged to (since): 'divulgee' (2) + └─> 'bank' creates DivulgeFetchNodeActors:Iou + with + bank = 'bank'; owner = 'alice' + + TX 1 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:41:17) + #1:0 + │ consumed by: #2:0 + │ referenced by #2:0 + │ disclosed to (since): 'bank' (1), 'divulgee' (1) + └─> 'divulgee' creates DivulgeFetchNodeActors:DivulgeFrom + with + stakeholder = 'bank'; divulgee = 'divulgee' + + TX 2 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:44:3) + #2:0 + │ disclosed to (since): 'bank' (2), 'divulgee' (2) + └─> 'bank' exercises ExeDivulgeFrom on #1:0 (DivulgeFetchNodeActors:DivulgeFrom) + with + cid = #0:0 + children: + #2:1 + │ disclosed to (since): 'bank' (2), 'divulgee' (2) + └─> 'bank' fetches #0:0 (DivulgeFetchNodeActors:Iou) + +Active contracts: #0:0 + +Return value: {} diff --git a/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/signatoryDivulges.EXPECTED.ledger b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/signatoryDivulges.EXPECTED.ledger new file mode 100644 index 00000000000..ec170ef24c3 --- /dev/null +++ b/compiler/damlc/tests/daml-test-files/DivulgeFetchNodeActors/signatoryDivulges.EXPECTED.ledger @@ -0,0 +1,33 @@ +Transactions: + TX 0 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:34:10) + #0:0 + │ referenced by #2:1 + │ disclosed to (since): 'alice' (0), 'bank' (0) + │ divulged to (since): 'divulgee' (2) + └─> 'bank' creates DivulgeFetchNodeActors:Iou + with + bank = 'bank'; owner = 'alice' + + TX 1 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:41:17) + #1:0 + │ consumed by: #2:0 + │ referenced by #2:0 + │ disclosed to (since): 'bank' (1), 'divulgee' (1) + └─> 'bank' creates DivulgeFetchNodeActors:DivulgeTo + with + stakeholder = 'bank'; divulgee = 'divulgee' + + TX 2 1970-01-01T00:00:00Z (DivulgeFetchNodeActors:44:3) + #2:0 + │ disclosed to (since): 'bank' (2), 'divulgee' (2) + └─> 'bank' exercises ExeDivulgeTo on #1:0 (DivulgeFetchNodeActors:DivulgeTo) + with + cid = #0:0 + children: + #2:1 + │ disclosed to (since): 'bank' (2), 'divulgee' (2) + └─> 'bank' fetches #0:0 (DivulgeFetchNodeActors:Iou) + +Active contracts: #0:0 + +Return value: {} diff --git a/compiler/scenario-service/client/src/DA/Daml/LF/PrettyScenario.hs b/compiler/scenario-service/client/src/DA/Daml/LF/PrettyScenario.hs index a7b9325d1d2..c962234e0e7 100644 --- a/compiler/scenario-service/client/src/DA/Daml/LF/PrettyScenario.hs +++ b/compiler/scenario-service/client/src/DA/Daml/LF/PrettyScenario.hs @@ -768,7 +768,7 @@ prettyNodeNode lvl nn = do ) NodeNodeFetch Node_Fetch{..} -> do - let (parties, kw) = partiesAction node_FetchSignatories "fetches" "fetch" + let (parties, kw) = partiesAction node_FetchActingParties "fetches" "fetch" pure $ parties <-> ( diff --git a/compiler/scenario-service/client/test/DA/Daml/LF/PrettyScenarioSpec.hs b/compiler/scenario-service/client/test/DA/Daml/LF/PrettyScenarioSpec.hs index c90d4a05179..dc523822695 100644 --- a/compiler/scenario-service/client/test/DA/Daml/LF/PrettyScenarioSpec.hs +++ b/compiler/scenario-service/client/test/DA/Daml/LF/PrettyScenarioSpec.hs @@ -71,8 +71,7 @@ toPtx nodes = case runState (mapM go nodes) (0, []) of Fetch -> pure $ S.NodeNodeFetch S.Node_Fetch { node_FetchContractId = "#0" , node_FetchTemplateId = Nothing - , node_FetchSignatories = V.empty - , node_FetchStakeholders = V.empty + , node_FetchActingParties = V.empty , node_FetchFetchByKey = Nothing } Lookup -> pure $ S.NodeNodeLookupByKey S.Node_LookupByKey diff --git a/compiler/scenario-service/protos/scenario_service.proto b/compiler/scenario-service/protos/scenario_service.proto index 5ac31f99988..c8d76acd83f 100644 --- a/compiler/scenario-service/protos/scenario_service.proto +++ b/compiler/scenario-service/protos/scenario_service.proto @@ -657,9 +657,8 @@ message Node { message Fetch { string contract_id = 1; Identifier template_id = 2; - repeated Party signatories = 3; - repeated Party stakeholders = 4; - KeyWithMaintainers fetch_by_key = 13; // optional, if non-empty then fetched by key + repeated Party acting_parties = 3; + KeyWithMaintainers fetch_by_key = 4; // optional, if non-empty then fetched by key } message Exercise { diff --git a/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala b/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala index bcb51d56104..8aa3d58b4bd 100644 --- a/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala +++ b/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala @@ -640,8 +640,7 @@ final class Conversions( proto.Node.Fetch.newBuilder .setContractId(coidToEventId(fetch.coid).toLedgerString) .setTemplateId(convertIdentifier(fetch.templateId)) - .addAllSignatories(fetch.signatories.map(convertParty).asJava) - .addAllStakeholders(fetch.stakeholders.map(convertParty).asJava) + .addAllActingParties(fetch.actingParties.map(convertParty).asJava) if (fetch.byKey) { fetch.keyOpt.foreach { key => fetchBuilder.setFetchByKey(convertKeyWithMaintainers(key)) @@ -739,8 +738,7 @@ final class Conversions( proto.Node.Fetch.newBuilder .setContractId(coidToEventId(fetch.coid).toLedgerString) .setTemplateId(convertIdentifier(fetch.templateId)) - .addAllSignatories(fetch.signatories.map(convertParty).asJava) - .addAllStakeholders(fetch.stakeholders.map(convertParty).asJava) + .addAllActingParties(fetch.actingParties.map(convertParty).asJava) .build ) case ex: Node.Exercise => diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala index ac933070458..dee69126493 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala @@ -277,7 +277,7 @@ private[lf] object Pretty { partiesAction(create.signatories, "creates", "create") & prettyContractInst(create.coinst) case fetch: Node.Fetch => - partiesAction(fetch.signatories, "fetches", "fetch") & + partiesAction(fetch.actingParties, "fetches", "fetch") & prettyContractId(fetch.coid) case ex: Node.Exercise => partiesAction(ex.actingParties, "exercises", "exercise") & @@ -376,7 +376,7 @@ private[lf] object Pretty { case Some(key) => d / text("key") & prettyKeyWithMaintainers(key) } case ea: Node.Fetch => - partiesAction(ea.signatories, "fetches", "fetch") & + partiesAction(ea.actingParties, "fetches", "fetch") & prettyContractId(ea.coid) case ex: Node.Exercise => val children =