1. 引言
Mina中的account中的字段有:
- 1)public_key:账号的压缩公钥。
- 2)token_id:
- 3)token_permission:Token_permissions.default
- 4)token_symbol:
- 5)amount:即balance。
- 6)nonce:nonce值逐交易递增
- 7)receipt_chain_hash:
- 8)delegate:委托账号的压缩公钥。
- 9)voting_for:对哪个state_hash投票
- 10)timing:Timing.Untimed。
- 11)permission:Permissions.user_default
- 12)zkapp:为Zkapp_account
- 13)zkapp_uri:为String。
{ public_key
; token_id
; token_permissions
; token_symbol
; balance
; nonce
; receipt_chain_hash
; delegate
; voting_for
; timing
; permissions
; zkapp
; zkapp_uri
}
(* Zkapp_account结构体为: *)
type ('app_state, 'vk, 'zkapp_version, 'field, 'slot, 'bool) t =
{ app_state : 'app_state
; verification_key : 'vk
; zkapp_version : 'zkapp_version
; sequence_state : 'field Pickles_types.Vector.Vector_5.Stable.V1.t
; last_sequence_slot : 'slot
; proved_state : 'bool
}
(* Permission.user_default为: *)
let user_default : t =
{ edit_state = Signature
; send = Signature
; receive = None
; set_delegate = Signature
; set_permissions = Signature
; set_verification_key = Signature
; set_zkapp_uri = Signature
; edit_sequence_state = Signature
; set_token_symbol = Signature
; increment_nonce = Signature
; set_voting_for = Signature
}
2. Mina account中的receipt_chain_hash
在account中引入receipt_chain_hash
字段的动机在于:
- Mina为succinct区块链,验证其状态为constant time。由于实现了constant-time lookup,不保留历史交易记录。
在某些情况下,让client证明他们的交易进入区块链是有帮助的。如果client想要证明他们向接收者发送了一大笔钱,这一点尤其有用。
receipt_chain_hash
为该账号发送的所有交易的certificate。假设某账号已发送交易
t
n
⋯
t
1
t_n\cdots t_1
tn⋯t1,
p
n
⋯
p
1
p_n\cdots p_1
pn⋯p1为这些交易的payload hash,则其receipt_chain_hash
r
n
r_n
rn为:
r
n
=
H
(
p
n
,
H
(
p
n
−
1
,
⋯
)
)
=
H
(
p
n
,
r
n
−
1
)
r_n=H(p_n,H(p_{n-1},\cdots))=H(p_n,r_{n-1})
rn=H(pn,H(pn−1,⋯))=H(pn,rn−1)
其中
H
H
H为哈希函数。
初始状态,
r
0
=
r_0=
r0=Receipt.Chain_hash.empty
为the empty hash for receipt_chain_hash
。【let empty = of_hash Random_oracle.(salt “CodaReceiptEmpty” |> digest)】
若client存储了
r
k
⋯
r
n
r_k\cdots r_n
rk⋯rn,则可证明其发送了交易
t
k
t_k
tk。因为任何Verifier都可查询链上的当前状态,检查receipt_chain_hash
等于
r
n
r_n
rn,然后递归验证
r
i
=
H
(
t
i
,
r
i
−
1
)
r_i=H(t_i,r_{i-1})
ri=H(ti,ri−1)从
i
=
2
开
始
,
直
到
i
=
k
为
止
i=2开始,直到i=k为止
i=2开始,直到i=k为止。
也就是说,client需要存储所有的交易和receipt chain hash值,当client与Mina网络断开时,也必须保存这些数据。与此同时,client需要很容易根据这些交易和receipt chain hash值来获得链的当前状态——通过key-value数据库很容易实现,key为receipt chain hash值,value具有如下字段:
type value = Root | Child of {parent: receipt_chain_hash; value: transaction}
prove过程会提供a merkle list of [ ( t 1 , r 1 ) , ⋯ , ( t k , r k ) ] [(t_1,r_1),\cdots,(t_k,r_k)] [(t1,r1),⋯,(tk,rk)],其中 r i = H ( t i , r i − 1 ) r_i=H(t_i,r_{i-1}) ri=H(ti,ri−1) for i = 2 ⋯ k i=2\cdots k i=2⋯k。
这种设计的缺陷在于:
- 1)为了证明其发送了某笔交易,client需记录其发送的所有交易。对于发送多笔交易的用户来说不可行。且证明的复杂度为 O ( n ) O(n) O(n), n n n为其已发送的交易数。
- 2)假定了a peer会通过同一机器发送交易。当a node在多台机器发送交易时,可将这些机器同步并共享其发送的交易。
对于用户来说,实现这种同步的最简单方案是在云数据库中存储其数据。用户也可在本地以cache形式存储其数据。
参考资料
[1] Mina rfcs 0006-receipt-chain-proving.md
附录1. Mina系列博客
Mina系列博客有:
- Mina概览
- Mina的支付流程
- Mina的zkApp
- Mina中的Pasta(Pallas和Vesta)曲线
- Mina中的Schnorr signature
- Mina中的Pickles SNARK
- Mina中的Kimchi SNARK
- Mina Kimchi SNARK 代码解析
- Mina Berkeley QANet测试网zkApp初体验
- Mina中的Poseidon hash
- Mina中的多项式承诺方案
- Recursive SNARKs总览
- Mina技术白皮书
- Mina代码解析
- Mina中的Snark Worker
- Mina中的Scan State
- Mina中的VRF
- Mina中的delta_transition_chain_proof/delta_block_chain_proof