Skip to content

JCS Conformance Runner

vauban-x402-jcs-conformance is the reference Rust 5th-implementation runner for the JCS canonical preimage discipline defined in the IETF Internet-Draft draft-vauban-x402-stark-receipts (Section 7 ; "Canonical Preimage Discipline").

It provides reproducible, byte-identical validation of the preimage rule

JCS_hash = SHA-256(JCS(object))      // RFC 8785

against publicly available JCS conformance suites. STARK receipts in the stark-vauban-pay-v1 format are proven against the canonical preimage produced by this discipline, so a divergence of even one byte in canonicalisation is detectable before a proof is ever computed.

Install

[dependencies]
vauban-x402-jcs-conformance = "0.1"

Public API

use serde_json::Value;
use vauban_x402_jcs_conformance::{
    jcs_canonical_bytes, jcs_hash, jcs_sha256, validate_pair_invariant,
};

// Canonical JCS bytes (RFC 8785).
let body: Value = serde_json::json!({"b": 2, "a": 1});
let canonical: Vec<u8> = jcs_canonical_bytes(&body)?;

// (base64(canonical_bytes), "sha256:<64-hex>") tuple.
let (b64, digest): (String, String) = jcs_hash(&body)?;
assert!(digest.starts_with("sha256:"));
assert_eq!(digest.len(), "sha256:".len() + 64);

// Digest only (lowercase hex, "sha256:" prefix).
let only_digest: String = jcs_sha256(&body)?;

// Two semantically-equivalent objects yield identical canonical bytes.
let left  = serde_json::json!({"a": 1, "b": 2});
let right = serde_json::json!({"b": 2, "a": 1});
assert!(validate_pair_invariant(&left, &right)?);

All fallible entry points return Result<_, JcsError>.

Coverage

Cross-validated byte-identical against publicly available JCS conformance suites :

Vector class Vectors Pair invariants Status
AP2 OMH v0 9 9 byte-identical
CTEF / APS v1 10 7 byte-identical
privacy_class v0.1 13 12 byte-identical
Cumulative 32 28 32 / 32 OK

The canonical bytes produced by this crate are byte-identical to four independent RFC 8785 reference implementations across Python, TypeScript, Go and Java. The underlying JCS serializer is the upstream serde_jcs crate (Apache-2.0 / MIT).

Why a preimage runner matters

A STARK proof binds a public statement to a hash. If two implementations canonicalise the same logical receipt to different bytes, they compute different hashes, and a verifier on one stack rejects a proof produced on another. The conformance runner removes that ambiguity : every implementation that agrees on the JCS preimage agrees on the hash, and therefore on the proof statement. This is what makes a receipt format portable across independent implementations rather than tied to one codebase.

Provenance