Zhuang's Diary

言之有物,持之以恒

需求

在供应链(金融)、个人履历以及各个行业应用中,ACL(Access Control List)是共同类的需求。

写管理

OpenZeppelinRoles.sol 可以使用,搭配 ERC721 合约 使用,处理生成和销毁数字资产功效加倍。但是数据写在区块链上之后,即使使用了 private 关键字也是可以被用户读取的。

以上方法只实现了用户的 写权限控制,无法实现用户的读权限控制。

读管理

思路简介:

a) 客户端 AES 加密原文(shared data);b) 密文(encrypt(shared data))如果过大则存放于某云数据库,其他用户也可以访问到云数据库,也可以直接存放于ethereum 上,如 Tx 的 extraData 或者 state 中;c) 验证用户符合条件,如 role,policy或者address的要求时,data owner 将 encrypt 的秘钥经过用户(data user)的 pk 加密后, 通过 event 传递给到用户(data user)

详细参加:Multi-Authority Attribute-Based Access Control with Smart Contract

以下是论文中的详细说明:

Architecture

System target

Here we present a concrete example. Suppose an data owner in the Computer and Information Sciences Department at the University of Delaware specifies access policy W to be [UD, PhD Student, Gender#] for accessing encrypted research meeting notes, and we have student Alice’s attribute list SAlice = [UD, PhD Student, Female], and student Bob’s attribute list SBob = [UD, Master Student, Male]. As a result, Alice can access the corresponding encrypted research meeting notes, while Bob cannot because he is an Master student. Notice that the Gender# attribute indicates that either gender satisfies the access policy.

Participants

• Data Owner (DO): A DO is an entity (e.g., person, organization, or process) who owns the data to be shared. A DO actively specifies access policies for the data it shares.

• Data User (DU): A DU is an entity who wants to access data shared by DOs. A DU actively seeks access authorizations from DOs.

• Shared Data (SD): An SD is a piece of data owned by a DO, and can be accessed passively by authorized DUs.

• Attribute Token (AT): An AT is a credential representing an attribute that a DU possesses.

• Attribute Authority (AA): An AA is a pre-verified and authorized node in Ethereum who issues ATs to qualified DUs who possess the corresponding attributes.

Workflow / Timeflow

Headless Commerce是一个有趣的名字,它是近一年国外电商行业的时髦术语。国内还不怎么流行这种叫法,但与其对应类似的概念实际上在中国也是漫天飞舞,这就是“API化”和“中台”说法。想到中台的火热,我也随手记下这篇文章,聊聊无头电商和中台。

什么是无头电商?

Headleass Commerce可以翻译成无头电商,或断头电商,核心概念就是将前台展现和后台服务进行解耦的一种架构。后台以API的方式提供服务,前端展现层与后端分离。没有前端表现层(头),剩下的就是无头电商了,剩下的就是一堆API接口。

写过代码的程序员都很容易理解,这不就是前后端分离,或面向服务架构(SOA)么?为什么这么简单的事情,会成为电商行业的噱头呢?其实,这个事情后面有很多深层次的原因,有商业原因,有电商演进历史,有生态原因,有品牌主新需求等等。

为什么会发生这种变化?

有几个事情比较重要:

  1. 品牌主建立自有电商的需求
  • 国内外电商平台虽然都已经寡头化,美国有亚马逊,中国有京东淘宝,很多品牌主依旧努力建立自有电商渠道,不断突围。

  • 品牌主建立自有平台可以加强自有数据的把控能力,直接与消费者进行互动,保证独有体验。

  1. 电商体验的多样化
  • 电商不在是一个简单Web端,电商行业出现很多新触点:语音购物,无人超市,场景购物等,前端变得更加丰富多样

  • 底层的基础能力相对稳定,底层可以利用API确保稳定

  1. 品牌直接面对消费者(Brand Direct To Consumer)
  • 很多互联网品牌通过创新的电商方式直接面对消费者,消除传统的中间环节(零售商,批发商等)

  • 一些私域流量给DTC创造了很多创新机会,最后这些创新场景都需要落地电商平台上。

  1. 电商平台的演化
  • 一体式的电商解决方案:从交易到内容,往往是一家巨型供应商提供,比如Oracle , SAP, WordPress等
  • 内容和交易能力的一些分离,出现了CMS或DXP的独立功能区域
  • 无头电商:以API为基础的构建方式,前后端分离,通过API支持更广泛的生态

这种无头商务平台脱离了通常模板化的系统前端,允许开发人员在任何类型的框架中为产品和服务创建各种接触点。这样,后端开发人员就可以灵活地创建和使用应用程序编程接口(API),以便交付给任何类型的设备,而不仅仅是标准屏幕。

无头商务与传统商业有什么区别?

传统平台为客户和业务提供了模板化的体验,缺少自由风格的发挥空间,通过无头商务,可以更好地控制商务平台、客户业务和用户体验。

结论

无头电商的好处本质上都来源于前后端的解耦,面向服务和API的架构。后端可以聚焦在沉淀,前后端可以利用API进行交互,以实现更多的应用场景。

  1. 无头商务是迎接物联网时代(IoT)而创建的对应一些新零售场景,特别是没有任何屏幕的场景,如何通过语音,视频,手势等方式与消费者完成商业互动,其中也包括在户外,汽车等不同场地。
  2. API 是数据流动的管道
    无头电商也是未来数据收集,分析,管理的技术架构的基础。传统的单体电商产品,往往不能实现数据的灵活对流。
  3. 快速发布
    各模块的解耦使得各个模块可以独立升级和发布,各个模块可以采用微服务技术独立发布,只需要保持接口的稳定和兼容。新的功能可以通过增加新的接口,新的场景可以驱动这些新接口的集成。例如,我们需要更换支付服务商,我们只需调用一个新的接口实现者就行,原则上不需要大更改,所有上层应用都不受影响。
  4. 个性化
    无头电商是模块化和灵活的,各个模块API可以进行灵活的组合,封装,二次开发等。很多个性化的策略可以灵活应用在无头电商的各个环节当中。例如,消费者画像也可以作为标准模块,提供给各个模块使用,最大程度复用沉淀的洞察。
  5. 扩展性和稳定性
    稳定性,可扩展性和性能对电子商务系统非常重要,因为它们可以直接影响客户的购买行为。如果出现意外的后端故障,如果后端和前端断开连接,后者仍然可用。后端和前端可以独立地进行水平扩展和垂直扩展。

无头电商和中台

说到这里,无头电商和中国热火朝天讨论的中台(Platform)的理念非常类似:大中台,小前台;

大中台:本质上是沉淀能力,利用API提高复用性;小前台:本质上是快速迭代和试错。这个逻辑其实是和Gartner2015提出的Pace-Layerd 应用战略是一致的,当时Garnter根据系统的变化速度分为 “创新型” ,”差异型”,”稳定型”几种。

数据中台其实就是保持接口稳定的一个系统,支持快速创新的业务层。

中台的一些困惑和随想

在中国,中台已经流行几年了,仔细想想,中台本质也是一种无头。无头电商是中台概念在一个具体行业的应用。沉淀复用是很多公司的不同阶段都会碰到的,中台战略是解决这个问题的某种形式。很多大大小小公司开始组建中台攻坚团队,我与很多朋友都聊过中体的经历,大大小小都会碰到一下一些困惑。例如,一个公司在推进中台战略中,单点登录是唯一成功的案例,其它中台能力的推广都是很难,每个业务线都有自己研发,不喜欢别人轮子。

1) 中台和前台的界限无法界定清楚。中台实现两个能力,一个是沉淀,另外是复用; 二者相辅相成。前台更加面向客户,他们更加容易最快速度创造客户价值和商业价值。

