24个稳定版本 (11个主要版本)
11.1.0 | 2024年6月18日 |
---|---|
10.0.0 | 2024年4月25日 |
9.1.0 | 2023年11月8日 |
8.0.0 | 2023年6月30日 |
0.2.0 | 2021年3月9日 |
#12 in #tooling
5,504 monthly downloads
用于 35 个crate (5个直接)
59KB
748 行
Filecoin证明子系统
Filecoin证明子系统 (或FPS) 提供Filecoin协议所需的存储证明。它完全使用Rust编写,作为一系列部分相互依赖的crate — 其中一些导出支持API的C绑定。
目前有几个不同的crate
-
存储证明核心 (
storage-proofs-core
) 一组在其他存储证明子crate中使用的通用原语,包括加密、Merkle树、哈希和gadget接口。 -
存储证明PoRep (
storage-proofs-porep
)storage-proofs-porep
旨在作为证明复制 (PoRep)的参考实现,同时为filecoin-proofs
执行繁重的工作。主要组件
- PoR (可检索证明: Merkle包含证明)
- DrgPoRep (深度鲁棒图 证明复制)
- StackedDrgPoRep
-
存储证明PoSt (
storage-proofs-post
)storage-proofs-post
旨在作为空间时间证明 (PoSt)的参考实现,用于filecoin-proofs
。主要组件
- PoSt (空间时间证明)
-
Filecoin Proofs (
filecoin-proofs
) 此处包含Filecoin特定的设置参数值。API被封装在rust-filecoin-proofs-api
中,然后它是filecoin-ffi
中FFI导出的API的基础,该API可以从C(实际上通过 lotus 通过cgo调用)调用。
这些crate之间的依赖关系如下所示
┌────────────────────────────────────────────────────────────────────┐
│ filecoin-proofs │
└─────┬────────────────────────────┬──────────────┬─────────────┬────┘
│ │ │ │
│ │ │ │
│ │ │ │
┌────────────▼──────────┐ ┌───────────▼──────────┐ │ ┌─────────▼───────────┐
│ storage-proofs-update ├─────▶ storage-proofs-porep │ │ │ storage-proofs-post │
└────────────┬──────────┘ └───────────┬──────────┘ │ └─────────┬───────────┘
│ │ │ │
│ │ │ │
│ │ │ │
┌─────▼────────────────────────────▼──────────────▼─────────────▼────┐
│ storage-proofs-core │
└────────────────────────────────────────────────────────────────────┘
crates之间共享的内容应放入 storage-proofs-core
。例外的是 storage-proofs-update
,它需要来自 storage-proofs-porep
的堆叠DRG。所有crate都可以自由使用工作区中的其他crate,例如 filecoin-hashers
或 fr32
。
安全审计
rust-fil-proofs
证明代码和 Filecoin规范 已经过由 Sigma Prime 执行的 证明安全审计,并被认为没有 关键 或 重大 安全问题。除了安全审查外,该文档还提供了发现摘要、漏洞分类和推荐解决方案。迄今为止,已解决代码和规范中的所有已知问题。
rust-fil-proofs
还经过由 Dr. Jean-Philippe Aumasson 和 Antony Vennard 执行的 SNARK证明安全审计,并被认为没有 关键 或 重大 安全问题。除了安全分析外,该文档还提供了审计目标、方法、功能描述以及最终关于可改进之处的观察。迄今为止,已解决所有已知问题。
设计说明
在设计过程的早期,我们考虑了在Go中实现成为FPS的方案——作为围绕多个SNARK电路库的包装器。我们最终决定使用 bellman——一个由Zcash开发的库,该库支持SNARK中的高效pedersen散列。做出这个决定后,在Rust中实现整个子系统既自然又高效。我们考虑了作为更大决策的一部分的收益(自包含的代码库、能够在层之间依赖静态类型)和成本(开发者学习曲线、有时借用检查器的难以控制),并确定整体项目的收益(特别是能够构建在Zcash的工作上)超过了成本。
我们还考虑了FPS是否应作为独立二进制文件实现,从Filecoin节点访问,作为单次调用的CLI或作为长时间运行的守护进程。将FPS作为FFI依赖项打包是为了简化将Filecoin节点作为单个单一的二进制文件交付,以及(感知的)相对简单的API实现开发。
如果在任何时候清楚FFI方法不可挽回地有问题,那么移动到独立FPS的选项仍然存在。然而,与从Go调用Rust相关的绝大多数技术问题现在都已解决,即使在允许高程度运行时配置的同时。因此,继续沿着我们已经投资并开始获得回报的同一条道路似乎很合理。
安装和配置Rust
注意: 如果你意外地将 rust-fil-proofs
作为 lotus
的子模块安装,那么你可能已经安装了 Rust。
以下说明假设你已独立安装 rust-fil-proofs
以进行测试、开发或实验。
构建
注意: rust-fil-proofs
仅能在 64 位平台上构建和运行;如果目标架构不是 64 位,构建将导致 panic。
在构建之前,您需要安装 OpenCL。在 Ubuntu 上,可以使用以下命令实现:apt install ocl-icd-opencl-dev
。其他系统依赖项,如 'gcc/clang'、'wall' 和 'cmake' 也需要。
对于 multicore sdr
功能(默认启用),您还需要安装 hwloc
库。在 Ubuntu 上,可以使用以下命令实现:apt install hwloc libhwloc-dev
。对于其他平台,请参阅 hwloc-rs 先决条件部分。
> cargo build --release --all
hwloc
依赖项是可选的,可以禁用。禁用它将不允许使用 multicore sdr
功能。默认情况下,回退到单核复制,除非有其他指定。
要禁用 multicore sdr
以使 hwloc
不需要,您可以像这样构建证明
> cargo build --release --all --no-default-features --features opencl
请注意,multicore-sdr
功能被省略在指定的功能列表中,这将从默认情况下移除其使用。
在 cuda
功能(默认禁用)之后存在对 CUDA 的实验性支持。您需要安装 nvcc
。在 Ubuntu 上,可以使用以下命令实现:apt install nvidia-cuda-toolkit
。要启用 CUDA 支持,您可以像这样构建证明
> cargo build --release --all --features cuda
现在它将同时构建具有 CUDA 和 OpenCL 支持的版本,在运行时将优先选择 CUDA,但可以通过 FIL_PROOFS_GPU_FRAMEWORK
环境变量禁用它(有关更多信息,请参阅下面的 GPU 使用
部分)。
为 Arm64 构建编译
为了为 arm64 构建编译,当前的要求是
- nightly rust 编译器
构建 filecoin-proofs
的示例
$ rustup +nightly target add aarch64-unknown-linux-gnu
$ cargo +nightly build -p filecoin-proofs --release --target aarch64-unknown-linux-gnu
测试
> cargo test --all
基准测试
主要的基准测试工具称为 benchy
。 benchy
有几个子命令,包括 merkleproofs
、prodbench
、winning_post
、window_post
和 window_post_fake
(使用假密封以实现更快的基准测试)。请注意,现在 winning_post
有一个 --fake
选项,也可以运行假密封以实现更快的基准测试。您可以使用各种配置选项运行它们,但以下是一些示例
> cargo run --release --bin benchy -- merkleproofs --size 2KiB
> cargo run --release --bin benchy -- winning-post --size 2KiB
> cargo run --release --bin benchy -- winning-post --size 2KiB --fake
> cargo run --release --bin benchy -- window-post --size 2KiB
> cargo run --release --bin benchy -- window-post-fake --size 2KiB --fake
> cargo run --release --bin benchy -- prodbench
#
# Synthetic PoRep examples (for both 2KiB test and 32GiB production sector sizes)
#
# Preserve a cache using synthetic-porep (2KiB sectors)
> cargo run --release --bin benchy -- porep --size 2KiB --cache /tmp/cache-2k-synthetic --preserve-cache --api-features synthetic-porep
# Preserve a cache using synthetic-porep (32GiB sectors)
> cargo run --release --bin benchy -- porep --size 32GiB --cache /tmp/cache-32g-synthetic --preserve-cache --api-features synthetic-porep
#
# After a preserved cache is generated, this command tests *only* synthetic proof generation (2KiB sectors)
> cargo run --release --bin benchy -- porep --size 2KiB --cache /tmp/cache-2k-synthetic --api-features synthetic-porep --skip-precommit-phase1 --skip-precommit-phase2 --skip-commit-phase1 --skip-commit-phase2
# After a preserved cache is generated, this command tests *only* synthetic proof generation (32GiB sectors)
> cargo run --release --bin benchy -- porep --size 32GiB --cache /tmp/cache-32g-synthetic --api-features synthetic-porep --skip-precommit-phase1 --skip-precommit-phase2 --skip-commit-phase1 --skip-commit-phase2
Window PoSt 基准测试用法
Window PoSt 基准测试可以用多种方式使用,其中一些在下面详细介绍。
首先,您可以像这样运行基准测试并保留工作目录
cargo run --release --bin benchy -- window-post --size 2KiB --cache window-post-2KiB-dir --preserve-cache
然后,如果您想再次运行基准测试以测试 commit-phase2,您可以快速运行它
cargo run --release --bin benchy -- window-post --size 2KiB --skip-precommit-phase1 --skip-precommit-phase2 --skip-commit-phase1 --cache window-post-2KiB-dir
或者,如果您只想测试 GPU 树构建,您可以像这样运行它
cargo run --release --bin benchy -- window-post --size 2KiB --skip-precommit-phase1 --skip-commit-phase1 --skip-commit-phase2 --cache window-post-2KiB-dir
请注意,某些参数组合会导致对您的缓存目录进行破坏性更改。对于更大的基准测试扇区大小,建议一旦创建初始缓存,就将其保存到其他位置,以防测试运行损坏。例如,以下运行序列将保证损坏您的缓存
# Do NOT run this sequence. For illustrative purposes only:
# Generate clean cache
cargo run --release --bin benchy -- window-post --size 2KiB --cache window-post-2KiB-dir --preserve-cache
# Skip all stages except the first
cargo run --release --bin benchy -- window-post --size 2KiB --skip-precommit-phase2 --skip-commit-phase1 --skip-commit-phase2 --cache broken-cache-dir
这个失败的原因是,在第一步中生成新的随机片段数据(而不是从之前的运行中从磁盘加载),然后在后续的密封步骤中尝试使用它,使用之前保留的运行中的数据。这是无法工作的。
还有一个名为 gpu-cpu-test
的基准测试。
> cargo run --release --bin gpu-cpu-test
一些结果会在命令行中显示,或者作为 JSON 文件写入。可以使用 RUST_LOG=trace
选项启用记录(在下文中的 Logging
部分查看更多记录选项)。
注意:在 macOS 上,您需要 gtime
(使用 brew install gnu-time
安装),因为内置的 time
命令不足以使用。
记录
为了在错误时获得更好的记录和回溯,开发人员应该在 Result<T, E>
和 Option<T>
上使用 expects
而不是 expect
。
该软件包使用 log
进行记录,默认情况下不记录任何内容。为了记录输出,可以使用如 fil_logger
这样的记录软件包。
例如
fn main() {
fil_logger::init();
}
然后当运行代码设置
> RUST_LOG=filecoin_proofs=info
将启用所有记录。
对于高级/详细/调试记录,您可以使用以下代码设置
> RUST_LOG=trace
设置
在本 README 的后面部分,描述了可以由最终用户调整的各种设置。这些设置总结在 rust-fil-proofs.config.toml.sample
中,并且如果将其复制到 ./rust-fil-proofs.config.toml
,则可以直接使用此配置文件。或者,可以使用形式为 "FIL_PROOFS_" 的环境变量设置每个设置(全部大写)。例如,要将 rows_to_discard
设置为 2,您需要在您的环境中设置 FIL_PROOFS_ROWS_TO_DISCARD=2
。
未指定任何配置设置已选择合理的默认值。
要验证当前的环境设置,您可以运行
cargo run --bin settings
参数文件位置
期望 Filecoin 证明参数文件位于 /var/tmp/filecoin-proof-parameters
。如果它们位于其他位置,您可以使用环境变量将系统指向该位置。
FIL_PROOFS_PARAMETER_CACHE=/path/to/parameters
如果您正在运行一个预期使用生产参数(即在存储库中 parameters.json
文件中指定的参数)的节点,您可以可选地使用环境变量验证您的磁盘参数
FIL_PROOFS_VERIFY_PRODUCTION_PARAMS=1
默认情况下,此验证是禁用的。
在复制过程中优化速度或内存
在复制和同时生成证明的 Merkle 树(MT)时,始终需要考虑时间-内存权衡,我们在这里提供了一种在牺牲另一项的同时优化一项的策略。
速度
复制过程中计算量最大的一项操作(除了编码本身)是在堆叠图中生成(扩展)父级的索引,通过 Feistel 密码(用作伪随机排列)实现。为了减少该时间,我们提供了一个缓存机制,只需生成一次并在复制过程中(在不同层之间)重用它们。
FIL_PROOFS_SDR_PARENTS_CACHE_SIZE=2048
此值默认为2048个节点,相当于112KiB的常驻内存(其中每个缓存的节点由DEGREE(基本值+指数=6+8)x 4字节元素组成,长度为56字节)。鉴于缓存现在位于磁盘上,当以与此变量相关的窗口大小访问时,它将被内存映射。此默认设置是为了最小化内存使用,同时仍然允许高效地访问缓存。如果您想尝试其他大小,可以修改环境变量
增加此值将增加使用的常驻RAM量。
最后,父缓存数据默认位于/var/tmp/filecoin-parents
磁盘上。要修改此位置,请使用环境变量
FIL_PROOFS_PARENT_CACHE=/path/to/parent/cache
根据以上设置,缓存数据将位于/path/to/parent/cache/filecoin-parents
。
或者,使用FIL_PROOFS_CACHE_DIR = /path/to/parent/cache
,其中父缓存将位于$FIL_PROOFS_CACHE_DIR/filecoin-parents
。请注意,如果您使用FIL_PROOFS_CACHE_DIR
,它必须通过环境设置,而不能通过配置文件设置。如果同时指定了FIL_PROOFS_PARENT_CACHE
,则此设置不起作用。
如果您担心磁盘上的父缓存文件完整性,可以在第一次访问时使用环境变量进行验证
FIL_PROOFS_VERIFY_CACHE=1
如果它们不一致(与存储在storage-proofs/porep/parent-cache.json中的清单比较),它们将在运行时自动重新生成。如果缓存生成失败,将报告为错误。
FIL_PROOFS_USE_MULTICORE_SDR
当仅使用单个核心执行SDR复制(预提交阶段1)时,获取节点父级的内存访问是瓶颈。多核心SDR使用多个核心(应限制为单个核心复杂以共享缓存)来组装每个节点的父级并执行一些预哈希。此设置默认不启用,但可以通过设置FIL_PROOFS_USE_MULTICORE_SDR = 1
来激活。
当可以锁定内存映射的页面时,也将实现最佳性能。这可以通过以非root用户运行进程并使用ulimit -l
增加系统最大锁定内存限制来实现。或者,如果其总锁定页面可以适应物理内存,则可以以root身份运行进程。否则,可能会调用OOM-killer。必须锁定两个扇区大小的数据(对于当前和之前层),以及56 * FIL_PROOFS_PARENT_CACHE_SIZE字节的父缓存。
默认参数已经调整以在AMD Ryzen Threadripper 3970x上提供良好的性能。在硬件不同的情况下,尝试这些参数可能很有用。我们已尽力使用合理的启发式方法,并确保在一系列配置和硬件上具有合理的性能,但除了我们的目标之外,多核心复制的实际性能或行为尚未经过充分测试。以下设置可能很有用,但请预期在寻找良好参数的过程中可能会出现一些失败。这可能表现为失败的复制(坏的证明)、复制过程中的错误,甚至可能是参数病理化时的潜在崩溃。目前,这是一个实验性功能,并且除了默认硬件(3970x)上的默认配置之外,尚未知道其他配置可以很好地工作。
FIL_PROOFS_MULTICORE_SDR_PRODUCERS
:这是并行加载节点父级的工线程数量。默认值是3
,因此生产者和主线程一起使用完整的核心复杂度(但不再增加)。FIL_PROOFS_MULTICORE_SDR_PRODUCER_STRIDE
:这是生产者在循环的每次迭代中加载父级节点的(最大)数量。默认值是128
。 FIL_PROOFS_MULTICORE_SDR_LOOKAHEAD
:这是生产线程预先加载节点父级的预览缓冲区的大小。默认值是800。
GPU使用情况
可以使用GPU构建列哈希树'tree_c',与CPU相比,可以显著提高速度。要激活GPU,请使用环境变量
FIL_PROOFS_USE_GPU_COLUMN_BUILDER=1
同样,'tree_r_last'树也可以使用GPU构建,这至少可以提供CPU 2倍的速度提升。要激活GPU,请使用环境变量
FIL_PROOFS_USE_GPU_TREE_BUILDER=1
请注意,如果可用支持GPU,则可以并且应该启用这两个GPU选项。
高级GPU使用
当使用GPU构建'tree_r_last'时(使用FIL_PROOFS_USE_GPU_TREE_BUILDER=1
),可以测试一个实验性变量以对您的硬件进行本地优化。
FIL_PROOFS_MAX_GPU_TREE_BATCH_SIZE=Z
默认的批次大小值是700,000个树节点。
当使用GPU构建'tree_c'时(使用FIL_PROOFS_USE_GPU_COLUMN_BUILDER=1
),可以测试两个实验性变量以对您的硬件进行本地优化。首先,您可以设置
FIL_PROOFS_MAX_GPU_COLUMN_BATCH_SIZE=X
此值的默认值为400,000,这意味着我们一次性编译400,000列,并将它们分批传递给GPU。每一列是一个“单个节点 x 层数”(例如,32GiB扇区有11层,因此每一列由11个节点组成)。此值既是一个合理的默认值,也测量到编译此大小批次所需的时间与GPU消耗它所需的时间大致相同(使用2080ti进行测试),我们并行执行以最大化吞吐量。如果设置过大,则可能会耗尽GPU RAM;如果设置过低,则可能会降低性能。此设置在此步骤中提供供您实验。
可能影响整体'tree_c'性能的第二个变量是存储从GPU返回的树数据时的并行写入缓冲区的大小。此值设置为合理的默认值262,144,但您可以根据需要调整它,如果可以从中获得个别性能提升。要调整此值,请使用环境变量
FIL_PROOFS_COLUMN_WRITE_BATCH_SIZE=Y
请注意,此值会影响持久化列树到磁盘时使用的并行度程度,如果未适当调整限制,可能会耗尽系统文件描述符(例如,使用ulimit -n
)。如果由于“无效文件描述符”错误而无法持久化树,请尝试将此值调整得更大(例如,524288或1048576)。增加此值会一次处理更大的块,从而导致并行磁盘写入更大(但更少)。
当库使用CUDA和OpenCL支持构建时,您可以在运行时选择使用哪一个。使用环境变量
FIL_PROOFS_GPU_FRAMEWORK=cuda
您可以将它设置为opencl
以使用OpenCL。默认值是cuda
,当您不设置或设置任何其他(无效)值时。
CUDA内核在编译和构建时。默认情况下,它们是为最新的架构构建的,例如Turing(sm_75
)和Ampere(sm_80
、sm_86
)。这会增加整体构建时间几分钟。您可以通过只为所需的特定架构编译来减少它。例如,如果您只需CUDA内核在Turing架构上工作,您可以将所有使用CUDA内核的依赖项设置。
BELLMAN_CUDA_NVCC_ARGS="--fatbin --gpu-architecture=sm_75 --generate-code=arch=compute_75,code=sm_75"
NEPTUNE_CUDA_NVCC_ARGS="--fatbin --gpu-architecture=sm_75 --generate-code=arch=compute_75,code=sm_75"
内存
目前默认配置设置为尽可能减少内存消耗,因此用户方面没有太多可以做的。我们现在将Merkle树存储在磁盘上,这是内存消耗的主要来源。您应该预期最大RSS在1-2个扇区大小之间,如果您遇到超出此范围的峰值,请报告问题(您可以使用/usr/bin/time -v
命令检查最大RSS)。
高级存储调整
关于在磁盘上持久化的缓存Merkle树'tree_r_last',提供了一个值来调整所需的存储空间量。缓存的Merkle树就像正常的Merkle树一样,除了我们丢弃了从基本级别以上的某些行。丢弃太多数据会导致在需要时几乎重新构建整个树,这是一个权衡。另一种极端是丢弃太少行,这会导致磁盘空间利用率更高。默认值被选择以仔细平衡这种权衡,但您可以根据本地硬件配置的需要进行调整。要调整此值,请使用环境变量。
FIL_PROOFS_ROWS_TO_DISCARD=N
请注意,如果您修改此值并使用它来密封扇区,则无法在不更新所有先前密封的扇区(或另选方案,丢弃所有先前密封的扇区)的情况下进行修改。为此提供了一个工具,但这被认为是一项昂贵的操作,应谨慎计划并在重启任何具有新设置的节点之前完成。原因是因为所有'tree_r_last'树都必须从具有新目标值FIL_PROOFS_ROWS_TO_DISCARD的密封副本文件中重新构建,以确保系统的一致性。
除非您理解修改的影响,否则不建议调整此设置。
生成文档
首先,导航到rust-fil-proofs
目录。
- 如果您手动克隆了
rust-fil-proofs
,它将是在您克隆它的任何地方。
> git clone https://github.com/filecoin-project/rust-fil-proofs.git
> cd rust-fil-proofs
对于对应最新源代码的文档,您应该自己克隆rust-fil-proofs
。
现在,生成文档。
> cargo doc --all --no-deps
通过将浏览器指向:…/rust-fil-proofs/target/doc/proofs/index.html
来查看文档。
API参考
FPS通过lotus的FFI调用其API访问,这是其组成部分API的联合。
定义FPS API的真相来源是一个单独的Rust源代码存储库。直接查看源代码。
上述引用的存储库包含面向消费者的API,它为rust-fil-proofs
存储库的内部API提供了一个版本化的包装。最终用户不应直接使用rust-fil-proofs
的内部API,因为这些API可能会在提供的正式API之外发生变化。
要本地生成API文档,请遵循上述生成文档的说明。然后导航到
-
Filecoin Proofs API:
…/rust-filecoin-proofs-api/target/doc/filecoin_proofs_api/index.html
贡献
参见贡献指南
许可证
Filecoin项目采用Apache 2.0和MIT许可条款双重许可
- Apache许可证第2版 (LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
依赖项
约4.5MB
约159K SLoC