在Filecoin的存储逻辑中,需要使用2种证明机制,来证明矿机正确的存储了数据的多个备份并且能够被任意的人在任意时刻检验数据的有效性,只有满足这两个条件,才能说明存储矿机安全可靠的存储了这些数据。
Proof-of-Replication:简称PoRep协议,解决了在数据上传初期,矿机证明自己生成了适当的数据备份,并保存在相对独立的存储设备上的问题。
Proof-of-Spacetime:简称PoSt协议,检查矿机是否仍然存储某个数据的备份,最直接的办法就是定期检查矿机的存储数据,这样可以保证矿机在检查点忠实的存储了用户的数据,但是这样会造成复杂的交互过程,并且会成为系统的瓶颈,因此通过PoSt协议,可以在无交互的情况下检查矿机的存储情况。
这些协议的具体实现,依赖于zk-NSARKs机制即零知识证明机制,这个我们在前面的几个章节中进行了详细的论证,有兴趣的同学可以翻一下前几节,我们本节重点讨论在已知此机制可用的情况下,Filecoin是如何实现数据的存储以及存储的校验。
PoRep协议:
SEAL(封装)操作:
用户将数据发送给矿机之后,矿机需要根据SEAL方法来存储数据,这个过程是为了保证诚实的矿机把数据存储独立的N份并且保证有足够的时间允许检查者生成检查的Challenge。
1, Setup:
输入:
prover key pair (pkP , skP ) 矿机的钥匙对
prover SEAL key pkSEAL 数据封装产生的公钥
data D :用户提供的数据。
输出:
replica R, 数据D的一个副本
Merkle root rt of R, 副本的hash树根
Proof πSEAL 副本存储证明
过程:
1) 计算数据的hash值 hD := CRH(D)
2) 封装数据 R:=Sealτ(D,skP)
3) 计算副本的hash树根 rt := MerkleCRH(R)
4) 令 ⃗x := (pkP,hD,rt)
5) 令 w⃗ := (skP,D)
6) 计算副本的存储证明 πSEAL := SCIP.Prove(pkSEAL , ⃗x , w⃗ )
7) 输出结果 R, rt, πSEAL
2,Prove:
输入:
prover Proof-of-Storage key pkPOS 数据存储公钥
replica R 数据副本
random challenge c 检查者发出的一个随机数,代表副本hash树的某个野子节点的下标
输出:
πPOS,存储的证明
过程:
1) 计算副本数据的hash树根 rt := MerkleCRH(R)
2) 从Rc到数个rt的路径 path := Merkle path from rt to leaf Rc
3) 令 ⃗x := (rt, c)
4) 令 w⃗ :=(path,Rc)
5) 计算一个存储证明 πPOS := SCIP.Prove(pkPOS , ⃗x , w⃗ )
6) 输出存储证明πPOS
3,Verify:
输入:
prover public key, pkP 矿机的公钥
verifier SEAL and POS keys vkSEAL, vkPOS – hash of data D, hD 数据和数据的hash值,数据封装的验证用公钥和存储用公钥
Merkle root of replica R, rt 副本数据的hash树根
random challenge, c 用来检查矿机的,数据副本hash树叶索引
tuple of proofs, (πSEAL, πPOS),存储证明和封装证明
输出:
bit b, 如果是1表示验证通过
过程:
1)令x⃗1 :=(pkP,hD,rt)
2) 计算数据封装的有效性b1 := SCIP.Verify(vkSEAL,x⃗1 ,πSEAL)
3)令x⃗2 :=(rt,c)
4) 计算数据存储的有效性b2 := SCIP.Verify(vkPOS,x⃗2 ,πPOS)
5) 输出检验结果 b1 ∧ b2
PoSt协议:
1,Setup:
输入:
prover key pair (pkP , skP ) 矿机的钥匙对
prover POST key pair pkPOST 存储时空公钥
data D 数据
输出:
replica R, 数据的副本
Merkle root rt of R, 数据副本的hash树根
Proof πSEAL 数据的封装证明
过程:
1) 封装数据,生成数据副本,副本的hash树根和封装证明
R, rt, πSEAL := PoRep.Setup(pkP,
skP , pkSEAL, D)
2) 输出封装结果 R, rt, πSEAL
2,Prove:
输入:
prover PoSt key pkPOST 矿机的数据时空公钥
replica R 数据副本
random challenge c – time parameter t 检查者定期检查的检查次数
输出:
数据的时空证明 πPOST,即证明在某一时刻对某一数据进行了有效的存储
过程:
1) 令 πPOST := ⊥
2) 计算数据副本的hash树根 rt := MerkleCRH(R)
3) 设置循环次数 i = 0...t:
a) 令c′ := CRH(πPOST||c||i)
b) 计算数据存储证明 πPOS := PoRep.Prove(pkPOS, R, c′)
c) 令 ⃗x := (rt, c, i)
d) 令 w⃗ := (πPOS,πPOST)
e) 计算数据的时空证明πPOST := SCIP.Prove(pkPOST , ⃗x , w⃗ )
4) 输出证明πPOST
3,Verify:
输入:
prover public key pkP 矿机的公钥
verifier SEAL and POST keys vkSEAL, vkPOST – hash of some data hD 数据的封装证明公钥,存储时空证明公钥,要检查的数据及数据的hash值
Merkle root of some replica rt 部分副本的hash树根
random challenge c 随机选择的hash树叶节点
time parameter t 循环检查次数
tuple of proofs (πSEAL, πPOST) 封装证明和数据时空证明
输出:
bit b, 检查是否通过
过程:
1)令x⃗1 :=(pkP,hD,rt)
2) 计算封装证明是否有效b1 := SCIP.Verify(vkSEAL,x⃗1 ,πSEAL)
3)令x⃗2 :=(rt,c,t)
4) 计算数据时空证明是否有效b2 := SCIP.Verify(vkPOST,x⃗2 ,πPOST)
5) 输入检查结果b1 ∧ b2