如何衡量这种花费是否合理? 一种衡量的方法是:对每个新业务,评估一下中台支持的粒度和程度,如果对于中台的范畴,大家都没有太大歧义,这么这种解耦可能是合理的。如果对于每个新业务,大家都要对范围界定进行激烈讨论,那么大家还是需要一个更加清晰的中台定位。

2) 中台的成功无法衡量和量化

那么如何衡量中台的成绩和成功呢?很多时候这个成绩是没有办法衡量的,但是无法量化的东西,是无法改进的。因此,很多中台的战略都是至上而下的组织形态优化。

具体量化的时候,我们常常有两个思路:a) 中台能力被使用了的范围和深度 ,例如API调用次数,业务使用量,依赖强度等;b) 中台帮助那些业务提升了效率和效益,提升比例等。量化这些指标常常是短期的行为,中台建设也包括一些创新的投资,以及中长期的数据能力沉淀。

3) 产品经理在中台战略的新挑战

大多产品经理喜欢参与2C的产品设计,小一部分产品经理深入2B的产品设计。中台涉及很多技术逻辑,涉及到业务底层实现,涉及到公司多个部门的协同共赢,能够胜任这种角色的产品经理,少之又少,大部分都是由研发主管兼任,或者是项目经理类似角色担当。

中台产品经理比较靠近2B/2D的产品经理,但是更加面向内部多种业务,面向综合效率提升,面向技术架构,也需要很强的商业化的思考。

