Offline BitTorrent v1/v2 metainfo creation and payload integrity verification
真实文件/目录 → 分片读取 → MoonBit SHA-1/SHA-256 哈希 → .torrent + magnet
已有 .torrent + 真实文件 → 格式/布局/哈希核验 → JSON + 离线 HTML + 绑定身份的核验凭据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 helpnode scripts/swarmcrate.mjs plan ./release --mode hybrid --piece-length autonode 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/announcenode scripts/swarmcrate.mjs verify ./release.torrent ./release --file docs/manual.pdf --html ./manual-check.htmlnode scripts/swarmcrate.mjs verify ./release.torrent ./release --diagnostics ./files.json --html ./files.html --detail-limit 4096node scripts/demo.mjs
# 再次演示时选择新的输出目录
node scripts/demo.mjs --output ./artifacts/demo-0.14.0{"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-warnmoon 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.pymoon add Novanke/swarmcrate@0.14.0let 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))moon run examples/library --target wasm-gc --release --deny-warn
moon run examples/library --target js --release --deny-warnmoon run examples/controlled --target wasm-gc --release --deny-warn
moon run examples/controlled --target js --release --deny-warn
python scripts/control_interop.pymoon run examples/create_controlled --target wasm-gc --release --deny-warn
moon run examples/create_controlled --target js --release --deny-warn
python scripts/creation_interop.pymoon 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.pypub struct BatchAudit {
// private fields
}pub struct BatchManifest {
// private fields
}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?
}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
}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?
}pub(all) struct FileIssue {
file : Int
path : String
expected : Int64
actual : Int64?
reason : String
}pub(all) struct StagingAssessment {
status : String
reason : String
operation_id : String?
}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
}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
}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?
}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
}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?
}pub struct VerificationReceipt {
// private fields
}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
}fn assess_staging(marker : Bytes, local_receipt : Bytes?, evidence : StagingEvidence) -> StagingAssessmentfn 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 CrateErrorfn 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 CrateErrorfn create_torrent(files : Array[SourceFile], options : CreateOptions, read : (Int, Int64, Int) -> Bytes raise CrateError) -> Bytes raise CrateErrorfn create_torrent_with_control(files : Array[SourceFile], options : CreateOptions, read : (Int, Int64, Int) -> Bytes raise CrateError, on_progress : (CreationProgress) -> Bool raise CrateError) -> Bytes raise CrateErrorfn edit_distribution(data : Bytes, trackers : Array[Array[String]], web_seeds : Array[String]) -> Bytes raise CrateErrorfn hash_v2_file(length : Int64, piece_length : Int, read : (Int64, Int) -> Bytes raise CrateError) -> V2FileHash raise CrateErrorfn piece_spans(files : Array[SourceFile], piece_length : Int, piece : Int) -> Array[PieceSpan] raise CrateErrorfn recommend_piece_length(files : Array[SourceFile], mode? : TorrentMode, target_pieces? : Int) -> Int raise CrateErrorfn sha1_pieces(files : Array[SourceFile], piece_length : Int, read : (Int, Int64, Int) -> Bytes raise CrateError) -> Bytes raise CrateErrorfn validate_piece_layer(root : Bytes, length : Int64, piece_length : Int, layer : Bytes) -> Unit raise CrateErrorfn verification_scope(torrent : Bytes, selected_files? : Array[Int]?) -> VerificationScope raise CrateErrorfn verify_payload(torrent : Bytes, lengths : Array[Int64?], read : (Int, Int64, Int) -> Bytes raise CrateError, detail_limit? : Int, selected_files? : Array[Int]?) -> VerificationReport raise CrateErrorfn 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 CrateErrorfn 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 CrateErrorInstall
Download zipOffline BitTorrent v1/v2 metainfo creation and payload integrity verification