Skip to content

PaymentIntent & Composition

A PaymentIntent is not a new type. It is a specialization of the VPSF Claim sextuplet.

PaymentIntent ≡ Claim sextuplet

VPSF field PaymentIntent specialization
Subject payer_stealth_addr — stealth address derived from payer Vauban-auth identity
Predicate "Owes amount of currency to merchant_pseudonym for service_id within deadline"
Evidence Stwo STARK proof of intent validity + signature (ML-DSA-65 Phase 2+ / Ed25519 MVP)
TemporalFrame expiry (replay window) + not_before (debounce)
RevelationMask Per-field Open / Commit / ZK / Encrypted
Anchor ProofChainAnchor.cairo L3 Madara (Phase 0-3 Starknet-first)

The same shape, with different predicates, gives you:

Type Predicate
PaymentIntent "Owes X to Y by deadline"
SettlementReceipt "Was paid X by Y on date"
RefundClaim "Refunds prior receipt Z"
DelegationGrant "Authorizes agent A to spend ≤ N for service P"
HumanityClaim "Subject is a unique human" (Glacis, already in production)

Same Claim trait. Same composition operators. Same audit surface.

Sprint-661 evidence

vauban-zkpay-types crate landed Sprint-661 (sealed 2026-05-12). 11/11 tests pass. Stwo dependencies pinned (stwo=2.2.0 + stwo-cairo-adapter=1.2.2). PaymentIntent / SettlementReceipt / RefundClaim / DelegationGrant structs implement the Claim trait. CBOR roundtrip + SHA-256 content-addressing + 100 proptest fuzz tests passing. VERIFIED.

The five operators

∧ Conjunction — same-subject HARD INVARIANT (MVP)

C1 ∧ C2  valid iff  both valid AND C1.subject == C2.subject

Canonical use case — regulated merchant flow:

PaymentIntent ∧ HumanityClaim

A merchant required to attest non-bot payers binds the payment to a Glacis humanity Claim sharing the same subject.

C-1 HARD INVARIANT, MVP enforced

VCA v0.1.0 enforces same-subject as a hard invariant. vauban-claim/src/composition.rs:301-303 returns SubjectMismatch unconditionally for any cross-subject Conjunction attempt. This is not a bug — it is the v0.1.0 limit (C-1).

Sprint-663 (planned 2026-07-13) includes an explicit negative test: composition cross-subject MUST fail. The red test enforces the invariant.

Workaround for cross-domain binding: derive both subjects from the same credit_secret with the same app_domain (spec v0.3 §3.3.5). Implemented via Vauban-auth derived keys.

Cross-subject linkage_proof contract is NOT in MVP scope. Tracked as VCA v0.2 issue upstream.

→ Delegation — principal-to-agent (Phase Agentic Q2 2027)

C_principal → C_agent  valid iff
    C_principal authorizes C_agent for predicate, scope, cap, duration

Canonical use case — CC agents pay-per-API:

DelegationGrant → AgentPayment

The principal issues a capped DelegationGrant ("agent A may spend up to 50 USDC for service P within 24h"). The agent's subsequent AgentPayment is valid iff the chain composes back to a valid principal Grant.

Cap circuits with explicit chain-depth limit prevent A6 Delegation Inflation attacks (see threat model).

⊕ Aggregation — batched settlement (Sprint 663, Q3 2026)

⊕_i C_i  =  batch root with all C_i included as Merkle leaves

Canonical use case — batch K=10 settlement:

⊕ {PaymentIntent_1, ..., PaymentIntent_10}

Target gas savings ~50% vs K independent settlements. Stwo recursion (v2.0.0+) makes this verification cost ≈ constant in batch size.

Aggregation does not require same-subject (unlike Conjunction). It's a Merkle commitment over heterogeneous Claims.

▷ Restriction — narrowed RevelationMask (MVP)

C ▷ mask  =  C with revelation mask narrowed

Canonical use case — auditor revenue ranges without linkability:

SettlementReceipt ▷ AuditorMask  // amount: range-only, merchant_id: hidden

The auditor receives a Claim revealing only what compliance requires. The original SettlementReceipt is unchanged.

¬ Revocation — nullifier-set invalidation (MVP)

¬C  =  C invalidated in the nullifier set

Canonical use case — refund cancels prior receipt:

¬SettlementReceipt  // tracked in ProofChainAnchor.cairo nullifier set

A subsequent verifier presented with the revoked SettlementReceipt rejects it because the nullifier was already burned.

Threat model: the composition adversary class

Algebraic composition introduces a novel adversary class distinct from classical ZK soundness/zero-knowledge. Six enumerated vectors (spec v0.3 §3.3):

ID Attack Mitigation
A1 Cross-subject correlation — link two Claims via different-identity subjects to forge a composition Same-subject HARD INVARIANT + nullifier set
A2 Temporal skew — replay via TemporalFrame not_before / expiry window mismatch Strict validation, ≤5min clock skew (K8s NTP per ADR-017)
A3 Mask widening — broaden RevelationMask post-issuance to leak extra fields Field-by-field commit + cryptographic binding to Evidence
A4 Operator confusion — forge a Claim representing ⊕ but actually ∧ Operator type-tagged in Evidence + per-operator Cairo circuit
A5 Linkage forgery — bypass C-1 cross-subject limit Linkage_proof NOT in MVP scope (deferred VCA v0.2)
A6 Delegation inflation — circumvent DelegationGrant cap via forged chain depth Cap circuits with explicit chain-depth limit (Phase Agentic)

Defense status:

  • Internal RSO audit Phase 0 (founder) covers theoretical
  • Preprint arXiv §10.7 Phase MVP submission (composition closure conjecture)
  • Bug bounty Phase MVP (Sprint 665, Sepolia public)
  • Academic partner Phase 2+ (caveat: Goldreich-Krawczyk 1990 sequential ZK composition critique applies — partial mitigation only)
  • Lean 4 / EasyCrypt formal verification (Phase 5 audit scope)

This is the first systematic enumeration of composition-adversary attacks for typed Claim algebras. Audit firm scoping in Phase 5 must address it explicitly — it's not on any standard checklist.

Implementation footprint

vauban-zkpay/                       # vertical core (Starknet-first reference)
├── crates/
│   ├── zkpay-types/                # Claim trait impls: PaymentIntent, Settlement, Refund, DelegationGrant
│   ├── zkpay-verifier/             # batch verifier middleware (Rust)
│   └── zkpay-prover-stwo/          # Stwo wrapping
└── cairo/
    └── payment_circuit.cairo        # IPaymentCircuit trait (extension VaubanSettlement)

Sprint mapping:

Sprint Status Composition delivery
661 ✅ sealed 2026-05-12 Claim trait impls, content-addressing, CBOR roundtrip
662 ✅ sealed 2026-05-12 payment_circuit.cairo extension, verifier middleware, 18/18 tests
663 planned 2026-07-13 aggregation_circuit ⊕ K=10, humanity_binding_circuit ∧ same-subject
664 planned 2026-08-03 x402 V2 wire format complete, ClaimExporter scaffold
665 planned 2026-08-24 Sepolia public + external validation
666 planned 2026-09-14 RSO audit + Brain decompose + spec v0.4