4) 数据中台越来越重要

大部分公司都有独立的数据平台团队,但各业务线对数据都有自己的解读。在每一个时刻,数据中台需要有自己清楚的定位,这个定位需要让所有业务都清楚了解。如果定位有任何变化,这种变化需要提前通知到各个业务线。

现实中,各个业务线都会发展自己的数据应用能力,数据分析能力,这些分析需要定期的沉淀到数据中台。

5) 中台需要面向开发者,与理解数据逻辑的业务人员的

中台不是华丽的界面和装修,而是底层的脊梁和砖头。中台的能力,必须由业务团队使用(逻辑上理解),程序员使用(利用API调用)。

如果中台直接面向业务的运营,很可能是不成功的。因为,运营很多时候具有快节奏的变化,缺少稳定性,运营平台更像是一种中台的上层应用。另外,运营在使用中台时候,缺少工程师对于API的一些理解,也不利于中台的接口完善和发展。

前台团队中有程序员,才能最大程度发挥中台的作用。

6) 中台是需要运营的,面向中台服务的技术运营

运营可以成为中台和前台的润滑剂,保证前台和中台之间的顺畅。在一些大型的公司,中台能力甚至需要一些主动的推广,确保整个组织能够真正从中台中收益,并且为中台也做贡献。

无头电商的技术方案

说了这么多中台,看起来有些跑题了,回到无头电商的一些技术,其中有些技术很多技术中台都可以采用。

1)CMS支持无头电商的产品:

  • Contentful (非常流行, 基于API的内容管理系统)
  • Adobe Experience Manager (企业级别体验管理平台)
  • Amplience (企业级别体验管理平台,支持无头电商)
  • Acquia (企业级别体验管理平台,支持无头电商)
  • Kentico (中型内容管理平台)
  • Sitecore (企业级别内容管理平台)
  • Prismic (面向API的CMS)
  • Gatsby (基于react的PWA 框架)
  • Vuestorefront (基于vue.js的PWA 框架)
  • Deity (基于react.js的 PWA 框架)

2)支持无头电商的系统

  • CommerceTools
  • ElasticPath(用途比较广的电商平台,支持丰富API)
  • Moltin(主打API模式的电商平台)
  • Magento (2018年5月被Adobe收购,整合在Adobe Commerce Cloud中,支持与Adobe其它软件整合)
  • BigCommerce(主打无头电商)
  • SAP CX Commerce Cloud (优势在后端 如CRM/ERP等,支持通过API模式与不同的前端整合)
  • OroCommerce (B2B的电商平台)
  • Spryker

3) 无头电商的API标准:

  • OCAPI (Open Commerce API):

    这个标准是Salesforce提供的电商API,渐渐成为电商行业的开放标准,Magento,SiteCore等系统能比较好支持这个协议。Salesforce在对接标准和开放程度上走在行业领先地位,这也是大家看好它的重要原因。

  • JSS(Javascript Services)
    SiteCore利用Javascript提供的API能力,SiteCore也越来越开放

**4) 扩展性的前端技术: **

  • JAMStack
    这是一个非常有趣的架构,企图颠覆传统三层架构:静态元素放在CDN上,动态数据利用Service/API进行交互。JAMstack将复杂问题分解为动态和静态部分。

  • PWA(Progressive Web Apps)

    把网页开发成像本地应用一样的技术,可以媲美原生用户体验,包括离线可用,后台推送等功能。类似微信的小程序技术,只不过PWA是浏览器里的小程序。PWA梦想很美好,现实很残酷。PWA的技术也在被各种平台内的技术所代替。

  • GraphQL

    一种面向API的理想主义查询语言;传统API需要严格规定参数和格式,GraphQL提供了一些API的查询和归一化能力,使得API开发更加方便和具有扩展性。它比REST更加灵活。一些都是接口,一切都是可描述的。

