DAML LookupByKey和FetchByKey需要不同的权限才能运行

时间:2019-08-07 01:44:20

标签: daml

我有多个签署人的合同。是否有关于如何执行LookupBykey合同的示例?我在解决如何获得各方授权以使LookupBykey正常工作方面遇到麻烦。

还有没有人可以向我解释,为什么LookupByKey比FetchByKey需要更多的权限才能运行?

使用LookupByKey和FetchByKey输入一些代码以获取相同的合同。对于同一个聚会,FetchByKey有效,而LookupByKey不起作用。

LookupByKey得到了 在Main:38:3提交时,场景执行失败:   #1:通过DA.Internal.Prelude:365:26的Sample:Sample键查找       由于缺少'partyA'的授权而失败


run = scenario do
  a <- getParty "partyA"
  b <- getParty "partyB"

  sample <- submit a do create Sample with sig = a, obs = b, content = "some text here" 

  caller <-submit b do create Caller with sig = b, obs = a

  submit b do exercise caller FetchByKey with company="test", text = "fetch by key sample"

  pure()



run2 = scenario do
  a <- getParty "partyA"
  b <- getParty "partyB"

  sample <- submit a do create Sample with sig = a, obs = b, content = "some text here" 

  caller <-submit b do create Caller with sig = b, obs = a

  submit b do  exercise caller LookupByKey with company="test", text = "look up by key sample"

  pure()


-- choices

    controller sig can
      FetchByKey : Bool
        with 
          company : Text
          text : Text
        do
          re <- fetchByKey @Sample (company, obs)

          cid_tr <- exercise (fst re) Operate with text = text

          return True


    controller sig can
      LookupByKey : Bool
        with 
          company : Text
          text : Text
        do
          re <- lookupByKey @Sample (company, obs)

          cid <- fetch (fromSome re) 

          res <- exercise (fromSome re) Operate with text = text

          return True

1 个答案:

答案 0 :(得分:1)

让我们在通用fetchByKey模板的上下文中同时查看lookupByKeySample


template Sample
  with
    maints : [Party]
    extraSigs : [Party]
    obs : [Party]
  where
    signatory maints ++ extraSigs
    observer obs

    key this : Sample
    maintainer key.maints

关键是整个合同,由指定的签署人子集维护。可以使用简单的投标工作流程实例化此类合同:


template SampleProposal
  with
    sample : Sample
    sigs : [Party]
  where
    signatory sigs
    observer (signatory sample)

    choice Sign
      : ContractId SampleProposal
      with
        sig : Party
      controller sig
      do
        assert (sig `elem` signatory sample)
        assert (sig `notElem` sigs)
        create this with sigs = sig :: sigs

    choice Accept
      : ContractId Sample
      with
        sig : Party
      controller sig
      do
        assert (sig `elem` signatory sample)
        create sample

makeSample = scenario do
  maints <- mapA getParty ["main1", "main2", "maint3"]
  extraSigs <- mapA getParty ["sig1", "sig2", "sig3"]
  obs <- mapA getParty ["obs1", "obs2", "obs3"]

  let sample = Sample with ..

  prop <- submit (head maints) do
    create SampleProposal with
      sample
      sigs = [head maints]

  signedProp <- foldlA
    (\p sig -> submit sig do exercise p Sign with sig)
    prop
    (tail maints ++ tail extraSigs)

  submit (head extraSigs) do
    exercise signedProp Accept with sig = head extraSigs

现在,谁可以fetchByKey,谁可以lookupByKey这个样本?

任何一个的第一个条件是提交方必须知道合同。也就是说,他们必须是利益相关者(即签字人或观察员),或者合同必须已经泄露给他们。

第二,必须正确授权该操作。 fetchByKey的授权与fetch一样,这意味着您必须拥有至少一个利益相关者的权限。因此,Sample的观察者可以泄露合同并委派fetchByKey

template FetchByKeyDelegation
  with
    sampleObserver : Party
    agent : Party
  where
    signatory sampleObserver, agent

    nonconsuming choice FetchSampleByKey
      : (ContractId Sample, Sample)
      with
        ctl : Party
        sample : Sample
      controller ctl
      do
        fetchByKey @Sample sample

template FetchByKeyDelegationInvite
  with
    fbkd : FetchByKeyDelegation
  where
    signatory fbkd.sampleObserver

    controller fbkd.agent can
      AcceptFBKDI
        : ContractId FetchByKeyDelegation
        do
          create fbkd

