Skip to main content

Crate datumesh_core

Crate datumesh_core 

Source
Expand description

Core of the Datumesh protocol: strict JSON and RFC 8785 JCS, canonical forms of scalars, cells, references, descriptors and receipts, cell URIs, key documents, response envelopes, unit resolution and offline receipt verification.

The rules are those of the specification, SPEC.md and units.md at https://github.com/datumesh-com/datumesh-spec. Section numbers in this documentation refer to SPEC.md.

Every function that can fail returns an Error carrying one of the codes of SPEC 10.2 (ErrorCode), the JSON path where the failure was found, and a human detail. Nothing in this crate panics on any input, touches the network (except fetch_keys behind the fetch feature), keeps global state or logs.

verify runs SPEC 10.1. Keys are an input (Keys); recomputation (step 7) asks a Resolver for the descriptor, the input receipts, the manifests of slice entries and the evaluation (with its lineage), lazily (MapResolver holds them in maps). Since spec-0.4.0 a receipt’s lineage may cite whole slices of cells (Slice, Manifest), and descriptors may carry signature.order and argument extents (FunctionDescriptor). Since spec-0.4.1 a mesh may answer pending (check_envelope_any, Pending), and cross-mesh resolution reads a host’s mesh document (resolve_mesh, MeshDoc); a verifier needs neither. Feature sign adds SigningKey and ReceiptBuilder, which make receipts that verify byte for byte like the specification’s. Feature fetch (fetch_keys) is deprecated since 0.3.1 and removed at 1.0: fetch key documents with your own HTTP client and pass the response to keys_from_response.

use datumesh_core::{verify, Keys, Level};

let receipt = br#"{"asof":"2024-03-16T09:00:00.000000Z","cell":{"args":{"base":{"type":"string","value":"EUR"},"date":{"type":"date","value":"2024-03-15"},"quote":{"type":"string","value":"USD"}},"fn":"fx_rate","fn_hash":"7b58ecb8fd23b644c87951d0bd609790ff547cbb23fed27186c669ce2ce0aa80","ns":"rates.example.org"},"computed_by":"rates.example.org#d712b32a2cc5cb7c","inputs":[],"issued":"2024-03-16T09:00:00.000000Z","licence":"CC-BY-4.0","proto":"datumesh/1","publisher":"rates.example.org","sig":"ddf61d49ff6593f7b0d94c76f19fefdd27f47778740b3666fc1c3315ec00c5d216f887c4078deb05c83d4d743453c6fecc568473663b3282ac4eda8c3eadcf01","summary":"1 EUR was worth 1.0892 USD at the 15 March 2024 reference rate.","tx":"2024-03-15T16:00:00.000000Z","type":"number","valid":{"date":{"type":"date","value":"2024-03-15"}},"value":"1.0892"}"#;
let key_doc = br#"{"host":"rates.example.org","keys":[{"alg":"ed25519","id":"d712b32a2cc5cb7c","public":"843baeb22bfd0364fb1b7262b367fb3202e7886c69a070fecf8e343fedb1eabf","valid_from":"2020-01-01T00:00:00.000000Z","valid_to":"2024-06-01T00:00:00.000000Z"}],"proto":"datumesh/1"}"#;

let mut keys = Keys::new();
keys.insert_response("rates.example.org", 200, Some(key_doc));
let result = verify(receipt, &keys, None, None);
assert!(result.ok);
assert_eq!(result.level, Some(Level::Signed));
assert_eq!(result.hash.as_deref(), Some("19a5fe3a744c5792f747fb4c286ce396ab44b95922de4f07937502fe595b6f81"));

Modules§

json
Strict JSON (SPEC 6.1, I-JSON) and the RFC 8785 JSON Canonicalization Scheme (SPEC 6.2).
lexical
Lexical forms: names (2), scalars (3), hex, licences, key references (9.1) and units (7.1).
testkit
A conformance kit for Resolver implementations (feature testkit).

Structs§

