perathos
docs/vrl-proof-bundle/proofs / shipping-linear-sum-v1

typed proof

vrl.shipping.linear-sum.v1

Domain-specific zero-knowledge proof entry for the VRL Proof Bundle proofs[] array. Proves that hidden per-component shipping costs sum to a public expected total under a committed pricing policy, with each committed value provably in [0, 2^28).

proof_typevrl.shipping.linear-sum.v1
proof_version1.0.0
domainshipping
schemepedersen-linear-nizk-v1 + vrl-zk-range-bit-or-v1
grouprfc3526-group14-qr (RFC 3526 group 14, order-q QR subgroup, 2048-bit safe prime)
trusted setupNone. No-trusted-setup Fiat-Shamir NIZK.
reference impl@perathos/vrl-zk-shipping
spec statusDraft amendment for vrl-protocol/spec v0.2.0

What it proves

For six private committed components — base rate, fuel surcharge, residential fee, oversize fee, other accessorials, customer discount — a verifier learns, without seeing any component value, that:

  • each committed value is a non-negative integer below 2^28 (Chaum-Pedersen bit-decomposition range proof);
  • the signed linear combination of the six values equals a public expected_total_cents (Schnorr-style Fiat-Shamir NIZK);
  • the proof transcript is bound to quote_id, policy_hash, and the range proofs, preventing replay or cross-quote substitution;
  • the entry as a whole is hash-bound — any tampering with statement, payload, or metadata invalidates hash.

What it does not prove yet

  • That the carrier rate sheet itself is truthful or current.
  • That shipment dimensions, weight, or service classification are correct.
  • That a private rate-card row belongs to an approved Merkle root (planned: vrl.shipping.rate-membership.v1).
  • That an AI model selected the correct shipping method.

Entry shape

{
  "proof_type": "vrl.shipping.linear-sum.v1",
  "proof_version": "1.0.0",
  "domain": "shipping",
  "scheme": "pedersen-linear-nizk-v1+vrl-zk-range-bit-or-v1",
  "group": "rfc3526-group14-qr",
  "created_at": "2026-05-12T17:42:11.823Z",
  "statement": {
    "quote_id": "...",
    "policy_hash": "sha256:...",
    "expected_total_cents": 13420,
    "billed_total_cents": 13999,
    "variance_cents": 579,
    "dispute_status": "review",
    "formula": "base + fuel + residential + oversize + other_accessorials - discount",
    "component_order": [ { "key": "baseRateCents", "coefficient": 1 }, ... ],
    "range_bits": 28,
    "input_commitment": "sha256:<digest of commitments+range_proofs>"
  },
  "payload": {
    "commitments":      { "baseRateCents": "0x...", ... },
    "range_proofs":     { "baseRateCents": { "scheme": "vrl-zk-range-bit-or-v1", "bits": 36, ... }, ... },
    "proof":            { "scheme": "pedersen-linear-nizk-v1", "group": "...", "challenge": "0x...", ... },
    "group_parameters": { "group": "...", "hGenerator": "0x...", "hDerivation": {...}, ... }
  },
  "privacy": {
    "privateAmountsHidden": true,
    "rangeProof": "vrl-zk-range-bit-or-v1",
    "rangeBits": 28
  },
  "hash": "sha256:<canonical digest of the entry, excluding the hash field>"
}

Verifier behavior

A generic VRL Proof Bundle consumer that encounters this entry should:

  1. Dispatch on proof_type and proof_version.
  2. Recompute the canonical hash and compare to hash.
  3. Verify each per-component range proof (bit-OR proofs + aggregation against the parent commitment).
  4. Verify the Schnorr linear-relation proof against the Fiat-Shamir challenge derived from the transcript.
  5. Return { ok: true | false, reason? } without aggregating other entries — each entry stands or falls on its own.

Stability

This is the v1 proof type. Backward-incompatible changes — different group, different range-proof scheme, expanded statement fields — will be published as vrl.shipping.linear-sum.v2, not as a silent revision of v1.