无头电商的缺点

1) 复杂性的增加

单体模式依旧是最简单模式,无头电商将失去这种简单,进入一个复杂的技术世界。幸运的是,现在的软件技术和云技术都可以更好的处理这些复杂度,当然这也涉及到技术思维的升级。。

2) 成本的增加

无头电商的推广和实施往往需要时间和耐心。从经验来看,无头电子商务实施通常会产生成本开销(由于需要更多开发);集成也会更加复杂 ,其中会涉及到更多的第三方供应商。

那么,如何管理这种复杂度和有效管理成本?有几点可能会有帮助:

1)加强数据团队和云技术人才,增强管理技术复杂度的能力

2)业务驱动的演化路径,一步步的演化系统架构,更好的系统架构要更加快速尝试更多的业务场景

3)积极利用公有云基础架构,少造轮子,持续优化

参考连接:

https://paulnrogers.com/introduction-to-headless-ecommerce/

https://www.sparkred.com/blog/michael-kors-case-study-a-journey-to-headless-commerce/

https://www.ipraxa.com/blog/headless-ecommerce-guide/

https://jss.sitecore.com/features

https://www.bigcommerce.com/blog/headless-commerce/

https://www.degdigital.com/insights/headless-architecture-digital-experiences/

https://www.bigcommerce.com/blog/flexible-headless-commerce-solutions/

https://www.jianshu.com/p/a88b80d88284

作者介绍:欧阳辰,品友互动,CTO,《Druid实时大数据分析》书作者,《构建高质量的软件》译者,超过17年的互联网老兵。

产品设计的关键步骤

AZTEC 产品的关键步骤:1)生成 note;2)管理秘钥;3)验证 note

AZTEC中的aztec.js能够工作在浏览器或者手机程序中,生成 proof 大约需要 10ms,非常高效。

1.生成 note

证明(proof)中的保密 Token 需要用到 note。note 在票据登记所(note registry)中登记,proof 也在 note registry 中登记。

生成一个新的 note 需要 owner 的publicKey,所有人使用其地址证明其 owner 的身份,value是 note 中保密 Token 的值:

bobNote1 = await aztec.note.create(bob.publicKey, 100);

2.管理秘钥

每一个 note 都有一个对应的查看秘钥(viewing key);同时还有一个对应的暂存秘钥(ephemeral key)。暂存秘钥用于恢复查看秘钥,同时 note 的 owner 的 private key 也可以恢复查看秘钥。

在服务器端,恢复查看秘钥并再次发送给到 owner 需要一套完备的管理系统,目前 AZTEC 还没有这样的系统。

在客户端,建议将暂存秘钥加密后保存起来。

3.消费 note

消费 note 使用标准的 Join Split 证明。

1
2
3
4
5
6
7
8
9
const { proofData, expectedOutput, signatures } = aztec.proof.joinSplit.encodeJoinSplitTransaction({
inputNotes: [bobNote1],
outputNotes: [sallyTaxiFee, bobNote2],
senderAddress: accounts[0],
inputNoteOwners: [bob],
publicOwner: accounts[0],
kPublic: 0,
validatorAddress: privateVenmoContract.address,
});

kPublic是被转换的 ERC20 Token 的值。负值代表 ERC20 Token 被消耗,且转换为 note;正值代表将 note 兑换回到 ERC20 Token。且遵守kPublic == outputNotes

Join Split证明是自动使用inputNoteOwners: [bob]的私钥来签名交易的。更加严谨的话可以使用confidentialApprove方法,例如:

1
2
const signature = aztec.signer.signNote(assetAddress, noteHash, spenderAddress, owner.privateKey);
ZkAsset.confidentialApprove(noteHash, spender, true, signature);

最后再使用下面的语句最终消费掉 note:

1
2
3
await privateVenmoContract.confidentialTransfer(proofData, signatures, {
from: accounts[0],
});

AZTEC 的交易流程

如图所示,结合借贷 DApp,分析AZTEC的步骤:

1.借贷 ZkAsset

1.1.构建 proof

用 aztec.js 构建 proof。即 proofData:

1
2
3
4
5
6
7
8
const {
proofData,
} = aztec.proof.mint.encodeMintTransaction({
newTotalMinted: newTotalNote,
oldTotalMinted: oldTotalNote,
adjustedNotes: [loanNotionalNote],
senderAddress: loanDappContract.address,
});
1.2.注册 note