ArgDecl
An argument declaration: {"type", "valid"}, plus unit for numbers.
Cell
A cell (4.4): a function, pinned by hash, applied to arguments. May denote a slice.
CellRef
A cell reference (4.3): what a cell URI denotes before the function name is resolved.
Descriptor
A function descriptor (7) in its spec-0.3.0 form: signature, code and declared inputs.
Envelope
A checked envelope.
EnvelopeExtras
The members of a checked envelope that Envelope has no field for, because they were added to SPEC 5.5 after it was frozen (0.3.0): see check_envelope_extras.
Error
A failure: its code, the JSON path (or URI part) where it was found, and a human detail.
Evaluation
What evaluating a cell gave (Resolver::evaluation): the value and, when the resolver has it, the lineage: the inputs entries the evaluation read (receipt hashes and slice entries), whose receipts and manifests the resolver offers for those the receipt under verification does not list.
FunctionDescriptor
A function descriptor (7) with the optional members of spec-0.4.0: signature.order and argument extent. Absent, it is the Descriptor of spec-0.3.0, byte for byte and hash for hash (From<Descriptor>, to_descriptor).
InvalidRequest
A malformed request description (5.5 step 5): the caller’s mistake, not an E_* code.
Key
One published key.
KeyDoc
A host’s key document (9.2), checked.
Keys
The keys a verifier has resolved: per host, a key document or the failure resolving it. A host that was never resolved behaves as E_KEY_UNAVAILABLE (SPEC 11).
Manifest
A slice manifest (15.13, spec-0.4.0): {"members": [...], "slice": {...}}, the member receipt hashes (ascending, unique, at most 1,048,576) and the slice object. It is fetched by its entry slice:<slice id>:<members hash>, where the members hash is SHA-256 of the canonical bytes of the members array (of [] for an empty slice).
MapResolver
A Resolver backed by maps: descriptors by function hash, receipts by receipt hash, manifests by slice entry, and evaluated values (with lineages) by cell id. It is what the vectors’ recompute object describes (SPEC 11): the descriptor goes under the receipt’s cell.fn_hash, the inputs under their hashes, the manifests under their entries, and value (and lineage) under the receipt’s own Cell::id.
MeshDoc
A checked mesh document (9.6): the host’s bindings URL and its known endpoint templates. Unknown members are dropped.
Pending
A pending envelope (5.5, spec-0.4.1): the job, an estimate, the URL to poll and the original request echoed. Build one with Pending::new (a mesh), or get one from check_envelope_any (a client).
Quote
A price quote (payment_required).
Receipt
A receipt (8.1) that has passed verification steps 1-4: strict JSON, structure, canonical form and consistency. Its signature has not been checked; use crate::verify.
ReceiptBuilder
The members of a receipt before it is signed; sign is the only way to turn it into a Receipt.
Request
What the client asked for, for the binding of 5.5 step 5.
ResolvedMesh
A host accepted by cross-mesh resolution: its key document and its mesh document.
Returns
The declared return: a type, with a unit exactly when it is number.
Signature
A function signature.
SigningKey
An Ed25519 signing key, from its 32-byte seed (RFC 8032 5.1.5).
Slice
A slice object (4.4, spec-0.4.0): a cell object with at least one argument open ("*") or bounded by a range object {"hi", "lo", "type"}, or a version slice {"cell", "from", "to"}. Its slice id is SHA-256 of its canonical bytes; for an unbounded slice it is the id of the cell object with the markers.
VerifyResult
The outcome of verify.

Enums§

AnyEnvelope
The answer to a request: a Pending envelope, or one of the eight outcomes an Envelope holds, with its EnvelopeExtras (see check_envelope_any).
Arg
An argument: a typed scalar, or the slice marker "*" (4.2).
ErrorCode
One variant per E_* code of SPEC 10.2 (spec-0.4.1). Non-exhaustive: codes added by later revisions of the specification are additions.
Extent
The cells a slice over an argument enumerates (7, spec-0.4.0): the argument declaration’s optional extent.
Fault
A formula evaluation fault (SPEC 5.5, 15.11; spec-0.4.0): the optional fault member of a not_covered envelope. The cell has no value, deterministically; this is not missing data. These are formula codes, not verification codes, so they are not ErrorCodes.
Level
How far a receipt verified.
Outcome
The eight outcomes of 5.5.
RateSide
One side of a rate: a currency code or an argument reference.
Retrieval
What one HTTPS GET of a document gave, as the caller’s HTTP client saw it.
Scalar
A typed scalar value in its one canonical lexical form.
Trust
The mesh’s trust label (5.5).
Type
One of the six scalar types (3).
Unit
A unit in a signature (7.1).

Traits§

Resolver
What step 7 of SPEC 10.1 obtains: the descriptor, the input receipts (slice members included), the manifests of slice entries, and the evaluation. This crate evaluates no functions and fetches nothing; the caller supplies a resolver, and verify asks it only for what step 7 reaches for the receipt at hand:

