Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 3m2s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
2.2 KiB
OCaml
67 lines
2.2 KiB
OCaml
(** CIDv1 computation — pure OCaml, WASM-safe.
|
|
|
|
Multihash + CIDv1 + multibase base32-lower (RFC 4648, no pad,
|
|
multibase prefix 'b'). Codecs: dag-cbor 0x71, raw 0x55. Hash
|
|
codes: sha2-256 0x12, sha3-256 0x16. Reference: the multiformats
|
|
specs (unsigned-varint, multihash, cid, multibase). No deps. *)
|
|
|
|
open Sx_types
|
|
|
|
(* Unsigned LEB128 (multiformats unsigned-varint). *)
|
|
let varint (n : int) : string =
|
|
let buf = Buffer.create 4 in
|
|
let n = ref n in
|
|
let cont = ref true in
|
|
while !cont do
|
|
let b = !n land 0x7f in
|
|
n := !n lsr 7;
|
|
if !n = 0 then (Buffer.add_char buf (Char.chr b); cont := false)
|
|
else Buffer.add_char buf (Char.chr (b lor 0x80))
|
|
done;
|
|
Buffer.contents buf
|
|
|
|
(* RFC 4648 base32 lowercase, no padding. *)
|
|
let b32_alpha = "abcdefghijklmnopqrstuvwxyz234567"
|
|
|
|
let base32_lower (s : string) : string =
|
|
let buf = Buffer.create ((String.length s * 8 + 4) / 5) in
|
|
let acc = ref 0 and bits = ref 0 in
|
|
String.iter (fun c ->
|
|
acc := (!acc lsl 8) lor (Char.code c);
|
|
bits := !bits + 8;
|
|
while !bits >= 5 do
|
|
bits := !bits - 5;
|
|
Buffer.add_char buf b32_alpha.[(!acc lsr !bits) land 0x1f]
|
|
done) s;
|
|
if !bits > 0 then
|
|
Buffer.add_char buf b32_alpha.[(!acc lsl (5 - !bits)) land 0x1f];
|
|
Buffer.contents buf
|
|
|
|
(* "abef" -> the 2 raw bytes. *)
|
|
let unhex (h : string) : string =
|
|
let n = String.length h / 2 in
|
|
let b = Bytes.create n in
|
|
for i = 0 to n - 1 do
|
|
Bytes.set b i
|
|
(Char.chr (int_of_string ("0x" ^ String.sub h (2 * i) 2)))
|
|
done;
|
|
Bytes.unsafe_to_string b
|
|
|
|
(* multihash = varint(code) || varint(len) || digest *)
|
|
let multihash (code : int) (digest : string) : string =
|
|
varint code ^ varint (String.length digest) ^ digest
|
|
|
|
(* CIDv1 = 0x01 || varint(codec) || multihash ; multibase 'b' base32. *)
|
|
let cidv1 (codec : int) (mh : string) : string =
|
|
"b" ^ base32_lower ("\x01" ^ varint codec ^ mh)
|
|
|
|
let codec_dag_cbor = 0x71
|
|
let mh_sha2_256 = 0x12
|
|
|
|
(* Canonicalize an SX value: dag-cbor encode -> sha2-256 ->
|
|
multihash -> CIDv1 (dag-cbor codec). *)
|
|
let cid_from_sx (v : value) : string =
|
|
let cbor = Sx_cbor.encode v in
|
|
let digest = unhex (Sx_sha2.sha256_hex cbor) in
|
|
cidv1 codec_dag_cbor (multihash mh_sha2_256 digest)
|