proof 可以被 Mint 成为新的 note,

1
Loan(loanId).confidentialMint(MINT_PROOF, bytes(_proofData));

2.结算 ZkAsset

2.1.批准 ACE 合约代表 owner 花费 ERC20 Token
1
await settlementToken.approve(aceContract.address, value);
2.2.构建 proof
1
2
3
4
5
6
7
8
9
10
11
12
const { 
proofData,
expectedOutput
} = aztec.proof.joinSplit.encodeJoinSplitTransaction({
inputNotes: [],
outputNotes: [Note1, Note2], // note values sum to kPublic
senderAddress: account.address,
inputNoteOwners: [],
publicOwner: account.address,
kPublic: -value,
validatorAddress: joinSplitContract.address,
});
2.3.批准 ACE 合约花费 ERC20 Token
1
2
3
await ACE.publicApprove(zkAsset.address, hashProof, kPublic, {
from: accounts[0],
});
2.4.转发交易

转发 proof 给到 ACE,proof 中的senderAddress与发起调用ACE.validateProof的msg.sender 需保持一致。

1
(bytes memory _proofOutputs) = ACE.validateProof(JOIN_SPLIT_PROOF, address(this), _proofData);
2.5.处理转移指令(Transfer Instructions)
1
_loanVariables.settlementToken.confidentialTransferFrom(JOIN_SPLIT_PROOF, _proofOutputs.get(0));

3.结算贷款处理

3.1.批准结算合约来花费 note
1
2
3
4
5
6
7
8
9
10
11
12
13
const settlementSignature = signNote(
zkSettlementAsset.address,
settlementNoteHash,
loanId,
lender.privateKey);
await zkSettlementAsset.confidentialApprove(
settlementNoteHash,
loanId,
true,
settlementSignature,
{
from: lender.address,
});
3.2.构建 proof
1
2
3
4
5
6
7
const {
proofData,
} = aztec.proof.bilateralSwap.encodeBilateralSwapTransaction({
inputNotes: [takerBid, takerAsk],
outputNotes: [makerAsk, makerBid],
senderAddress: loanId,
});

其中需要takerBid == makerAsk ; takerAsk == makerBid

3.3.终极交易并更新状态
1
2
3
4
5
(bytes memory _proofOutputs) = ACE.validateProof(BILATERAL_SWAP_PROOF, address(this), _proofData);
(bytes memory _loanProofOutputs) = _proofOutputs.get(0);
(bytes memory _settlementProofOutputs) = _proofOutputs.get(1);
settlementZkAsset.confidentialTransferFrom(BILATERAL_SWAP_PROOF, _settlementProofOutputs);
loanZkAsset.confidentialTransferFrom(BILATERAL_SWAP_PROOF, _loanProofOutputs);

由此完成了借贷以及结算,同时全部的账目均为保密。

项目进展

AZTEC目前已经在 ethereum mainnet 上线PoC,应用于 DAI 与 AZTEC Token 的转换,即从 DAI 的明文 ERC20 到密文 AZTEC note 的转换。

目前 AZTEC 也可以实现独立密文 Token 的发布和使用,完全基于密文的 Join Split 交易证明。

目前如果是 2 个输入note,2 个输出note,保密交易的情况下,在 ethereum 的 gas 消耗大概是 900,000gas。如果 EIP1108 上线了的话,gas 消耗大约在 200,000 — 300,000gas 之间。

示例项目 step by step 发布至 Ganache

1.下载,git clone https://github.com/AztecProtocol/aztec-ganache-starter-kit.git

2.安装,cd aztec-ganache-starter-kit && yarn install

3.复制 account 环境,cp RENAME_ME.env .env

4.通过 **package.json **的 script,配合.env 中的 account 配置,启动 Ganache,yarn start

5.通过 **package.json **的 script,按照 truffle-config.js 中的内容,配合migrations中的发布文件,编译合约并发布至 Ganache,yarn migrate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
➜  aztec-ganache-starter-kit git:(master) ✗ yarn migrate
yarn run v1.16.0
$ truffle compile --all && truffle migrate --reset

