Cryptographic Receipts

Verifiable proof of every transaction with signatures and hashes

What is a Receipt?

Every request in x402++ generates a cryptographically signed receipt that proves:

✓ Work Was Done
Provider's Ed25519 signature proves they processed the request
✓ Data Integrity
SHA-256 hashes prove input/output weren't tampered
✓ SLA Compliance
Automatic verification of latency and quality metrics
✓ Fair Charges
Receipt shows exactly what was charged

Receipt Structure

interface Receipt {
  // Identity
  receiptId: string;
  sessionId: string;
  requestNumber: number;         // Sequence in session
  
  // Cryptographic Proof
  inputHash: string;             // SHA-256 of input
  outputHash: string;            // SHA-256 of output
  signature: string;             // Ed25519 signature
  
  // Timing
  requestStartedAt: number;      // Start timestamp
  requestCompletedAt: number;    // End timestamp
  latencyMs: number;             // Actual latency
  
  // Financial
  amountCharged: number;         // Amount deducted
  
  // SLA Verification
  slaVerification: {
    met: boolean,                // Was SLA met?
    metrics: {
      latency?: {
        expected: number,
        actual: number,
        met: boolean
      }
    },
    refundAmount?: number        // If breached
  },
  
  // Provider
  providerPubkey: string;        // Who created this
  
  // Optional
  pdaAddress?: string;           // On-chain anchor
  metadata?: Record<string, any>;
}

Verification Process

Receipt Verification Steps:
───────────────────────────

1. SIGNATURE VERIFICATION
   ┌──────────────────────────────────────┐
   │ Extract signature from receipt       │
   │ Remove signature field               │
   │ Serialize remaining fields to JSON   │
   │ Hash with SHA-256                    │
   │ Verify Ed25519 signature             │
   │   → Valid = Provider signed this ✓   │
   └──────────────────────────────────────┘

2. DATA INTEGRITY CHECK
   ┌──────────────────────────────────────┐
   │ Hash original input with SHA-256     │
   │ Compare to receipt.inputHash         │
   │   → Match = Input not tampered ✓     │
   │                                      │
   │ Hash original output with SHA-256    │
   │ Compare to receipt.outputHash        │
   │   → Match = Output not tampered ✓    │
   └──────────────────────────────────────┘

3. SLA VERIFICATION
   ┌──────────────────────────────────────┐
   │ Check latencyMs <= sla.maxLatencyMs  │
   │   → If yes: SLA met ✓                │
   │   → If no: Refund triggered          │
   └──────────────────────────────────────┘

4. TIMESTAMP VALIDATION
   ┌──────────────────────────────────────┐
   │ Verify completedAt > startedAt       │
   │ Verify latency = completed - started │
   │   → Prevents time manipulation ✓     │
   └──────────────────────────────────────┘
Verifying a Receipt
import { verifyReceipt, verifyReceiptHashes } from 'x402pp-core';

// 1. Verify signature
try {
  verifyReceipt(receipt);
  console.log('✓ Signature valid');
} catch (error) {
  console.error('✗ Invalid signature!');
  throw error;
}

// 2. Verify data integrity
const hashesValid = verifyReceiptHashes(
  receipt,
  originalInput,
  originalOutput
);

if (!hashesValid) {
  console.error('✗ Data tampered!');
  throw new Error('Receipt hashes dont match');
}

// 3. Check SLA
if (!receipt.slaVerification.met) {
  console.log('⚠ SLA breached');
  console.log('Refund amount:', receipt.slaVerification.refundAmount);
}

console.log('✓ Receipt fully verified');

Automatic SLA Refunds

// Scenario: SLA requires <2000ms, but request took 3500ms

const receipt = {
  latencyMs: 3500,
  amountCharged: 0.008,
  slaVerification: {
    met: false,                    // SLA breached!
    metrics: {
      latency: {
        expected: 2000,
        actual: 3500,
        met: false
      }
    },
    refundAmount: 0.004            // 50% refund for breach
  }
};

// Agent automatically gets 0.004 USDC refund
// Balance: 0.996 → 1.0 (refund applied)
// Only paid 0.004 instead of 0.008

// Fair and automatic!

On-Chain Anchoring

Optionally anchor receipts to Solana for permanent, immutable proof.

Solana Program (Anchor)
pub fn anchor_receipt(
    ctx: Context<AnchorReceipt>,
    receipt_id: String,
    session_id: String,
    input_hash: String,
    output_hash: String,
    latency_ms: u64,
    sla_met: bool,
) -> Result<()> {
    let receipt = &mut ctx.accounts.receipt;
    
    receipt.receipt_id = receipt_id;
    receipt.session_id = session_id;
    receipt.input_hash = input_hash;
    receipt.output_hash = output_hash;
    receipt.latency_ms = latency_ms;
    receipt.sla_met = sla_met;
    receipt.timestamp = Clock::get()?.unix_timestamp;
    
    msg!("Receipt anchored: {}", receipt.receipt_id);
    Ok(())
}
X (Twitter)