Deterministic incremental transfer kernel: block signatures, verified deltas, content-defined chunking and deduplication
| 使用者与问题 | 输入 → 库内计算 → 输出 | 可运行入口 |
|---|---|---|
| 收到增量包的客户端:这个 delta 能不能安全落到本地? | 旧数据 + 服务端给的 delta → 反序列化、重放 COPY/COPY_RUN/LITERAL、逐 op 校验、末尾再验整体摘要 → 新数据 + 结论(成功,或第几块失败) | verified_update;examples/corruption_check |
| 发布方 / 服务端:这次更新实际要传多少字节? | 客户端签名 + 新版本 → 弱校验分桶、滑窗匹配、规划、规范化 → DDLT 字节流 + 字节数与节省比例 | plan_transfer / plan_from_signature;examples/version_upgrade |
| 备份 / 构建缓存:两个版本重复了多少? | 两个版本的对象 → 内容定义分块、指纹索引、引用计数 → DCHK manifest + 去重率 + 可重建校验 | ChunkStore::ingest / assemble;examples/chunk_dedup |
moon 0.1.20261023 (3778465 2026-10-23)
moonc v0.10.17+d971670cd (2026-10-23)
moonrun 0.1.20261023 (3778465 2026-10-23)$env:PATH = 'D:\moonbit\_tools\moon-0.10.17\bin;' + $env:PATHmoon check --deny-warn --target all
moon build --target js
moon test --deny-warn --target js
moon run examples/version_upgrade --target js
moon run examples/chunk_dedup --target js
moon run examples/corruption_check --target jsmoon add niuniu513-ask/moon-deltasync@0.1.1import {
"niuniu513-ask/moon-deltasync" @ds,
}old bytes: 120890
new bytes: 120935
| delta 字节 | 8346 | 复制操作数 2,复制字节 114688,字面量字节 8237,节省比例 0.9310
delta bytes on the wire: 8346
rebuilt bytes: 120935 (verified 14 blocks)
identical to the new version: true{"kind":"chunk","path":"snapshot-1","length":142471,"chunk_count":13,"new_chunks":13,"reused_chunks":0,"stored_bytes":142471,"saved_bytes":0,"root_hex":"e23b35b5…"}
{"kind":"chunk","path":"snapshot-2","length":142471,"chunk_count":13,"new_chunks":1,"reused_chunks":12,"stored_bytes":148786,"saved_bytes":136156,"root_hex":"80b61929…"}
distinct chunks in the store: 14
bytes actually kept: 148786
bytes deduplication avoided: 136156
matches the source: trueintact delta rebuilds 25089 bytes, all checksums agree
damaged delta: rejected: the rebuilt bytes do not match the digest the delta carries
same delta against a different old version: rejected: block 1 does not match the signature"DSIG"(4) version:u8 block_size:u32 strong_len:u8 total_length:u64 block_count:u32
repeat block_count 次: weak:u32 strong:u8[strong_len]"DDLT"(4) version:u8 block_size:u32 strong_len:u8 new_length:u64 content_digest:u8[32] op_count:u32
repeat op_count 次:
tag:u8=0 COPY: block_index:u32 strong:u8[strong_len]
tag:u8=1 LITERAL: length:u32 bytes[length]
tag:u8=2 COPY_RUN: start:u32 count:u32 strong:u8[strong_len]"DCHK"(4) version:u8 min_size:u32 max_size:u32 mask_bits:u8 chunk_count:u32
repeat chunk_count 次: sha256:u8[32] length:varint
root:u8[32] // = SHA-256(concat(每个块的 32 字节 sha256))| 层 | 入口 |
|---|---|
| 签名 | sign_bytes(input, block_size?, strong_len?) -> FileSignature、decode_signature、FileSignature::{encode, block_count, block_length, digest_hex}、signature_matches |
| delta | compute_delta(new, signature) -> Delta、Delta::encode、decode_delta、apply_delta(old, delta) -> ApplyResult、Delta::{digest_hex, op_count, copy_ops, copied_blocks, copied_bytes, literal_bytes} |
| 工作流 | plan_transfer(old, new, block_size?, strong_len?)、plan_from_signature(sig, new)、verified_update(old, delta_bytes)、TransferPlan::{delta, signature, delta_bytes, new_length, copy_ops, copied_bytes, literal_bytes, savings_ppm} |
| 分块 | chunk_boundaries(input, params?)、chunk_manifest(input, params?)、ChunkManifest::{encode, verify, chunk_count, total_length, unique_chunks, root_hex}、decode_manifest |
| 块存储 | ChunkStore::{new, ingest, assemble, unique_chunks, stored_bytes, saved_bytes}、ingest_snapshot(store, input, params?) |
| 报告 | render_signature_json(signature, path, content_sha256_hex, content_xxh64_hex)、render_delta_json、render_apply_json、render_chunk_json、render_error_json、render_plan_text、render_plan_markdown、ppm_text |
| 基础 | sha256、sha256_hex、sha256_prefix、weak_checksum、WeakRoll、xxh64、hex_encode、hex_decode、constant_time_equal、ByteSink |
moon-deltasync sign <path> # 签名摘要与统计
moon-deltasync delta <old> <new> --out <d> # 计算 delta,可写出 DDLT 原始字节
moon-deltasync apply <old> <delta> --out <f> # 应用并逐块校验,可写出重建结果
moon-deltasync chunk <path> # 分块与去重率报告
moon-deltasync verify <path> <sha256-hex> # 全流校验moon run cmd/main --target js -- sign old.txt --out old.dsig
moon run cmd/main --target js -- delta old.txt new.txt --out patch.ddlt
moon run cmd/main --target js -- apply old.txt patch.ddlt --out rebuilt.txt
moon run cmd/main --target js -- chunk new.txt --out new.dchk{"kind":"sign","path":"old.txt","total_length":120890,"block_size":8192,"strong_len":16,"block_count":15,"signature_bytes":322,"signature_sha256_hex":"add8904b…","sha256_hex":"d242f2a7…","xxh64_hex":"8d32c2ca93e03df3"}
{"kind":"delta","old":"old.txt","new":"new.txt","new_length":120935,"op_count":3,"copy_ops":2,"copy_blocks":14,"copied_bytes":114688,"literal_bytes":8237,"delta_bytes":8346,"delta_sha256_hex":"7830b34f…","savings_ratio":0.9310}
{"kind":"apply","ok":true,"bytes_written":120935,"blocks_verified":14,"ops_applied":3,"sha256_hex":"970caa0e…"}
{"kind":"chunk","path":"new.txt","length":120935,"chunk_count":4,"unique_chunks":4,"new_chunks":4,"reused_chunks":0,"stored_bytes":120935,"saved_bytes":0,"dedup_ratio":0.0000,"manifest_bytes":190,"root_hex":"ba92558c…"}
{"kind":"verify","ok":true,"sha256_hex":"970caa0e…"}
{"kind":"error","code":"usage","message":"the expected digest is not hexadecimal"}| 操作 | 时间 | 额外空间 |
|---|---|---|
| sign_bytes | O(n) 单遍 | 签名 = 22 + block_count * (4 + strong_len) 字节 |
| compute_delta | O(新数据长度),未命中时最多额外 block_size 次字节比较 | 弱校验分桶索引 + 输出 delta |
| apply_delta | O(新数据长度) | 输出缓冲 |
| chunk_boundaries / chunk_manifest | O(n) 单遍,窗口恒定 | 每块 32 字节指纹 + varint 长度 |
| 项目 | 结果 |
|---|---|
| moon check --deny-warn --target all | 通过,0 warning |
| moon build --target js / --target wasm-gc | 通过 |
| moon test --deny-warn --target js | 38 tests, 38 passed, 0 failed |
| moon test --deny-warn --target wasm / wasm-gc | 各 38/38 通过 |
| moon test --target native | 未在本机运行:moon build --target native 报缺少 MSVC(cl.exe/clang-cl),由 CI 覆盖 |
| 三个示例 | 全部实跑,输出见上文 |
| CLI 端到端 | sign→delta→apply 重建结果与新文件 SHA-256 一致;verify 与 PowerShell Get-FileHash 一致 |
| CLI --out 四个子命令 | 全部写出原始字节:sign 322 B(= signature_bytes)、chunk 190 B(= manifest_bytes)、delta 与 apply 同样落地,均与 JSON 内的字节数一致 |
| 指标 | 结果 |
|---|---|
| 硬断言 | 775 / 775 通过,0 失败 |
| advisory(不计入失败) | 26 / 26 |
| 阻塞项 | 0 |
| 退出码 | 0(0 = 硬断言全过;1 = 有硬断言失败;2 = 自测通过但 CLI 联调被阻塞) |
pub suberror FormatError {
BadMagic(String)
UnsupportedVersion(Int)
Truncated(Int)
BadField(String)
TooLarge(String)
BlockMismatch(Int)
UnsupportedOp(Int)
DigestMismatch
}pub struct ApplyResult {
bytes_written : Int
blocks_verified : Int
ops_applied : Int
digest_hex : String
output : Bytes
}pub struct BlockSignature {
index : Int
weak : UInt
strong : Bytes
}pub struct ChunkParams {
min_size : Int
max_size : Int
mask_bits : Int
}fn ChunkParams::new(min_size? : Int, max_size? : Int, mask_bits? : Int) -> ChunkParams raise FormatErrorpub struct ChunkRef {
digest : Bytes
length : Int
}pub enum DeltaOp {
Copy(Int, Bytes)
CopyRun(Int, Int, Bytes)
Literal(Bytes)
}pub struct FileSignature {
block_size : Int
strong_len : Int
total_length : Int
blocks : Array[BlockSignature]
}pub struct IngestReport {
total_bytes : Int
chunk_count : Int
new_chunks : Int
reused_chunks : Int
unique_bytes : Int
manifest : ChunkManifest
}pub struct SnapshotReport {
total_bytes : Int
chunk_count : Int
unique_chunks : Int
new_chunks : Int
reused_chunks : Int
stored_bytes : Int
saved_bytes : Int
manifest_bytes : Int
dedup_ppm : Int
root_hex : String
}pub struct TransferPlan {
signature : FileSignature
delta : Delta
new_length : Int
delta_bytes : Int
}pub struct WeakRoll {
a : UInt
b : UInt
window : UInt
}fn block_count(total : Int, block_size : Int) -> Intfn constant_time_equal(left : BytesView, right : BytesView) -> Boolfn default_block_size(length : Int) -> Intfn hex_decode(text : String) -> Bytes?fn hex_encode(view : BytesView) -> Stringfn json_string(text : String) -> Stringfn plan_from_signature(signature : FileSignature, new_bytes : BytesView) -> TransferPlan raise FormatErrorfn plan_transfer(old : BytesView, new_bytes : BytesView, block_size? : Int, strong_len? : Int) -> TransferPlan raise FormatErrorfn ppm_text(ppm : Int) -> Stringfn read_u32(view : BytesView, offset : Int) -> UInt?fn read_u64(view : BytesView, offset : Int) -> UInt64?fn read_u8(view : BytesView, offset : Int) -> Int?fn read_varint(view : BytesView, offset : Int) -> (UInt64, Int)?fn render_error_json(code : String, message : String) -> Stringfn render_signature_json(signature : FileSignature, path : String, content_sha256_hex : String, content_xxh64_hex : String) -> Stringfn sha256_hex(view : BytesView) -> Stringfn sha256_prefix(view : BytesView, length : Int) -> Bytesfn sign_bytes(input : BytesView, block_size? : Int, strong_len? : Int) -> FileSignature raise FormatErrorfn sub_view(view : BytesView, offset : Int, length : Int) -> BytesView?fn weak_checksum(view : BytesView) -> UIntfn xxh64(view : BytesView) -> UInt64fn xxh64_hex(view : BytesView) -> StringInstall
Download zipDeterministic incremental transfer kernel: block signatures, verified deltas, content-defined chunking and deduplication