DAML:在单独的模板中引用和设置条件到预定义列表

DAML: Reference and set conditions to a pre-defined list in a seperate template

我是 DAML 的新手,整整两天都在为这个问题绞尽脑汁。 在 "template Voting" 中指定的投票系统中,参与者可以将选民党添加到指定为 "choice Add" 的选民列表中。这个选民名单(我假设是一个名单)被定义为"voters : Set Party",(其中我似乎找不到定义),并且在"Choice Vote"和"Choice Decide"中定义了一些条件。

我正在尝试删除 "Choice Add" 功能,而是在单独模板中定义的列表中预先定义所有选民。如果我理解正确,这些预定义的选民必须声明为列表: [Party] 我创建了一个名为 "Creation" 的模板,其中包含一些变量以及名为 "CreationRights" 的自定义类型,其中包含必须成为选民的列表从投票模板中引用。 但是,我似乎无法以任何方式引用此列表。将选民数据类型更改为 [Party] 也会在 Choice Decide 和 Choice Vote 中给出 "voters" 错误。使指定的条件不可用:

无法将预期类型 'Set a1' 与实际类型“[Party]”相匹配

如何在仍然应用条件集的同时引用预定义的选民 (votingRight) 列表? 非常欢迎任何提示!

代码:

data CreationRights = CreationRights
  with 
    votingRight : [Party]
  deriving (Eq, Show)

template Creation
  with 
    actor       : Party
    creationId  : Text
    title       : Text
    votingRight : CreationRights
  where
    signatory actor

template Voting
  with
    actor : Party
    claim : Claim
    voters : Set Party
    voted : Set Party
    votes : [Bool]

  where
    signatory actor, voted
    observer voters

    key (actor, claim) : VotingKey
    maintainer key._1

    ---choice Add : ()
      ---with voter : Party
      ---controller actor
      ---do
        ---create this with voters = S.insert voter voters
        ---pure ()

    choice Decide : ContractId Decision
      controller actor
      do
        assertMsg "At least 60% must have voted" $ ((size voters / 100) * 60) <= length votes
        let approvals = length $ L.filter (\v -> v) votes
        let disapprovals = length $ L.filter (\v -> not v) votes
        let accept = approvals > disapprovals
        create Decision with ..

    choice Vote : ()
      with
        voter : Party
        accept : Bool
      controller voter
      do
        assertMsg "Voter not added" $ member voter voters
        assertMsg "Voter already voted" $ not $ member voter voted
        create this with voted = S.insert voter voted; votes = accept :: votes
        pure ()

template Decision
  with
    actor : Party
    claim : Claim
    voters : Set Party
    accept : Bool
  where
    signatory actor, voters

您无需执行任何操作即可在不使用 Add 的情况下创建 Voting 实例。 Voting 将其签名者定义为 actor, voted,因此如果 voted 为空或包含同一方的单例,则初始 Voting 实例只有一个签名者。这意味着它可以由 actor 直接创建,无需进一步交互。我在这个答案的末尾包含了一个简化的演示。

鉴于您已经创建了 Creation 的实例,您将在分类账上拥有一份选民列表的副本。届时,如果你想使用该列表,你将不得不对该合同进行选择或从分类账中读取该合同。您可以在另一个合同的选择中使用 fetchfetchByKeylookuplookupByKey 来执行后者(尽管您需要提供密钥或合同 ID)。然而,由于此模板实例代表创建 Voting 实例的权限,因此建议直接将此权限表示为 Creation 上的选择。

最后,如果您将 voters 的数据类型从 Set 更改为 List,那么您还必须更改使用该参数的相应函数。因此,例如,S.insert voter voted 必须变为 voter :: voted 或类似的。

daml 1.2
module Voting where

import DA.Next.Set as S
import DA.List as L

type Claim = Text

type VotingKey = (Party, Claim)

template Voting
  with
    actor : Party
    claim : Claim
    voters : Set Party
    voted : Set Party
    votes : [Bool]

  where
    signatory actor, voted
    observer voters

    key (actor, claim) : VotingKey
    maintainer key._1

    choice Decide : ContractId Decision
      controller actor
      do
        assertMsg "At least 60% must have voted" $ ((size voters / 100) * 60) <= length votes
        let approvals = length $ L.filter identity votes
        let disapprovals = length $ L.filter not votes
        let accept = approvals > disapprovals
        create Decision with actor; claim; voters; accept

    choice Vote : ContractId Voting
      with
        voter : Party
        accept : Bool
      controller voter
      do
        assertMsg "Voter not added" $ member voter voters
        assertMsg "Voter already voted" . not $ member voter voted
        create this with voted = S.insert voter voted; votes = accept :: votes

template Decision
  with
    actor : Party
    claim : Claim
    voters : Set Party
    accept : Bool
  where
    signatory actor, voters

test = scenario do
    alice <- getParty "Alice"
    bob <- getParty "Bob"
    charlie <- getParty "Charlie"

    alice `submit` create
        Voting with
            actor = alice
            claim = "Pizza"
            voters = fromList [ alice, bob, charlie ]
            voted = empty
            votes = []