Compiling your contracts...
===========================
> Compiling ./contracts/AceContracts.sol
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/TestERC20.sol
> Compiling @aztec/protocol/contracts/ACE/ACE.sol
> Compiling @aztec/protocol/contracts/ACE/NoteRegistry.sol
> Compiling @aztec/protocol/contracts/ACE/validators/adjustSupply/AdjustSupply.sol
> Compiling @aztec/protocol/contracts/ACE/validators/adjustSupply/AdjustSupplyABIEncoder.sol
> Compiling @aztec/protocol/contracts/ACE/validators/bilateralSwap/BilateralSwap.sol
> Compiling @aztec/protocol/contracts/ACE/validators/bilateralSwap/BilateralSwapABIEncoder.sol
> Compiling @aztec/protocol/contracts/ACE/validators/dividendComputation/DividendComputation.sol
> Compiling @aztec/protocol/contracts/ACE/validators/dividendComputation/DividendComputationABIEncoder.sol
> Compiling @aztec/protocol/contracts/ACE/validators/joinSplit/JoinSplit.sol
> Compiling @aztec/protocol/contracts/ACE/validators/joinSplit/JoinSplitABIEncoder.sol
> Compiling @aztec/protocol/contracts/ACE/validators/privateRange/PrivateRange.sol
> Compiling @aztec/protocol/contracts/ACE/validators/privateRange/PrivateRangeABIEncoder.sol
> Compiling @aztec/protocol/contracts/ERC1724/ZkAsset.sol
> Compiling @aztec/protocol/contracts/ERC1724/ZkAssetMintable.sol
> Compiling @aztec/protocol/contracts/ERC1724/ZkAssetOwnable.sol
> Compiling @aztec/protocol/contracts/ERC20/ERC20Mintable.sol
> Compiling @aztec/protocol/contracts/interfaces/AdjustSupplyInterface.sol
> Compiling @aztec/protocol/contracts/interfaces/DividendComputationInterface.sol
> Compiling @aztec/protocol/contracts/interfaces/IAZTEC.sol
> Compiling @aztec/protocol/contracts/interfaces/IZkAsset.sol
> Compiling @aztec/protocol/contracts/interfaces/JoinSplitInterface.sol
> Compiling @aztec/protocol/contracts/interfaces/PrivateRangeInterface.sol
> Compiling @aztec/protocol/contracts/libs/LibEIP712.sol
> Compiling @aztec/protocol/contracts/libs/NoteUtils.sol
> Compiling @aztec/protocol/contracts/libs/ProofUtils.sol
> Compiling @aztec/protocol/contracts/libs/SafeMath8.sol
> Compiling openzeppelin-solidity/contracts/math/SafeMath.sol
> Compiling openzeppelin-solidity/contracts/ownership/Ownable.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
> Artifacts written to /home/user/Documents/Aztec/aztec-ganache-starter-kit/build/contracts
> Compiled successfully using:
- solc: 0.5.4+commit.9549d8ff.Emscripten.clang


Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.


Starting migrations...
======================
> Network name: 'development'
> Network id: 1564378609369
> Block gas limit: 0x6691b7



1_initial_migration.js
======================

Deploying 'Migrations'
----------------------
> transaction hash: 0x6d94779d277c1f3f02ae8bf1e86ca9c62866f308ccd0834347233d2522ac2306
> Blocks: 0 Seconds: 0
> contract address: 0x31bA6208D85a545C75186c51d0F36B1498Fd70bB
> block number: 1
> block timestamp: 1564379036
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.99580786
> gas used: 209607
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00419214 ETH



> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.00419214 ETH




2_ace.js
========


Deploying 'ACE'
---------------
> transaction hash: 0x249b155829f8a7c069009129d008751e8c6547d39e54b961cb07d80beec13c29
> Blocks: 0 Seconds: 0
> contract address: 0x7BeDb6777e6fFe535Fc444217A80edf349DB8623
> block number: 3
> block timestamp: 1564379036
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.9273801
> gas used: 3379461
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.06758922 ETH



Deploying 'AdjustSupply'
------------------------
> transaction hash: 0xc8c52025eb50204fee60bc65cdb7b7abc09345abff8264e0f88b3f4ec80c54f5
> Blocks: 0 Seconds: 0
> contract address: 0x817888dC24398DEE4A53AB6b247b58C3B22F862c
> block number: 4
> block timestamp: 1564379037
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.9142172
> gas used: 658145
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0131629 ETH




