DAML系列:Multiple party agreement

Multiple party agreement模式使用pending合约作为协议合约(agreement contract)的包装。 签署方中的任何一方都可以通过在分类帐上创建pending合约来启动工作流程,并将自己填入在signatory字段中。 除非所有各方都同意pending合约,并用自己的签名替换发起人的签名,否则不会在分类帐上创建协议合同。

动机

Initiate and Accept模式展示了如何在DAML中创建双边协议。 但是,一个项目或工作流通常需要两个以上的参与者才能达成共识,并将他们的签名放到多方合约中。 例如,在一个大型建筑项目中,至少有三个主要利益相关者:所有者,建筑师和建造者。 在开始施工之前,所有三个方面都需要就主要职责和项目成功标准达成协议。

如果将这样的协议建模为三个单独的双边协议,则任何一方都无法确定其两个合约与合作伙伴之间的第三份合约是否存在冲突。 如果使用Initiate and Accept模式来收集多方协议上的三个签名,则将对共识顺序施加不必要的限制,并且将需要一些其他合约模板(contract templates)作为中间步骤。 两种解决方案都不理想。

遵循多方协议模式,很容易与多个签署方签订协议合同,并让各方明确接受

实现

Agreement contract

Agreement contract代表了一组利益相关者之间的最终协议。 它的内容可以随业务案例而变化,但是在这种模式下,它始终具有多个签名者。

template Agreement
  with
    signatories: [Party]
  where
    signatory signatories
    ensure
      unique signatories
  -- The rest of the template to be agreed to would follow here

Pending contract

Pending contract需要包含拟议的协议合同的内容作为参数。 这样一来,各方可以知道他们要同意的是什么,在所有各方签署后Agreement contract就能被创建了。

Pending contract包含已签约的当事人列表和尚未签约的当事人列表。 如果将这些列表加在一起,则它必须与Agreement contract的签署者列表一致。

所有toSign参与者都可以选择签名。 此choice将检查该方是否确实是toSign的成员,然后创建这个Pending contract的新实例,在该实例中它们已被移至signed列表。

template Pending
  with
    finalContract: Agreement
    alreadySigned: [Party]
  where
    signatory alreadySigned
    observer finalContract.signatories
    ensure
      -- Can't have duplicate signatories
      unique alreadySigned

    -- The parties who need to sign is the finalContract.signatories with alreadySigned filtered out
    let toSign = filter (`notElem` alreadySigned) finalContract.signatories

    choice Sign : ContractId Pending with
        signer : Party
      controller signer
        do
          -- Check the controller is in the toSign list, and if they are, sign the Pending contract
          assert (signer `elem` toSign)
          create this with alreadySigned = signer :: alreadySigned

一旦所有当事方都签署了,任何一方都可以使用Finalize choice 来创建最终的Agreement contract。 这将检查该协议的所有签署方是否已签署Pending contract。

Collecting the signatures in practice

由于最终的待定合同具有多个签署者,因此任何一个涉众都不能在该状态下创建该合同。

parties@[person1, person2, person3, person4] <- makePartiesFrom ["Alice", "Bob", "Clare", "Dave"]
  let finalContract = Agreement with signatories = parties

  -- Parties cannot create a contract already signed by someone else
  initialFailTest <- person1 `submitMustFail` do
    create Pending with finalContract; alreadySigned = [person1, person2]

  -- Any party can create a Pending contract provided they list themselves as the only signatory
  pending <- person1 `submit` do
    create Pending with finalContract; alreadySigned = [person1]

一旦创建了Pending contract,其他各方就可以签署该合同。 为简单起见,示例代码仅具有表达共识的choices(但您可能希望添加到“接受”,“拒绝”或“协商”)。

  -- Each signatory of the finalContract can Sign the Pending contract
  pending <- person2 `submit` do
    exercise pending Sign with signer = person2
  pending <- person3 `submit` do
    exercise pending Sign with signer = person3
  pending <- person4 `submit` do
    exercise pending Sign with signer = person4

  -- A party can't sign the Pending contract twice
  pendingFailTest <- person3 `submitMustFail` do
    exercise pending Sign with signer = person3
  -- A party can't sign on behalf of someone else
  pendingFailTest <- person3 `submitMustFail` do
    exercise pending Sign with signer = person4

一旦所有当事方都签署了Pending contract,任何一方都可以执行Finalize choice。 这将在账本上创建Agreement contract。

person1 `submit` do
    exercise pending Finalize with signer = person1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章