0

我与多个签署人签订了合同。是否有关于如何执行 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

4

1 回答 1

2

让我们看一下通用模板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可以泄露合同并委托 a 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有更严格的授权规则。您需要所有维护者的权威,而不是一个利益相关者。除此之外,委托的工作方式相同:

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真的需要。通常建议设计工作流程,以便所有关键查找都是积极的。

于 2019-09-09T07:21:01.760 回答