freenet_git_encoding/lib.rs
1//! Wire-format encoding pin for freenet-git.
2//!
3//! This crate is the single source of truth for two byte formats that both the
4//! contract WASM and the on-host helpers must agree on exactly:
5//!
6//! 1. **Signed-payload encoding** ([`signed`]) — the byte string fed into
7//! ed25519 signatures. Hand-rolled length-prefixed concatenation. Every
8//! element (including the domain prefix) is wrapped in a 4-byte
9//! little-endian length followed by raw bytes.
10//!
11//! 2. **Canonical encoding for content-addressed hashes** ([`canonical`]) — a
12//! minimal deterministic CBOR encoder for the structured types we hash to
13//! derive bundle ids. RFC 8949 §4.2.1 deterministic rules: definite-length
14//! items, smallest-encoding-of-integers, sorted map keys.
15//!
16//! ## Why "v1" appears in domain prefixes
17//!
18//! Every signed payload starts with a domain string like
19//! `b"freenet-git/v1/ref-update"`. The `v1` is the wire-format version. When
20//! either of the two encodings here changes in a way that produces different
21//! bytes for the same input, the domain version must bump to `v2` in lockstep
22//! with a contract WASM change. Without the version bump, signatures from the
23//! two implementations would silently disagree and fork the network.
24
25#![deny(unsafe_code)]
26#![warn(missing_docs)]
27
28pub mod canonical;
29pub mod signed;
30
31/// The current wire-format version. Embedded in every domain prefix.
32pub const WIRE_VERSION: &str = "v1";
33
34/// Compute BLAKE3-256 of a byte slice.
35///
36/// Returned as a `[u8; 32]` so callers can convert into whatever hash type
37/// they use without depending on the `blake3` crate directly.
38pub fn blake3_32(input: &[u8]) -> [u8; 32] {
39 *blake3::hash(input).as_bytes()
40}