Functions§

canonicalize_cell
Canonical bytes of a cell given as JSON text (4.4, 6.2). Slices are allowed.
canonicalize_descriptor
Canonical bytes of a function descriptor given as JSON text (7, 6.2), order and extent included (spec-0.4.0; see FunctionDescriptor).
canonicalize_receipt
The signed payload of a receipt given as JSON text: canonical bytes without sig (8.3). Runs verification steps 1-4 first.
canonicalize_ref
Canonical bytes of a cell reference given as JSON text (4.3, 6.2).
canonicalize_scalar
Canonical bytes of a typed scalar given as JSON text (4.1, 6.2).
canonicalize_slice
Canonical bytes of a slice object given as JSON text (4.4, 6.2; spec-0.4.0).
cell_hash
The cell id of a cell given as JSON text: SHA-256 of its canonical bytes (4.4, 6.3).
cell_uri_from_https
The cell URI served at an HTTPS URL on mesh host mesh (5.3), by stripping the prefix. None when the URL is not under https://<mesh>/cell/.
check_envelope
Checks a response envelope (5.5) in the order of its procedure: strict JSON, members, HTTP status, the receipt through step 6 of 10.1, the binding to request, then trust and superseded_by. Never touches the network. A not_covered envelope’s fault (spec-0.4.0) is checked and accepted; check_envelope_extras also returns it.
check_envelope_any
Checks a response envelope (5.5) of any of the nine outcomes, pending included (spec-0.4.1), in the order of its procedure, and binds it to request: a pending envelope’s echoed request to the request made (and its job to the job polled, when request has one), any other outcome to the original request’s cell id and asof, whether it answers the /cell request or the job URL. E_JOB_UNKNOWN is accepted only in a bad_request answering a job URL (request with a job). Never touches the network.
check_envelope_extras
check_envelope, also returning the members Envelope has no field for (EnvelopeExtras): the fault of a not_covered envelope, one of the six formula evaluation faults of SPEC 5.5 (E_ENVELOPE for any other value, or on another outcome).
fetch_keysDeprecated
Fetches https://<host>/.well-known/datumesh.json and checks it (9.2, 9.3).
format_uri
Writes the one URI of a cell reference (5.2). format_uri(&parse_uri(u, s)?) == u for every accepted u.
function_hash
The function hash of a descriptor given as JSON text (7, 6.3), order and extent included.
https_url
The HTTPS URL of a cell URI on mesh host mesh (5.3): https://<mesh>/cell/<rest>. mesh must be a DNS name (E_CANON_NAME), uri must start with cell:// (E_PARSE_URI).
key_id
The key id of a public key: the first 16 hex digits of SHA-256 over its 32 bytes (9.1).
keys_from_response
Resolves a host’s keys from the HTTPS response to GET https://<host>/.well-known/datumesh.json (9.3). body is None when a 200 response carried no document.
parse_uri
Parses a cell URI against a function signature (5.4), reporting the first failure in the order 5.4 defines.
receipt_hash
The receipt hash (8.3), after steps 1-4.
receipt_payload
The canonical bytes of a receipt without sig (8.3), after steps 1-4.
resolve_mesh
Cross-mesh resolution of host (9.6, spec-0.4.1), from what GET https://<host>/.well-known/datumesh.json and GET https://<host>/.well-known/datumesh-mesh.json gave. Separate from verification, which never needs it; it fetches nothing. In the order of 9.6, the first failure is reported:
resolve_with
Substitutes a checked cell’s arguments into a checked descriptor’s return unit.
resolved_unit
The unit of a cell’s value (7.1, units.md 3), from the descriptor and cell JSON texts.
resolved_unit_value
resolved_unit over parsed JSON values.
sha256
SHA-256 of data.
sha256_hex
SHA-256 of data as 64 lowercase hex digits.
verify
Verifies a receipt (10.1). Never touches the network and never panics.
verify_ed25519
Verifies an Ed25519 signature with the rules of SPEC 10.1 step 6 (libsodium’s crypto_sign_verify_detached): reject S >= L, non-canonical A or R, points that do not decode, small-order A or R; then accept exactly when the encoding of [S]B - [k]A equals R (the cofactorless equation). Mixed-order keys are accepted.

Type Aliases§

Args
An argument map, keyed by argument name (byte order equals JCS order for names).
Result
Shorthand used throughout the crate.