Expand description
The atproto data model, its canonical encoding, and the CIDs that names.
atproto’s records are exchanged as JSON and identified as DAG-CBOR. The two are the same data model wearing different clothes, and the identity of a record — the CID a commit signs, a link quotes and an MST keys on — is the sha-256 of the DAG-CBOR bytes. Everything downstream of that hash depends on there being exactly one such encoding per record, which is why this crate is three narrow pieces rather than a serializer:
-
Valueis the data model: the values that have an encoding, and nothing else. Building one from JSON is where every rejection happens. -
dag_cborturns one into bytes, and cannot fail. It reads them back too, which is a stricter job: seedag_cbor::decode. -
Cidis the hash of those bytes, and the only string form atproto permits for it. -
mstis the fourth piece and the largest: the Merkle search tree a repository is keyed by, along with the two pure functions its shape comes from.
use didbot_data::{dag_cbor, Value};
let record = serde_json::json!({
"$type": "com.example.thing",
"text": "quernstone",
"count": 1,
});
let value = Value::object_from_json(&record).expect("a data-model record");
let bytes = dag_cbor::encode(&value);
assert_eq!(dag_cbor::cid(&value), didbot_data::Cid::of_dag_cbor(&bytes));§Why this is its own crate
It sits below everything that would use it and depends on none of them. A
repository needs it to name a record, a Merkle search tree needs it to key
one, a commit needs it to sign one, and a CAR file needs it to frame one.
The tree is here, because a tree is nothing but keys and the encoding of
its own nodes; the commit and the CAR are in didbot-repo, because
they need a signing key and this crate deliberately depends on nothing.
§What this crate does not do
It is not a serde data format: records arrive here as serde_json::Value from
an HTTP body, and a derive-driven path would only add a second way to
produce bytes that must be identical to these.
The conformance suite this is held to is data-model/ in the vendored
upstream vectors; see docs/conformance.md.
Re-exports§
pub use cid::Cid;pub use cid::CidError;pub use cid::RawHasher;pub use value::DataError;pub use value::ErrorKind;pub use value::Value;
Modules§
- cid
- Content identifiers, decoded rather than glanced at.
- dag_
cbor - The DAG-CBOR encoding, which is the canonical form a record is hashed in.
- encoding 🔒
- Base32 and base64, in the two exact dialects atproto uses.
- mst
- The Merkle search tree a repository is keyed by.
- value
- The atproto data model: the values a record is made of.