让我们看一下通用模板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
可以泄露合同并委托 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
真的需要。通常建议设计工作流程,以便所有关键查找都是积极的。