我有多个签署人的合同。是否有关于如何执行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
答案 0 :(得分:1)
让我们在通用fetchByKey
模板的上下文中同时查看lookupByKey
和Sample
:
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
。通常建议设计工作流,以使所有关键查找都为正。