Filecoin源码上线10天了。相信各位爱好者们已经做了各种尝试:安装分析、下单接单、申请代币、挖矿等等。我的一个体会是,现在整个系统还比较初级,但已经能够看出雏形,在测试网上钱和正式网上线前必然还会有大的改动。敬请期待。
Filecoin的存储封印(Sealing)和证明(PoRep & PoSt)是用rust语言编写,而且是单独成篇的,也就是说可以单独拿出来玩。协议实验室希望大家群策群力,通过一个比赛的方式,来得到新的想法,获得测试数据,以便于进一步改进。这个你玩了吗?这部分是最有趣的也是最难的部分。本文进行一个初步的解析,供探讨。
程序一览
Filecoin复制游戏程序的源码可以到以下地址下载:
https://github.com/filecoin-project/replication-game
如果你不想下载源码,直接下载可执行代码的话,直接到这里:
https://github.com/filecoin-project/rust-fil-proofs/releases
下载完毕,解压,得到如下目录结构和程序:
这里分别介绍一下各个程序的功能:
libfilecoin_proofs.a : 用于存储证明的一个静态库
libfilecoin_proofs.h : 与上面静态库相对应的c语言头文件
libfilecoin_proofs.pc : 一个pkg-config 清单,用来说明依赖关系
paramcache : 用来产生Groth 参数文件,用于后续封印和证明用,默认情况下,参数文件会保存在 /tmp/filecoin-proof-parameters
paramfetch : 用来从IPFS网管获取 Groth参数文件
**parameters.json **: 包含最新的 Groth 参数文件信息的列表 (当前包含两个,分别对应256M和1K)
Groth 参数
什么叫 Groth 参数?这个是封印和证明过程中需要用到的,属于零知识证明算法中需要用到的数据,具体可以参考【1】,Groth是作者之一。
rust-fil-proofs 是 filecoin 的一部分,相信大家在安装 filecoin 的时候已经注意到 rust_fil_proofs的安装过程,可以自动也可以手动。在我的前一篇文档中特别提到到分解安装的步骤,其中安装依赖包的后三步是用来安装和准备 rust_fil_proofs 环境的。其中有下面的这个脚本:
install-rust-proofs.sh
另外有两个环境变量可以使用:FILECOIN_USE_PRECOMPILED_RUST_PROOFS 和 GITHUB_TOKEN。如果设置了这两个环境变量,脚本会自动判断是否参数已经存在(通过SHA比较来判断),如果没有,则通过 cURL 下载,如果不能下载则本地编译生成。
这里用到两个程序:paramfetch 和 paramcache。paramfetch 程序通过 IPFS 网络下载 Groth 参数,而 paramcache 在本地生成。
当在存储证明期间,也即是在做 RoRep (复制证明) 和 PoSt(时空证明)时,rust-fil-proofs 会访问 Groth 参数来生成结果。
RoSt 和 PoRep 现状
1.PoRep
在当前的开发者网络中,使用的是 Zigzag 复制证明算法。无论是持续运行的 devnet-user,或者是每天更换的 nightly 网络都是如此。协议实验室也在考虑其他算法,可能使用某些累积运算模式。最终方案将于近期作出结论。
2.PoSt
而时空证明,采用的是VDF PoSt (Verifiable Delay Function Proof of Spacetime) 。目前工作没有完成,当然在 go-filecoin 里面也就没有相关证明。实际上,其中还有一些理论问题亟待解决。
目前,协议实验室在考虑即使半成品,可集成进系统之中进行测试优化。但是,问题没有那么简单。有些事情必须考虑,比如:
当做存储证明的时候,Challenge要求是完全随机的,或者需要其种子是随机的,但如何在区块链领域中产生随机数是一个问题
如何使得 VDF PoSt能够支持可变的扇区数来提供证明,目前支持2个扇区。这也涉及到 go-filecoin 代码修改。
使用小的扇区大小进行测试
大家可能已经注意到,在devnet-user网络中,扇区大小是256M,十分巨大,而且耗时;而在nightly网络中,为了节省开发者的时间,扇区大小设置为 1K,小太多了。运行起来就快得多。但到底多大的扇区是合适的,这个目前没有定论。只能经过更多的测试,也许测试网或正式网络会根据大家的反馈设定一个与当前完全不同的数值。
当前 rust-fil-proofs 实际上支持一个配置参数,来设定不同的扇区尺寸。而这个参数取值为 “Live“ 或 “Test" 二者之一。
当系统的环境变量 FIL_USE_SMALL_SECTORS 设置为 true 时, go-filecoin 就会参数 Test 到 rust-fil-proofs,这样,rust-fil-proofs就会使用1Kbytes的扇区大小;否则,扇区大小就是 256M。
那么,你必须考虑你的证明方式必须与你连接的网络相适应,因此,当你初始化和连接到 nightly 网络的时候,请设置上述环境变量;但如果你是连接到 user 网络,则不需要。
go-filecoin 如何与 rust-fil-proofs 交互
rust-fil-proofs 的算法是一方面,当然整体需要有一个架构支撑,这个架构就是 Sector Base。Sector Base主要实现接口,任务调度,以及扇区的关系和管理,包括但不限于:
写入(预处理)用户数据块到磁盘
布置和调度封印(复制证明)相关人物
布置和调度时空证明生成任务
布置和调度解封(用于检索)任务
为时空证明和复制证明验证提供接口(在FIL状态机内调用)
在复制拷贝和封印扇区之间建立映射
在数据指纹(base-58 或者 base-58BTC 编码的 CID)和封印扇区之间建立映射
go-filecoin 代码与 rust-fil-proofs 之间的交互主要包含两个Go语言接口:
type Verifier interface {
VerifyPoST(VerifyPoSTRequest) (VerifyPoSTResponse, error)
VerifySeal(VerifySealRequest) (VerifySealResponse, error)
}
type SectorBuilder interface {
AddPiece(ctx context.Context, pi *PieceInfo) (sectorID uint64, err error)
ReadPieceFromSealedSector(pieceCid cid.Cid) (io.Reader, error)
SealAllStagedSectors(ctx context.Context) error
SectorSealResults() <-chan SectorSealResult
GetMaxUserBytesPerStagedSector() (uint64, error)
GeneratePoST(GeneratePoSTRequest) (GeneratePoSTResponse, error)
Close() error
}
Verifier 接口在 RustVerifier 结构中被定义;SectorBuilder 接口在 SectorBuilder 结构中被定义。这两个结构通过 CGO 可以直接调用 rust 代码。
近期可能的改进
可以看出,关于存储证明时空证明还有大量的工作要做。这一块绝对是一块硬骨头,需要花大量的精力。这不可能是在几个星期之内就完成的。但我们期待,随着时间的推移,能够逐步看到进展。近期来看,也许可以期待如下进展:
PoSt 代码集成进 go-filecoin,即使目前还是半成品
考虑 PoSt 和 PoRep 可配置的方案
从性能的角度考虑,go-filecoin在时间和空间上的平衡 - 扇区大小和证明的快慢?
支持多种扇区大小?不同扇区大小意味着不同的 Groth 参数,因此不可能是随意的。
参考:
【1】 Efficient Zero-Knowledge Argument for Correctness of a Shuffle, Stephanie Bayer & Jens Groth, 2012
【2】 Tight Proofs of Space and Replication, Ben Fisch, 201807
【3】 Proofs of Replicated Storage Without Timing Assumptions, Ivan Damg ̊ard, Chaya Ganesh, and Claudio Orlandi, 2018