Skip to content

fixtures: stark-vauban-pay-v1 v0 ; Axis 1 STARK receipt conformance - #2413

Closed
seritalien wants to merge 1 commit into
x402-foundation:mainfrom
vauban-org:fixtures-stark-vauban-pay-v1-v0
Closed

fixtures: stark-vauban-pay-v1 v0 ; Axis 1 STARK receipt conformance#2413
seritalien wants to merge 1 commit into
x402-foundation:mainfrom
vauban-org:fixtures-stark-vauban-pay-v1-v0

Conversation

@seritalien

Copy link
Copy Markdown

Per @andysalvo's greenlight on #2398 ("STARK Axis 1 under `fixtures/stark-vzk2p-v1/v0/` as a separate PR also makes sense"), opening this PR with the Vauban-anchored Axis 1 fixture set.

Note on naming : the proof scheme was renamed from `stark-vzk2p-v1` to `stark-vauban-pay-v1` per Vauban brand discipline (the `vzk2p` codename is internal-only, the public surface uses the `vauban-pay` brand). The directory path follows the rename.

What this PR adds

`fixtures/stark-vauban-pay-v1/v0/` with :

  • `manifest.json` ; proof scheme, proof system, anchor chain, cross-axis interop bindings
  • `README.md` ; 4-vector table, cross-axis bindings, open question on `BoundReceipt` vs flat `receipt_core` shape
  • `vectors/0001-baseline.json` ; canonical reference, PASS
  • `vectors/0002-field-name-load-bearing.json` ; `payment_hash` -> `paymentHash` rename, FAIL, divergent digest pinned
  • `vectors/0003-stark-proof-tamper-evidence.json` ; 1-byte `proof_blob_b64` mutation, FAIL, divergent digest pinned
  • `vectors/0008-interop-shared-payment-hash.json` ; key-reorder + Axis 2/3 interop bind, PASS

Total : 4 vectors, 1 cross-vector interop bind.

Cross-axis interop bindings

Every vector in this set shares the canonical values with sibling coalition fixture sets so a conformance harness can validate the cross-axis bindings byte-for-byte :

This is the cross-axis substrate the coalition discussed on #2357 : the four axes (substrate, STARK, hybrid-PQC, work-receipt) compose without overlap, each axis independently verifiable, with shared binding values that let a downstream conformance suite validate the interop is real.

Canonicalisation discipline alignment with #2326 v3

This fixture set adopts the v3-converged discipline :

  • JCS (RFC 8785) is the only canonicaliser ; SHA-256 of canonical bytes, lowercase hex
  • Field names treated as load-bearing opaque UTF-8 bytes (the `paymentHash` vector 0002 proves the rule)
  • Asymmetric failure surface : producer-loud (reject non-canonical input at wire) ; verifier-silent (any equivalent canonical input accepted)
  • `canon_version` field shipped on every vector ; good-discipline default even though `stark-vauban-pay-v1` is not under MiCA Art. 80 retention by default

Open question (intentionally surfaced rather than hidden)

The `BoundReceipt` Rust type in `crates/zkpay-x402/src/lib.rs` is a nested structure (`receipt: R`, `action_ref: Option<[u8; 32]>`). The fixture's `receipt_core` is a flat structure that combines VPSF Claim fields with x402 wire extensions for digest purposes. The mapping between the Rust type and the canonical fixture shape is documented in the README §Open Questions. This is an open TSC item on #2357 that the fixture surfaces explicitly rather than papering over.

Two resolutions are plausible :

  1. The Rust type adapts to match the flat `receipt_core` shape (breaks the Phase 2a serialisation invariant in the spec)
  2. The fixture's canonical preimage is computed by a dedicated `receipt_core_from_bound_receipt(BoundReceipt) -> ReceiptCore` adapter (preserves the Rust type, makes the canonical surface explicit)

Vauban's working preference is option 2 (clean separation between in-memory type and canonical wire form). Feedback welcome.