Deploying 'BilateralSwap'
-------------------------
> transaction hash: 0xebc929146741026593580155d9d19844c96f65877eb48faa6e43bad2da812db5
> Blocks: 0 Seconds: 0
> contract address: 0xcD53E73dADB6eaD307892C0aBe0bfE5B2f8f570F
> block number: 5
> block timestamp: 1564379037
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.9055876
> gas used: 431480
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0086296 ETH



Deploying 'JoinSplit'
---------------------
> transaction hash: 0x1fa8ac853d1f6c9306418c07e50f85e3fee1a759ccbe79fa5b035fac0083b00c
> Blocks: 0 Seconds: 0
> contract address: 0x77c76635fdBE43afECa6A12cE8588010Ea6f2E02
> block number: 6
> block timestamp: 1564379037
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.8929998
> gas used: 629390
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0125878 ETH



Deploying 'PrivateRange'
------------------------
> transaction hash: 0x5820bd16d8f9b725f2dcfe965dd7d8dd20e80a763ef1a8e7c2a98c35040d05b0
> Blocks: 0 Seconds: 0
> contract address: 0xe052a2Ab6b49af87265e7d4b245B0AbFE470865b
> block number: 7
> block timestamp: 1564379037
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.88160816
> gas used: 569582
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.01139164 ETH



Deploying 'DividendComputation'
-------------------------------
> transaction hash: 0x6154f1716037db818d98ce0293c6370b84fca6977863ce90a5f736451dca4c68
> Blocks: 0 Seconds: 0
> contract address: 0x36cBFA4f87a3771E92D51F41fa0E32d5Ca65f340
> block number: 8
> block timestamp: 1564379038
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.86990106
> gas used: 585355
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0117071 ETH




> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.12506826 ETH




3_ZkAsset.js
============


Deploying 'TestERC20'
---------------------
> transaction hash: 0x166f81eec89ffc816f12dbcb05a581194125df3ab191fc8025c425cd641509e2
> Blocks: 0 Seconds: 0
> contract address: 0x1fE2f08A5D69e6A886B349bd8c26407C0e3Ef89d
> block number: 16
> block timestamp: 1564379039
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.84888398
> gas used: 629044
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.01258088 ETH



Deploying 'ZkAsset'
-------------------
> transaction hash: 0xba9cbfe6a1c5de0126ff7152f12b0b72812c652ad63daa6604bcefd186180a96
> Blocks: 0 Seconds: 0
> contract address: 0x8B02C67c7175a48e1aBA3067b5F5eEA29a051ECd
> block number: 17
> block timestamp: 1564379039
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.81309922
> gas used: 1789238
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.03578476 ETH



Deploying 'ZkAssetMintable'
---------------------------
> transaction hash: 0xd8d3c7e33af3e7ec5dfdb8e3a0ee5d3928b884011d87035443ab229f5c7a4502
> Blocks: 0 Seconds: 0
> contract address: 0x2E63304e1F9f6AD963540A05D3f385426957A2C7
> block number: 18
> block timestamp: 1564379040
> account: 0x909E433c507A398a5405677B5b2767a3f523F73b
> balance: 999.76265604
> gas used: 2522159
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.05044318 ETH


> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.09880882 ETH



Summary
=======
> Total deployments: 10
> Final cost: 0.22806922 ETH


Done in 41.03s.

第一步 1_initial_migration.js

第二步 2_ace.js。发布 ACE,setCommonReferenceString 方法建立零知识系统的配置文档

await aceContract.setCommonReferenceString(constants.CRS);

通过 ACE 的setProof(proofId, address)方法来设定各个执行证明的合约地址。proofId 为 proof 的类别,从@aztec/dev-utils里面取得定义。address为发布的合约地址

1
2
3
4
5
await aceContract.setProof(MINT_PROOF, AdjustSupply.address);
await aceContract.setProof(BILATERAL_SWAP_PROOF, BilateralSwap.address);
await aceContract.setProof(DIVIDEND_PROOF, DividendComputation.address);
await aceContract.setProof(JOIN_SPLIT_PROOF, JoinSplit.address);
await aceContract.setProof(PRIVATE_RANGE_PROOF, PrivateRange.address);

第三步 3_ZkAsset.js。发布零知识资产(ZkAsset)

1
2
3
4
5
6
7
8
9
// initialise the ZkAsset with an equivilant
await deployer.deploy(
ZkAsset,
aceContract.address,
TestERC20.address,
1,
false,
true
);

