是否可以定义一个模板Daily
,它每天只能创建一次,如果Alice
创建一个,则Bob
不再可以,如果Bob
创建一个,则Alice
不再可以?
2 回答
当询问 DAML 中“每天一个”这样的约束时,必须考虑该约束的范围以及谁来保证它。
DAML 中最简单的模板是
template Daily
with
holder : Party
where
signatory holder
此模板的一个实例只有holder
. 没有任何一方或一组方可以确保Alice
和之间只有一个这样的合约实例Bob
。在某些分类帐拓扑中,Alice
甚至Bob
可能彼此不知道,也没有任何一方知道两者。
需要一组保证唯一性的方:
template Daily
with
holder : Party
uniquenessGuarantors : [Party]
...
唯一性保证者需要能够启用或阻止创建Daily
. 换句话说,他们必须是签字人。
template Daily
with
holder : Party
uniquenessGuarantors : [Party]
where
signatory holder, uniquenessGuarantors
现在保证 DAML 中任何类型的唯一性的最简单方法是使用合约密钥。由于我们每天需要一个,我们需要一个Date
字段。
template Daily
with
holder : Party
uniquenessGuarantors : [Party]
date : Date
where
signatory holder, uniquenessGuarantors
key (uniquenessGuarantors, date) : ([Party], Date)
maintainer key._1
这就是说,Daily
每个密钥都有一个唯一的副本,并且其中的担保人key._1
有责任使其如此。
最后,您需要一种机制来实际创建这些东西,一种DailyFactory
由担保人提供的机制。该工厂还可以确保date
始终将其设置为分类帐上的当前日期。
template DailyFactory
with
uniquenessGuarantors : [Party]
holder : Party
where
signatory uniquenessGuarantors
controller holder can
nonconsuming FabricateDaily
: ContractId Daily
do
now <- getTime
let date = toDateUTC now
create Daily with ..
一个简单的测试显示了它是如何工作的,唯一性由单方保证Charlie
:
test_daily = scenario do
[alice, bob, charlie] <- mapA getParty ["Alice", "Bob", "Charlie"]
fAlice <- submit charlie do
create DailyFactory with
holder = alice
uniquenessGuarantors = [charlie]
fBob <- submit charlie do
create DailyFactory with
holder = bob
uniquenessGuarantors = [charlie]
-- Alice can get hold of a `Daily`
submit alice do
exercise fAlice FabricateDaily
-- Neither can create a second
submitMustFail alice do
exercise fAlice FabricateDaily
submitMustFail bob do
exercise fBob FabricateDaily
-- The next day bob can create one
pass (days 1)
submit bob do
exercise fBob FabricateDaily
-- But neither can create a second
submitMustFail alice do
exercise fAlice FabricateDaily
submitMustFail bob do
exercise fBob FabricateDaily
请注意,在隐私方面,Alice
不Bob
知道彼此或对方的Daily
or DailyFactory
,但uniquenessGuarantors
知道所有保持唯一性的各方,并知道Daily
他们保证唯一性的所有实例。他们必须!
要运行上述代码段,您需要导入DA.Time
和DA.Date
.
请注意getTime
返回 UTC - 因此代码将保证唯一性,根据 UTC,每天一个,但不能根据当地日历(例如,奥克兰 NZ)。