Cross-implementation status

  • Author : Vauban Pay (`@seritalien`)
  • Self-validated : 4/4 vectors PASS-or-FAIL as expected, 1/1 interop bind under serde_jcs (5th-impl per the substrate matrix in fixtures: canonicalisation-substrate v0 ; 53-vector in-tree mirror #2412)
  • Cross-implementation validation : Phase 2 ask ; happy to coordinate runners with AlgoVoi / FeedOracle / andysalvo for parity with the substrate coverage (5-impl 53/53 + 37/37)

Conformance runner

`runner-stark-axis-1` is TBD ; expected result 4/4 vectors + 1/1 interop bind. Contribution welcome ; the privacy_class runner pattern from gist `seritalien/b0b86baabae33e289fdb6d2f3fb30130` transfers cleanly (only delta is the field naming from `attestation_body` to `receipt_core` and the digest field name).

Related fixture sets

License

Apache 2.0

Refs #2357 #2326 #2411 #2398 #2332

Vauban-authored Axis 1 conformance fixture set, paralleling the
coalition structure :
  Axis 0 ; AlgoVoi substrate (this PR's sibling, x402-foundation#2412)
  Axis 2 ; FeedOracle hybrid-PQC (PR x402-foundation#2411)
  Axis 3 ; andysalvo work-receipt (PR x402-foundation#2398)

Proof scheme : stark-vauban-pay-v1
Proof system : Stwo Circle STARK M31 (FRI-based, post-quantum)
Anchor chain : Starknet
Canonicaliser : RFC 8785 (JCS), digest SHA-256 lowercase hex

Four vectors :
  0001-baseline                          PASS  canonical reference
  0002-field-name-load-bearing           FAIL  payment_hash -> paymentHash
  0003-stark-proof-tamper-evidence       FAIL  proof_blob 1-byte mutation
  0008-interop-shared-payment-hash       PASS  key-reorder + Axis 2/3 bind

Cross-axis interop bindings :
  payment_hash 2ed186eb... shared with FeedOracle Axis 2 (PR x402-foundation#2411)
  action_ref   10d8a38c... shared with andysalvo Axis 3 (PR x402-foundation#2398)

Discipline alignment with x402-foundation#2326 v3 :
  canon_version field shipped on every vector (good-discipline
    default ; stark-vauban-pay-v1 not under MiCA Art. 80 retention
    by default, but the field discipline is the same)
  Field names treated as load-bearing opaque UTF-8 bytes
  Asymmetric failure surface (producer-loud / verifier-silent)

Open question flagged in README §Open Questions :
  BoundReceipt<R> Rust type (nested receipt + Option<action_ref>)
  does NOT match the flat receipt_core shape used in this fixture.
  The receipt_core combines VPSF Claim fields with x402 wire
  extensions for digest purposes. This is an open TSC item on
  x402-foundation#2357 ; the fixture documents the field mapping rather than
  papering over it.

Conformance runner runner-stark-axis-1 is TBD ; contribution
welcome. Expected result : 4/4 vectors pass + 1/1 interop bind
(vector 0008 digest equals vector 0001 digest).

Refs x402-foundation#2357 x402-foundation#2326 x402-foundation#2411 x402-foundation#2398 x402-foundation#2332
@vercel

vercel Bot commented May 21, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Coinbase Team on Vercel.

A member of the Team first needs to authorize it.

@seritalien

Copy link
Copy Markdown
Author

Opening a TSC question on the BoundReceipt<R> shape before we freeze the wire format in this PR. Two options on the table: Option 1 ; keep BoundReceipt<R> as the canonical wire-level type (generic over receipt variant, matches the current SDK surface). Option 2 ; introduce a flat receipt_core adapter at the wire boundary, keeping the generic confined to the SDK layer. Vauban's position is Option 2: wire format stability matters more than type-level elegance at the protocol boundary, and the generic can live in the SDK without leaking into the JSON serialization shape. Requesting TSC guidance before we merge so the fixture vectors can reference the canonical field names.

@phdargen

phdargen commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Thanks for participating in the x402 ecosystem.

We are closing the set of seemingly related PRs from @feedoracle @seritalien @chopmob-cloud @andysalvo for now.
These PRs are hard to review as a group: they appear interconnected with discussion spread across long, cross-linked threads. The changes also seem overly verbose and read more like promotion of partner projects rather than neutral, foundation-scoped additions.

Please make your case in an Issue first, with a concise description of the problem, scope and value add,
respecting our guidelines for AI-assisted contributions .
Once there is alignment, submit one PR with a minimal diff that is neutral, standalone and does not rely on or reference 3rd party services

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants