Paper II — JSON✯Atomic
The Identity Layer
Normative keywords per RFC 2119/8174 (MUST/SHOULD/MAY) apply.
The Problem (A True Story)
November 2023. A smart contract audit. $12 million at stake.
The contract hashed a JSON document to verify agreement between parties. Both parties signed the "same" document. Both hashes were different.
// Party A's serializer produced:
{"amount": 12000000, "recipient": "0x7a3f..."}
// Party B's serializer produced:
{"recipient": "0x7a3f...", "amount": 12000000}
Same meaning. Different bytes. Different hashes. The contract rejected both signatures as invalid.
The fix took three weeks and $200,000 in legal fees. The root cause? JSON doesn't guarantee key order.
This was not a bug. This was a design flaw in every system that treats JSON as a serialization format without canonicalization.
JSON✯Atomic eliminates this class of failure entirely.
I. The Principle
**Same semantics ⇒ same bytes ⇒ same hash ⇒ same identity.**
use json_atomic::canonize;
// These two objects have the same meaning
let obj_a = json!({"b": 1, "a": 2});
let obj_b = json!({"a": 2, "b": 1});
// JSON✯Atomic produces identical bytes
let bytes_a = canonize(&obj_a);
let bytes_b = canonize(&obj_b);
assert_eq!(bytes_a, bytes_b);
// Both produce: {"a":2,"b":1}
// Therefore identical hashes
let hash_a = blake3::hash(&bytes_a);
let hash_b = blake3::hash(&bytes_b);
assert_eq!(hash_a, hash_b);
// Both produce: b3:7f3a9b2c4d5e6f7a8b9c0d1e2f3a4b5c...
This is not a feature. It is the foundation upon which all other papers rest.
- Paper I requires canonical tuples to chain
- Paper III requires canonical capsules to verify
- Paper IV requires canonical ASTs to prove
- Paper V requires canonical receipts to audit
- Paper VI requires canonical policies to execute
The byte is the unit of law.
II. Install It Now
# Add to your Rust project
cargo add json-atomic
# Or install the CLI
cargo install logline-cli
use json_atomic::{canonize, verify, Error};
fn main() -> Result<(), Error> {
let document = json!({
"who": "did:logline:agent:alice",
"did": "transfer",
"this": {"amount": 1000, "to": "bob"},
"when": "2026-02-05T14:30:00Z"
});
// Canonicalize
let canonical_bytes = canonize(&document)?;
// Hash (identity)
let identity = blake3::hash(&canonical_bytes);
println!("Identity: b3:{}", hex::encode(identity.as_bytes()));
// Verify another serialization matches
let other_bytes = r#"{"did":"transfer","this":{"amount":1000,"to":"bob"},"when":"2026-02-05T14:30:00Z","who":"did:logline:agent:alice"}"#;
assert!(verify(&document, other_bytes.as_bytes())?);
Ok(())
}