delegateFetch = scenario do
  sample <- makeSample
  let obs = head sample.obs
  agent <- getParty "Agent"

  prop <- submit obs do
    create FetchByKeyDelegationInvite with
      fbkd = FetchByKeyDelegation with
        sampleObserver = obs
        agent

  fbkd <- submit agent do
    exercise prop AcceptFBKDI

  -- By calling FetchSampleByKey, `obs` divulges the contract to `agent`
  submit obs do
    exercise fbkd FetchSampleByKey with
      ctl = obs
      sample

  -- Now `agent` can use the authority of `obs` to `fetchByKey`
  submit agent do
  exercise fbkd FetchSampleByKey with
    ctl = agent
    sample

lookupByKey具有更严格的授权规则。您需要一个 all 维护者的权限,而不是一个利益相关者。除此之外,委托的工作原理相同:

template LookupByKeyDelegation
  with
    maints : [Party]
    agent : Party
  where
    signatory maints, agent

    nonconsuming choice LookupSampleByKey
      : Optional (ContractId Sample)
      with
        ctl : Party
        sample : Sample
      controller ctl
      do
        lookupByKey @Sample sample


template LookupByKeyDelegationInvite
  with
    lbkd : LookupByKeyDelegation
    sigs : [Party]
  where
    signatory sigs
    observer (signatory lbkd)

    choice SignLBKDI
      : ContractId LookupByKeyDelegationInvite
      with
        sig : Party
      controller sig
      do
        assert (sig `elem` signatory lbkd)
        assert (sig `notElem` sigs)
        create this with sigs = sig :: sigs

    controller lbkd.agent can
      AcceptLBKDI
        : ContractId LookupByKeyDelegation
        do
          create lbkd

delegateLookup = scenario do
  sample <- makeSample
  let maints = sample.maints
  agent <- getParty "agent"

  lbkdi <- submit (head maints) do
    create LookupByKeyDelegationInvite with
      lbkd = LookupByKeyDelegation with
        maints
        agent
      sigs = [head maints]

  signedlbkdi <- foldlA
    (\p sig -> submit sig do exercise p SignLBKDI with sig)
    lbkdi
    (tail maints)

  lbkd <- submit agent do
    exercise signedlbkdi AcceptLBKDI 

  -- By calling LookupSampleByKey, a maintainer divulges the contract to `agent`
  submit (head maints) do
    exercise lbkd LookupSampleByKey with
      ctl = head maints
      sample

  -- Now `agent` can use the authority of `obs` to `lookupByKey`
  submit agent do
  exercise lbkd LookupSampleByKey with
    ctl = agent
    sample

在您的特定模型中,partyB似乎是观察者,而不是维护者。因此,他们知道合同(第一个条件),并且他们的行为得到了利益相关者的授权(fetchByKey的第二个条件)。但是,lookupByKey未经维护者授权,因此会失败。

授权差异的原因是在否定查找的情况下的行为。 fetchByKey在提交者节点上失败,因此否定查询永远不会到达网络。 lookupByKey允许否定查询,因此它们确实可以访问网络。

DAML的设计原则是除非任何一方签署了任何内容,否则任何一方都不必做任何工作。验证密钥查找是可行的,因此除非您签订了合同,否则您不必这样做。对于fetchByKey,这是事实。除非您签署了维护者的合同,否则诚实的节点将永远不会提交您作为维护者的fetchByKey

但是,对于lookupByKey,这是不正确的。首先,如果查找结果为负,则您拥有的唯一信息就是维护者的身份,因为只有这些是密钥的一部分。因此,要在提交者节点上进行授权检查,授权规则必须与维护者有关,而与利益相关者无关。

现在,假设一个维护者(而不是所有维护者)的权限就足够了。那么以下将是一件完全合法的事情:

badLookup = scenario do
  frankie <- getParty "Frankie"
  spammer <- getParty "spammer"

  let
    sample = Sample with
      maints = [frankie, spammer]
      extraSigs = []
      obs = []

  forA [1..1000] (\_ -> do
    submit spammer do
      lookupByKey @Sample sample
    )

也就是说,恶意方可以合法地通过昂贵的操作向您发送垃圾邮件。这违反了DAML的核心原则,因此授权规则必须是所有维护人员都需要的。

关键在于,应该非常仔细地考虑是否实际需要lookupByKey。通常建议设计工作流,以使所有关键查找都为正。