Sign in

    swarmcrate

    Offline BitTorrent v1/v2 metainfo creation and payload integrity verification

    bittorrent
    metainfo
    integrity
    cli
    Download zip
    Author
    Version
    0.14.0
    License
    Apache-2.0
    Last updated
    2 hours ago
    Downloads
    100

    #SwarmCrate

    基于 MoonBit 的离线 BitTorrent 元数据制作与文件完整性核验工具。

    SwarmCrate 直接读取本地文件或目录,生成可被 BitTorrent 客户端读取的 v1、v2 或混合格式 .torrent 和磁力链接;也能读取已有种子、核对实际文件,并把损坏分片映射到文件与字节偏移。可用于开源发布包制作、数据集交付、离线镜像巡检和已有种子的发布地址维护。

    真实文件/目录 → 分片读取 → MoonBit SHA-1/SHA-256 哈希 → .torrent + magnet 已有 .torrent + 真实文件 → 格式/布局/哈希核验 → JSON + 离线 HTML + 绑定身份的核验凭据

    核心算法和命令处理由 MoonBit 实现,CLI 的 Node.js 适配层仅负责操作系统 I/O,不调用外部种子生成程序、系统哈希命令或网络服务。库可在 Wasm GC、JavaScript 后端使用,文件系统 CLI 需要 Node.js 22.16+。没有下载、做种或 Tracker 服务功能。

    长期按三条主线推进:开源发布与数据集交付、离线镜像巡检、MoonBit 可复用 SDK。优先级、下一项交付与验收标准见 开发路线图。

    受控创建和批量巡检强制终止后,可用 staging-list PARENT 只读识别残留,再用 staging-clean STAGE --operation ID 清理一个经确认的本机孤立任务。MoonBit 会核对所有权记录、目录/文件身份、检查快照和进程状态;旧版无记录、活动任务、额外文件或无法确认的条目保留,正式输出不受影响。使用范围、命令和失败边界见暂存识别与安全清理。

    #快速使用

    安装官方 MoonBit 工具链,要求 moonc ≥ 0.10.14,本版验证使用 0.10.16;另安装 Node.js 22.16+。CI 会检查编译器版本下限。克隆后执行:

    git clone https://github.com/Novanke/swarmcrate.git cd swarmcrate moon update python scripts/check_toolchain.py # 可选的本机版本检查;需要 Python 3 moon build --target js --release node scripts/swarmcrate.mjs help

    发布前可先只读规划,不打开载荷文件、不计算内容哈希,也不生成输出文件:

    node scripts/swarmcrate.mjs plan ./release --mode hybrid --piece-length auto

    规划显示真实字节、逻辑布局字节、虚拟补零、两套分片数、v1 哈希字节和 v2 分片层字节上限。storage_bytes 不等于磁盘占用或流量,哈希层上限不等于完整种子大小;最终格式/节点限制仍由实际创建校验。计划不能替代载荷核验。

    制作真实目录的混合格式种子(Tracker 是可选项,示例地址不提供服务):

    node scripts/swarmcrate.mjs create ./release ./release.torrent --mode hybrid --piece-length 262144 node scripts/swarmcrate.mjs inspect ./release.torrent node scripts/swarmcrate.mjs magnet ./release.torrent node scripts/swarmcrate.mjs verify ./release.torrent ./release --receipt ./receipt.json --html ./verification.html node scripts/swarmcrate.mjs edit ./release.torrent ./release-new.torrent --tracker https://example.org/announce

    create 输出 JSON,包含真实输出文件、内容标识和磁力链接。verify 输出逐片核验 JSON,可同时生成不依赖网络、脚本和外部样式的 HTML 报告。返回码 0 表示成功,1 表示输入或 I/O 错误,2 表示核验失败。损坏报告中的分片索引和文件偏移从零开始。

    create 默认自动选择分片大小,也可显式使用 --piece-length auto;选择结果见输出的 info.piece_length。目标约 4,096 个分片,同时考虑 v2/混合格式的每文件对齐与硬上限。需要固定布局和内容标识时,传入明确的字节数。create --help、verify --help 等子命令可直接查看用法。

    只复核资料包中的指定文件(可重复 --file,路径与 inspect 一致):

    node scripts/swarmcrate.mjs verify ./release.torrent ./release --file docs/manual.pdf --html ./manual-check.html

    局部成功在 HTML 中标记为 PARTIAL PASS,JSON 的 complete=false,不能作为整个资料包通过的证明。v1 跨文件分片还需要相邻文件的部分字节;required_files 列出这些依赖。其他分片跳过读取和哈希;不指定 --file 则检查全部文件。v2 单片读取失败仅影响该片,后续分片仍会检查。

    --receipt NEW.json 另存 swarmcrate.receipt.v1:绑定完整种子原始字节的 SHA-256、两套 infohash、真实文件索引/路径/长度、所需文件的观测大小及完整核验结果。outcome 区分 PASS、PARTIAL_PASS 和 FAIL,失败检查也能保存。标准输出和退出码保持兼容。仅改 Tracker 就会改变完整种子摘要,即使 infohash 不变,旧凭据也只对应原始输入。凭据是普通未签名 JSON,不认证发布者,也不代替未来重新核验;见凭据字段与范围说明。

    凭据和 HTML 的父目录必须已存在;读取载荷前拒绝已有/重复目标,以及与任意列出载荷文件重叠的目标,包括未选择或缺失文件。读后检测到源文件变化时不写报告。多个输出依次独占写入,不是原子事务;后续 I/O 失败时先前完整输出可能保留。

    创建前会复查已扫描的文件和目录清单,空目录也参与检查;新增文件、移除或重命名目录等变化会中止创建,不写出新种子。枚举顺序变化不影响结果。检查仍是顺序执行,制作发布物时请使用稳定源目录。

    单文件种子的 PAYLOAD 参数直接指向文件;多文件种子指向包含元数据所列相对路径的目录,不额外拼接种子名称。输出必须是新文件,CLI 不覆盖已有文件。edit 用所给参数整体替换 Tracker 和 Web Seed 列表;修改后保留原始 info 字节,内容哈希不会改变。

    按文件查看待复核范围,或单独保存 JSON:

    node scripts/swarmcrate.mjs verify ./release.torrent ./release --diagnostics ./files.json --html ./files.html --detail-limit 4096

    诊断汇总哈希不一致、不可读分片影响、缺失内容和额外尾部,合并相邻/重叠区间及两套哈希的重复范围。缺失空文件仍保留问题标记。v1 共享分片只能给出相关文件的候选范围,不能断定每个文件都损坏;短文件现有前缀也不会被冒充已检查。详情截断时 ranges_complete=false,清单和字节数可能不完整,HTML 明示 INCOMPLETE。默认标准输出保持兼容,载荷不会被自动修改。字段与使用限制见按文件诊断说明。

    可重复的完整演示:

    node scripts/demo.mjs # 再次演示时选择新的输出目录 node scripts/demo.mjs --output ./artifacts/demo-0.14.0

    默认在 artifacts/demo/ 生成合成演示文件、三种格式种子、正确与损坏核验报告及凭据,以及指定文件的局部校验报告与凭据;已有目录不会覆盖,可用 --output 指定新目录。演示目录不纳入源码统计或发布包。

    #批量巡检多个镜像或发布包

    0.14.0 提供纯 MoonBit 批量 SDK 与磁盘命令。jobs.json 使用 swarmcrate.audit-manifest.v1,例如:

    {"schema":"swarmcrate.audit-manifest.v1","tasks":[ {"id":"release","metainfo":"release.torrent","payload":"release"}, {"id":"manual","metainfo":"docs.torrent","payload":"docs","files":["guide.pdf"]} ]}

    node scripts/swarmcrate.mjs audit-batch ./jobs.json ./audit-summary.json moon run examples/batch --target wasm-gc --release --deny-warn moon run examples/batch --target js --release --deny-warn moon run examples/batch_disk --target js --release --deny-warn

    相对输入按清单目录解析。每任务独立返回 PASS、PARTIAL_PASS、FAIL 或 ERROR;坏种子、无效选择或来源变化只影响该项,之后继续。汇总绑定原始清单/种子的 SHA-256、infohash、实际 selected/required 文件索引和同次凭据摘要;只改 Tracker 也会保留不同身份,不按 infohash 复用检查。局部成功退出 0,但 all_full_pass=false;有任务错误退出 1,否则有核验失败退出 2。

    保存前保护清单及所有任务的输入根,汇总暂存后原子不覆盖发布,要求硬链接支持。清单最多 1 MiB/64 项,默认汇总最多 16 MiB;超过预算的任务明确记为错误并继续。汇总是各任务完成时的顺序观测,不能代表全批次原子快照。字段、边界和 SDK 回调见批量巡检说明。

    从 0.13.0 起,可使用 audit_batch_with_control / cli.execute_batch_with_control 获取批次和单任务核验进度。回调 false 或抛错终止整批,不返回/保存候选汇总;任务已全部完成、汇总已序列化和磁盘写入前仍可取消。累计读取按真实回调增量统计,完成计数不能当作全量通过。受控保存前再次检查清单与当前来源,随后原子发布;同步协作检查点,不是 Ctrl-C 或异步抢占。见批量进度与取消。

    真实文件消费方支持 --cancel-file MARKER,可由另一终端创建标记,在下个检查点终止整批;进度写 stderr,最终结果写 stdout,示例命令见上述说明。

    moon run examples/batch_controlled --target wasm-gc --release --deny-warn moon run examples/batch_controlled --target js --release --deny-warn python scripts/batch_control_interop.py

    #在 MoonBit 工程中使用

    moon add Novanke/swarmcrate@0.14.0

    在消费方 moon.pkg 导入 "Novanke/swarmcrate" @swarm,然后调用:

    let content = b"hello"
    let options = {
    ..@swarm.create_options("hello.txt"),
    mode: @swarm.Hybrid,
    single_file: true,
    }
    let torrent = @swarm.create_torrent(
    [{ path: ["hello.txt"], length: 5L }], options,
    fn(_, offset, n) { content[offset.to_int():offset.to_int() + n].to_owned() },
    )
    let summary = @swarm.inspect_torrent(torrent)
    println(@swarm.info_json(summary).stringify(indent=2))
    let (report, receipt) = @swarm.verify_with_receipt(
    torrent, [Some(5L)],
    fn(_, offset, n) { content[offset.to_int():offset.to_int() + n].to_owned() },
    )
    println(@swarm.verification_json(report).stringify())
    println(@swarm.receipt_json_text(receipt))
    println(@swarm.receipt_diagnostics_json_text(receipt))

    调用方处理 CrateError(code, detail)。读取回调必须返回请求的完整字节,创建时的文件索引始终对应输入数组,库内部确定性排序不会改变回调映射。核验时的文件索引对应 inspect_torrent(...).files。见 接口约定 和自动生成的 公开接口。

    仓库另有完整、可直接运行的纯 MoonBit 示例,无需准备文件或使用文件系统桥:

    moon run examples/library --target wasm-gc --release --deny-warn moon run examples/library --target js --release --deny-warn

    示例依次规划并创建 v1、v2、混合种子,输出元数据、磁力链接、完整核验报告和不可变凭据快照,再主动破坏内容并检查能否发现损坏。两个后端都由 CI 实际执行。消费方包的导入方式与示例的 moon.pkg 相同。

    从 0.10.0 起,SDK 可用 verify_with_control(..., on_progress) 接收同步进度并协作取消。回调返回 false 或抛出错误时不返回完整报告/凭据,包括检查计数已完成但尚未返回的阶段。进度不能替代最终通过结果;核验与创建分别使用独立控制接口;均不包含异步 I/O 或浏览器事件循环适配。完整契约与真实文件消费方见 SDK 进度与取消:

    moon run examples/controlled --target wasm-gc --release --deny-warn moon run examples/controlled --target js --release --deny-warn python scripts/control_interop.py

    创建种子也可使用独立的 create_torrent_with_control 和 CLI 适配器 execute_create_with_control。读取、编码前、最终化及写入前均可协作取消;取消不返回种子,受控磁盘流程在来源复查后通过暂存和原子不覆盖发布目标。新发布原语要求硬链接支持;强制进程终止可能留下隐藏暂存区,目标路径保持不存在或完整。契约和示例见 创建进度与取消:

    moon run examples/create_controlled --target wasm-gc --release --deny-warn moon run examples/create_controlled --target js --release --deny-warn python scripts/creation_interop.py

    #已实现

    • 纯 MoonBit 的 plan_torrent / plan_json 和只读 CLI plan;创建复用规划预检,在读取载荷前拒绝超限布局。
    • 有界、规范 bencode 编解码,保留原始字节区间,拒绝重复/未排序字典键、非规范整数、截断、超深与过大输入。
    • v1 跨文件 SHA-1 分片,v2 16 KiB 区块 Merkle 树、零哈希补齐及认证分片层。
    • v1/v2/混合格式创建与严格读取;混合格式使用虚拟补零,并核对两种格式的路径、顺序、长度和对齐一致性。
    • 读取独立 v1 的 BEP 47 补零条目,以虚拟零字节参与核验,不需要磁盘上的 .pad 文件;局部核验和损坏定位始终使用真实文件索引。
    • 所有创建模式只读取一次真实载荷;v2 读取按片边界合并为不超过 1 MiB 的请求,Merkle 叶子仍严格为 16 KiB;多文件树使用目录索引构建。
    • 文件大小、缺失、读取异常、损坏分片及文件偏移报告;混合格式在一次真实读取中分别核验两套预期哈希,短片的虚拟补零不读磁盘。读取失败同时影响该片的两套检查,之后的分片继续检查。
    • SHA-1 十六进制/Base32、SHA-256 multihash 磁力链接解析与输出,UTF-8 百分号编码。
    • Tracker 分层、Web Seed、私有标志、注释,以及保留 info 精确字节的分发地址编辑。
    • 文件扫描、分段读取、源文件与目录清单复查(含空目录)、拒绝符号链接和特殊文件、独占创建输出。创建期间的新增、移除、重命名与目录替换会触发错误,停止写出过时元数据。
    • 无损尺寸字符串 JSON、离线 HTML 核验报告和六个真实文件命令。
    • 同次核验生成的独立 JSON 凭据,绑定精确种子身份、文件映射、检查范围和结果;调用方修改返回报告的数组不会改写已捕获的凭据。
    • 按文件合并的待复核范围、缺失/额外尾部与去重字节数,可从凭据或 --diagnostics 导出;HTML 展示分组范围及截断提示。
    • 纯 MoonBit 清单解析、批量巡检、任务失败隔离和不可变身份/范围汇总;跨任务输出保护、来源复查及原子保存,附双后端与真实文件示例。
    • 核验 SDK 的标量进度快照、协作取消与观察者错误传递;普通读取错误仍作为不可读分片,旧调用方式保持兼容。
    • 创建 SDK 与受控命令的进度、取消、固定输入快照和最终发布门槛;暂存后原子不覆盖提交,取消、写入失败和发布竞态均有真实文件验证。

    #验证与规模

    moon fmt --check moon info moon test --target wasm-gc --deny-warn moon test --target js --deny-warn moon build --target js --release --deny-warn python scripts/source_audit.py python -m pip install libtorrent==2.1.1 torf==4.3.1 python scripts/interop.py --cli _build/js/release/build/cmd/main/main.js python scripts/io_faults.py

    当前有 55 个核心测试块,JS 加文件系统/CLI 测试共 78 个测试块。独立互操作脚本通过 215 个真实文件场景,涵盖 libtorrent 接收输出、反向读取 libtorrent 生成的数据、torf 校验 v1、Python 独立 SHA-1/Merkle 根、损坏/缺失/截断、磁力链接、编辑保持身份、三种格式的局部校验、自动分片,超过 1 MiB 的批量读取与末片补齐,以及独立 v1 补零、尾部补零、部分文件未对齐时的邻居依赖和损坏定位。还覆盖真实 OS 读取计数、混合核验单遍读取、1 MiB 内部读取失败后的继续检查,以及三种格式的目录变化拦截、稳定/乱序对照、内容标识保持与目录句柄关闭。规划测试禁止打开载荷,且用实际种子的独立解码对照所有计划计数。新增凭据场景独立核对完整 SHA-256、infohash、文件映射、全量/局部/失败状态,并检查输出保护和源文件变化拦截;单遍读取观测同时保存凭据,确保不重复读取载荷。

    文件级诊断测试还覆盖字节位图区间并集对照、大偏移字符串、混合格式去重、缺失/短/长/空文件、邻居归属和不完整清单。新增 32 个磁盘场景对照实际文件、独立 v1 补零和三类输出保护;真实异常/短读观测同时导出诊断,确认不会重复读取载荷。

    另外,scripts/control_interop.py 通过 30 个真实文件 SDK 控制场景:三种格式的完成、各阶段取消、观察者错误、损坏/缺失、已有输出和读后变化。核验控制的五个核心测试块覆盖所有回调阶段、单调计数、普通读错与观察者错误的区别,以及检查数完成后取消仍不返回结果。两类磁盘脚本与测试块分别统计,不相加作为测试块数量。

    scripts/creation_interop.py 另有 78 个真实文件创建场景,覆盖所有取消/回调错误阶段、单/多文件、来源变化、已有/竞争目标、部分或零写入、同步/链接失败,以及发布前后模拟进程中断。四个新增核心测试块验证输出字节兼容、索引、取消及输入冻结;host/CLI 测试验证新发布原语和最后取消门槛。

    0.11.1 引入并持续通过 21 个关闭故障场景:读取/写入关闭失败仍返回结构化错误,核验继续后续分片并保存 FAIL 凭据,原子暂存关闭失败不发布目标,不重试可能已被 OS 释放的句柄。CI 覆盖 Windows/Linux × Node 22.16.0/24;最低版本实测发现的设备字段差异已修复,完整互操作仍验证来源变化拦截。公开 SHA-1 工具函数也在读取前拒绝超过 400,000 分片的任务;详见运行环境与独立复现。

    批量巡检新增五个核心测试块和六个 MoonBit CLI 测试块,覆盖混合状态后继续、精确元数据/范围绑定、回调修改、汇总预算、清单目录基准、跨任务输入保护、来源/清单变化、已有及竞争目标。新增批量编排与接口测试使用 MoonBit;独立 Python 预言机继续用于交叉核对。

    批量控制另有四个核心和四个 MoonBit CLI 测试块,以及 48 个真实子进程场景:覆盖每个取消/异常检查点、读取恢复、最终计数、观察者修改来源、写入/同步/关闭/链接故障、竞争及强制退出。所有场景与测试块分别统计。

    仅根目录自写库代码:4,179 行非空非注释源码,2,572 行保守函数体统计;已排除测试、文档、生成接口、依赖、CLI、基准程序和 JS 桥接。该统计是透明复核材料,不替代主办方计数。实际功能提交见 实现记录,版本变化见 更新记录。

    混合核验的 8 MiB + 3 字节合成对照中,相比注册表 0.4.0,读取量从 16,777,222 降至 8,388,611 字节,回调次数由 66 降至 33,两套哈希检查仍共 66 次。该结果说明读取量减少,不等于 CPU 哈希工作减半;性能对照与复现方式见 基准说明。验收项与仓库证据的对应关系见 验收自查,关键原理与取舍见 设计说明。

    #范围和资源边界

    元数据最大 16 MiB、深度 64、20 万 bencode 节点;文件系统扫描最多 200,000 个后代条目(文件与目录合计,不含输入根目录),按剩余预算逐项枚举并在超限时停止;真实文件集合最多 65,536 个文件、32 层路径,独立 v1 的存储条目上限 65,536 包括补零;总字节数最多 2^53-1,分片最多 400,000;分片大小为 16 KiB 至 16 MiB 的二次幂。载荷必须至少包含一个非空文件,可以同时包含空文件。哈希按块/片读取,不把整个载荷装入内存。元数据、分片哈希和有界诊断保存在内存中。

    采用可移植安全路径子集:拒绝遍历、Windows 设备名、大小写冲突、文件/目录冲突和保留 .pad 源路径。读取已有种子时对不受支持的路径、文件属性和符号链接明确报错,不尝试静默改名。独立 v1 补零只支持 attr="p" 且必须填满已有的未满分片,可有尾部补零;补零路径可省略,存在时仍检查安全组件。其他属性组合及符号链接明确拒绝,详细兼容范围见接口约定。支持 HTTP(S) Tracker/Web Seed 和 UDP Tracker;不接收 URL 用户凭据或片段。只处理 BitTorrent 元数据与文件核验,不提供签名认证、网络传输、下载续传或完整客户端功能。

    #来源、原创性和许可证

    这是遵循 BEP 3、BEP 52、BEP 47、BEP 9 的独立工程实现,不宣称发明 BitTorrent 或哈希算法。SHA-1/SHA-256 来自官方纯 MoonBit 包 moonbitlang/x/crypto@0.5.5,依赖源码不计入本项目代码量。libtorrent 和 torf 仅用于独立测试,不参与运行时输出。

    功能与作者已有的 QuireLoom 拼版库、moonmorph JSON 迁移工具不同;公开生态检索范围与相关项目见 方向核对记录。代码、测试和文档由 AI 辅助编写并执行验证,使用前可依据源码和复现步骤审阅。

    Apache-2.0,见 LICENSE 和 依赖与来源说明。后续供评审使用的功能更新须同步发布 Mooncakes 新版本,见 发布流程。

    CrateError

    pub(all) suberror CrateError {
    CrateError(String, String)
    } derive(
    Debug
    )

    BatchAudit

    pub struct BatchAudit {
    // private fields
    }

    Immutable, unsigned summary. Only audit_batch can construct one.

    BatchManifest

    pub struct BatchManifest {
    // private fields
    }

    Validated, immutable task definitions bound to the exact manifest bytes.

    BatchProgress

    pub(all) struct BatchProgress {
    phase : String
    manifest_sha256 : String
    task_count : Int
    completed_tasks : Int
    pass_tasks : Int
    partial_pass_tasks : Int
    failed_tasks : Int
    error_tasks : Int
    read_calls : Int64
    validated_read_bytes : Int64
    task_index : Int?
    task_id : String?
    task_outcome : String?
    verification : VerificationProgress?
    }

    Immutable checkpoint values. Completed rows and read bytes are not a success certificate.

    BatchTask

    pub(all) struct BatchTask {
    id : String
    metainfo : String
    payload : String
    files : Array[String]?
    }

    Locators are opaque to the core; the filesystem CLI resolves them from the manifest directory.

    CreateOptions

    pub(all) struct CreateOptions {
    name : String
    mode : TorrentMode
    piece_length : Int
    single_file : Bool
    private_torrent : Bool
    trackers : Array[Array[String]]
    web_seeds : Array[String]
    comment : String
    }

    CreationProgress

    pub(all) struct CreationProgress {
    phase : String
    mode : TorrentMode
    file_count : Int
    total_bytes : Int64
    read_calls : Int
    validated_read_bytes : Int64
    file : Int?
    offset : Int64?
    length : Int?
    metainfo_bytes : Int?
    }

    Creation checkpoints describe real reads, not proof that metainfo is encoded or saved. before_write is emitted only by the controlled CLI adapter, before atomic publication.

    FileIssue

    pub(all) struct FileIssue {
    file : Int
    path : String
    expected : Int64
    actual : Int64?
    reason : String
    }

    Magnet

    pub(all) struct Magnet {
    v1 : String?
    v2 : String?
    name : String?
    trackers : Array[String]
    }

    PieceFailure

    pub(all) struct PieceFailure {
    scheme : String
    piece : Int
    spans : Array[PieceSpan]
    reason : String
    }

    PieceSpan

    pub(all) struct PieceSpan {
    file : Int
    offset : Int64
    length : Int
    }

    SourceFile

    pub(all) struct SourceFile {
    path : Array[String]
    length : Int64
    }

    StagingAssessment

    pub(all) struct StagingAssessment {
    status : String
    reason : String
    operation_id : String?
    }

    StagingEvidence

    pub(all) struct StagingEvidence {
    stage_path : String
    directory_id : String
    data_id : String
    actual_bytes : Int64
    local_host : String
    local_user : String
    owner_state : String
    }

    Filesystem/process observations are supplied by an adapter; the core performs no I/O.

    StagingOwner

    pub(all) struct StagingOwner {
    operation_id : String
    stage_path : String
    target_path : String
    directory_id : String
    data_id : String
    pid : Int
    host : String
    user : String
    expected_bytes : Int64
    }

    Versioned provenance for one exclusive publication stage, not a signature.

    TorrentInfo

    pub(all) struct TorrentInfo {
    name : String
    mode : TorrentMode
    piece_length : Int
    files : Array[SourceFile]
    single_file : Bool
    private_torrent : Bool
    trackers : Array[Array[String]]
    web_seeds : Array[String]
    comment : String
    info_hash_v1 : String?
    info_hash_v2 : String?
    }

    TorrentMode

    pub(all) enum TorrentMode {
    V1
    V2
    Hybrid
    } derive(Eq,
    Debug
    )

    TorrentMode::equal

    fn TorrentMode::equal(TorrentMode, TorrentMode) -> Bool

    TorrentMode::not_equal

    fn TorrentMode::not_equal(x : TorrentMode, y : TorrentMode) -> Bool

    TorrentPlan

    pub(all) struct TorrentPlan {
    name : String
    mode : TorrentMode
    piece_length : Int
    single_file : Bool
    file_count : Int
    empty_files : Int
    real_bytes : Int64
    storage_bytes : Int64
    padding_bytes : Int64
    v1_pieces : Int
    v2_pieces : Int
    v1_hash_bytes : Int64
    v2_piece_layer_bytes_upper_bound : Int64
    }

    V2FileHash

    pub(all) struct V2FileHash {
    root : Bytes
    piece_layer : Bytes
    }

    VerificationProgress

    pub(all) struct VerificationProgress {
    phase : String
    total_checks : Int
    checked_pieces : Int
    failed_pieces : Int
    unreadable_pieces : Int
    read_calls : Int
    validated_read_bytes : Int64
    complete_scope : Bool
    selected_file_count : Int
    required_file_count : Int
    file : Int?
    offset : Int64?
    length : Int?
    read_ok : Bool?
    }

    Synchronous cooperative-verification checkpoint. All fields are value snapshots. Checks count hash comparisons (two per hybrid piece), not physical byte ranges.

    VerificationReceipt

    pub struct VerificationReceipt {
    // private fields
    }

    Immutable, unsigned snapshot of one verification and its exact metainfo input. Constructed by verify_with_receipt, rather than by pairing an arbitrary report and subject.

    VerificationReport

    pub(all) struct VerificationReport {
    ok : Bool
    scope : VerificationScope
    checked_pieces : Int
    skipped_pieces : Int
    failed_pieces : Int
    unreadable_pieces : Int
    file_issues : Array[FileIssue]
    failures : Array[PieceFailure]
    details_truncated : Bool
    }

    VerificationScope

    pub(all) struct VerificationScope {
    complete : Bool
    selected_files : Array[Int]
    required_files : Array[Int]
    }

    assess_staging

    fn assess_staging(marker : Bytes, local_receipt : Bytes?, evidence : StagingEvidence) -> StagingAssessment

    Only matching local provenance, stable object identities and positively absent PID qualify. Existing/reused PIDs and all uncertain observations are preserved, regardless of age.

    audit_batch

    fn audit_batch(manifest : BatchManifest, load : (Int, BatchTask) -> Bytes raise CrateError, observe : (Int, TorrentInfo, VerificationScope) -> Array[Int64?] raise CrateError, read : (Int, Int, Int64, Int) -> Bytes raise CrateError, finish? : (Int) -> Unit raise CrateError?, detail_limit? : Int, max_summary_bytes? : Int) -> BatchAudit raise CrateError

    Sequential independent audits. Only checked CrateError task failures are isolated; programming panics are not caught. finish must recheck caller-owned storage before acceptance. A summary quota failure records ERROR for that task and continues, never dropping later jobs.

    audit_batch_with_control

    fn audit_batch_with_control(manifest : BatchManifest, load : (Int, BatchTask) -> Bytes raise CrateError, observe : (Int, TorrentInfo, VerificationScope) -> Array[Int64?] raise CrateError, read : (Int, Int, Int64, Int) -> Bytes raise CrateError, on_progress : (BatchProgress) -> Bool raise CrateError, finish? : (Int) -> Unit raise CrateError?, detail_limit? : Int, max_summary_bytes? : Int) -> BatchAudit raise CrateError

    False or observer errors abort the entire batch, with no BatchAudit returned. Task-local checked storage errors retain ordinary ERROR/FAIL isolation.

    batch_audit_exit_code

    fn batch_audit_exit_code(audit : BatchAudit) -> Int

    1 if any task ERROR, otherwise 2 for integrity FAIL, otherwise 0 (including partial success).

    batch_audit_json_text

    fn batch_audit_json_text(audit : BatchAudit) -> String

    batch_manifest_tasks

    fn batch_manifest_tasks(manifest : BatchManifest) -> Array[BatchTask]

    Return independent copies, not the runner's frozen task definitions.

    batch_progress_json

    fn batch_progress_json(event : BatchProgress) -> Json

    Structured progress is telemetry, never a saved/verified batch result.

    check_bencode

    fn check_bencode(data : Bytes) -> Unit raise CrateError

    Validate canonical bencoding, including raw byte key order and signed Int64 bounds.

    create_options

    fn create_options(name : String) -> CreateOptions

    create_torrent

    fn create_torrent(files : Array[SourceFile], options : CreateOptions, read : (Int, Int64, Int) -> Bytes raise CrateError) -> Bytes raise CrateError

    Produce only metadata accepted by this library's full syntax and layout checks.

    create_torrent_with_control

    fn create_torrent_with_control(files : Array[SourceFile], options : CreateOptions, read : (Int, Int64, Int) -> Bytes raise CrateError, on_progress : (CreationProgress) -> Bool raise CrateError) -> Bytes raise CrateError

    Create complete, validated metainfo with synchronous cooperative cancellation. Callback false or any error returns no metainfo. No filesystem writes occur here.

    edit_distribution

    fn edit_distribution(data : Bytes, trackers : Array[Array[String]], web_seeds : Array[String]) -> Bytes raise CrateError

    Replace distribution endpoints without changing the exact encoded info dictionary. Unknown top-level extension fields are retained. Private torrents must retain a tracker.

    expected_v1_pieces

    fn expected_v1_pieces(data : Bytes) -> Bytes raise CrateError

    Expose expected v1 piece hashes for verification and integration with other clients.

    expected_v2_files

    fn expected_v2_files(data : Bytes) -> Array[V2FileHash] raise CrateError

    format_magnet

    fn format_magnet(magnet : Magnet) -> String raise CrateError

    hash_v2_file

    fn hash_v2_file(length : Int64, piece_length : Int, read : (Int64, Int) -> Bytes raise CrateError) -> V2FileHash raise CrateError

    Hash 16 KiB blocks with BEP 52 zero-hash padding, buffering one piece's hashes. Empty files have neither pieces root nor piece layer.

    info_json

    fn info_json(info : TorrentInfo) -> Json

    Sizes are decimal strings so consumers never round 64-bit file offsets.

    inspect_torrent

    fn inspect_torrent(data : Bytes) -> TorrentInfo raise CrateError

    mode_name

    fn mode_name(mode : TorrentMode) -> String

    parse_batch_manifest

    fn parse_batch_manifest(data : Bytes) -> BatchManifest raise CrateError

    Parse <=1 MiB UTF-8 JSON, depth <=8, unique keys/IDs, 1..64 tasks. Unknown fields and explicit empty selections are errors before any callbacks.

    parse_magnet

    fn parse_magnet(uri : String) -> Magnet raise CrateError

    parse_staging_owner

    fn parse_staging_owner(data : Bytes) -> StagingOwner raise CrateError

    piece_spans

    fn piece_spans(files : Array[SourceFile], piece_length : Int, piece : Int) -> Array[PieceSpan] raise CrateError

    Map a v1 piece to its contributing real file ranges, including boundary pieces.

    plan_json

    fn plan_json(plan : TorrentPlan) -> Json

    plan_torrent

    fn plan_torrent(files : Array[SourceFile], options : CreateOptions) -> TorrentPlan raise CrateError

    Plan the creator's layout without reading or hashing payload bytes. V2 piece-layer size is an upper bound because identical roots are deduplicated only after hashing. This is not a prediction of complete metainfo size.

    receipt_diagnostics_json_text

    fn receipt_diagnostics_json_text(receipt : VerificationReceipt) -> String

    Export immutable per-file candidate ranges bound to the same receipt and scope. Truncated failure details make the range inventory incomplete, never a complete repair plan.

    receipt_json_text

    fn receipt_json_text(receipt : VerificationReceipt) -> String

    Serialize the immutable receipt snapshot. This does not reverify a saved JSON document.

    recommend_piece_length

    fn recommend_piece_length(files : Array[SourceFile], mode? : TorrentMode, target_pieces? : Int) -> Int raise CrateError

    Recommend a power-of-two piece size in 16 KiB..16 MiB. The target is soft; per-file formats cannot use fewer pieces than their nonempty file count. Never recommend a size that would exceed the hard 400,000-piece limit.

    sha1_pieces

    fn sha1_pieces(files : Array[SourceFile], piece_length : Int, read : (Int, Int64, Int) -> Bytes raise CrateError) -> Bytes raise CrateError

    Hash the exact caller-supplied file order, crossing file boundaries (BEP 3). The callback must return exactly the requested bytes; only one piece is buffered. Reject layouts above 400,000 pieces before calling the reader.

    sorted_source_indices

    fn sorted_source_indices(files : Array[SourceFile]) -> Array[Int] raise CrateError

    Return indices rather than silently reordering a caller's read callback mapping.

    staging_owner_bytes

    fn staging_owner_bytes(owner : StagingOwner) -> Bytes raise CrateError

    torrent_magnet

    fn torrent_magnet(data : Bytes) -> String raise CrateError

    torrent_storage_bytes

    fn torrent_storage_bytes(data : Bytes) -> Int64 raise CrateError

    V1 storage size includes virtual v1/hybrid padding, unlike the real file total.

    valid_staging_operation_id

    fn valid_staging_operation_id(id : String) -> Bool

    validate_options

    fn validate_options(files : Array[SourceFile], options : CreateOptions) -> Unit raise CrateError

    validate_piece_layer

    fn validate_piece_layer(root : Bytes, length : Int64, piece_length : Int, layer : Bytes) -> Unit raise CrateError

    validate_sources

    fn validate_sources(files : Array[SourceFile]) -> Int64 raise CrateError

    The creator uses a portable path subset and reserves .pad for hybrid alignment.

    verification_html

    fn verification_html(info : TorrentInfo, report : VerificationReport) -> String

    A self-contained, script-free report that can be opened offline or attached to a release.

    verification_json

    fn verification_json(report : VerificationReport) -> Json

    verification_scope

    fn verification_scope(torrent : Bytes, selected_files? : Array[Int]?) -> VerificationScope raise CrateError

    Resolve a file selection before filesystem reads. Indices refer to inspected files. None selects all; duplicates are normalized; an empty selection fails. Required files include V1 boundary neighbours, which are only partly checked.

    verify_payload

    fn verify_payload(torrent : Bytes, lengths : Array[Int64?], read : (Int, Int64, Int) -> Bytes raise CrateError, detail_limit? : Int, selected_files? : Array[Int]?) -> VerificationReport raise CrateError

    Check real sizes and hashes. Missing files are None. Read errors cannot pass as zero data. Failure detail storage is bounded; aggregate counters always include every piece.

    verify_with_control

    fn verify_with_control(torrent : Bytes, lengths : Array[Int64?], read : (Int, Int64, Int) -> Bytes raise CrateError, on_progress : (VerificationProgress) -> Bool raise CrateError, detail_limit? : Int, selected_files? : Array[Int]?) -> (VerificationReport, VerificationReceipt) raise CrateError

    Cooperatively verify with synchronous progress and cancellation checkpoints. False raises CrateError("cancelled", ...); observer errors propagate unchanged. Cancellation returns neither a report nor a receipt, including at finalization.

    verify_with_receipt

    fn verify_with_receipt(torrent : Bytes, lengths : Array[Int64?], read : (Int, Int64, Int) -> Bytes raise CrateError, detail_limit? : Int, selected_files? : Array[Int]?) -> (VerificationReport, VerificationReceipt) raise CrateError

    Verify and capture identity, real-file mapping, observed sizes and actual scope together. The caller supplies stable contents and sizes; no clock, filesystem or authentication is implied.