此处共计 5 个参数:

1.aceAddress — ACE 的合约地址;

2.linkedTokenAddress — 零知识资产所代表的公开的 ERC20 Token 的合约地址,如不代表特定 Token 则可设定为 address(0);

3.scalingFactor — 是表示与代表的 ERC20 Token 的转换比例,此处为 1:1 转换;

4.canAdjustSupply — owner 是否可以修改 note 的 totalSupply;

5.canConvert — 是否可以将保密 note 转换回到公开的 ERC20 Token

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
➜  aztec-ganache-starter-kit git:(master) ✗ truffle test
Using network 'development'.


Compiling your contracts...
===========================
\> Everything is up to date, there is nothing to compile.


Contract: PrivateVenmo
Bob wants to deposit 100
Bob succesffully deposited 190
Bob takes a taxi, Sally is the driver
The fare comes to 25
Bob paid sally 25 for the taxi and gets 75 back
​ ✓ Bob should be able to deposit 100 then pay sally 25 by splitting notes he owns (5861ms)


1 passing (6s)

测试程序位于test文件夹内。

AZTEC

AZTEC 是一个高效的隐私协议,它运用了零知识证明(zero knowledge proofs)和同台加密(homomorphic encryption)来处理数值,并可对这些密文做特定的逻辑运算。这些密文可以保存在区块链上,对其做零知识证明验证,且不会泄露其明文。

基础概念

AZTEC 中的 note 是被加密的密文,是运算的基础单元,同时遵照了 UTXO 模型。

互操作特性

所有基于 AZTEC 的 digital asset 都基于同一个智能合约—ACE(AZTEC Cryptography Engine)。ACE 主要有两个功能:1)针对指定的 ERC20 Token 合约生成 Proof 证明;2)验证 Proof,并更新 note 的状态。

交易的隐私程度

隐私性: 交易的所有信息不会被第三方得知。

匿名性: 交易内容是公开的,但是交易双方的身份是保密的。

保密性: 交易内容是保密的,单交易双方的身份则是公开的。

AZTEC 提供交易的保密性。但是通过第三方代理行为或者交易方多账户的行为可以实现交易的匿名性,进而实现完全的隐私性。

功能介绍:

目前AZTEC 提供了7个功能:

1.Join Split(转账)

Join Split 证明能将一个或者多个票据结合或者拆分成为一个或者多个票据,并保证输入和输出的票据综合一致。Join Split 也可以将 ERC20 的明文值转换为 AZTEC note 密文,或者将 AZTEC note 密文转回到 ERC20 明文。

2.Bilateral Swap(互换)

Bilateral Swap 证明能让使用者互换票据。例如用来互换代表两种资产的 note。次证明验证甲方提供的note == 乙方要求的note,同时,乙方提供的 note == 甲方要求的 note

3.Dividend

Dividend 能验证:输入 note 的值 == 输出 note 的值 * PublicFactor

次证明通常用来验证收到的利息是否正确。

4.Mint

Mint 证明让可信的使用者能够增加 note 。例如,在转入账户收到稳定币后,产生一个等值的 AZTEC note。

5.Burn

Burn 证明让可信的使用者能够销毁 note。例如,在转出稳定币给到他人后,销毁一个等值的 AZTEC note。

6.Private Range

Private Range 能验证:if note A 的值 > note B 的值。例如,保证某资产小于另一个资产的值。

7.Public Range

Public Range 能验证:if note A 的值 > int 的值。例如,保证某资产小于某门限值。

隐私资产

AZTEC 提出了 EIP 1724 ,旨在讲隐私资产接口标准化。

AZTEC 示例

伪代码:

1
2
3
if (tradeNotional + assetBalance[buyer] < regulatoryMax) {
//交易可以进行的逻辑内容
}

使用 Private Range 证明:

1
2
3
4
5
6
7
const {
proofData,
} = await aztec.proof.privateRange.encodePrivateRangeTransaction({
originalNote: regulatoryMax,
comparisonNote: postTradeUserBalance,
senderAddress: accounts[0],
});

以上生成 comparisonNote 的值小于 originalNote 的规则证明。加下来做规则验证:

1
2
3
4
5
6
(bytes memory _proofOutputs) = ACE.validateProof(
PRIVATE_RANGE_PROOF,
address(this),
_proofData
);
//交易可以进行的逻辑内容