Skip to main content

Purpose

A transaction proof is a signed receipt attesting that a transfer was completed. It’s the cryptographic evidence that enables trustless settlement.

Proof Structure

{
  "proof": {
    "txid": "barclays_tx_456",
    "issuer": 100,
    "from": { "ocid": 200, "reference": "paypal_tx_123" },
    "to": { "ocid": 300, "reference": "momo_tx_789" },
    "amount": "10000.00",
    "currency": "UGX",
    "timestamp": 1706500500,
    "memo": "Settlement for ORD-2024-001"
  },
  "signature": "a1b2c3d4e5f6...7f1b"
}

Proof Fields

FieldTypeRequiredDescription
txidstringYesUnique transaction ID from issuer
issuernumberYesOCID of service that executed the transfer
fromobjectYesSender information
from.ocidnumberYesSender’s OCID
from.referencestringNoSender’s transaction ID for correlation
toobjectYesRecipient information
to.ocidnumberYesRecipient’s OCID
to.referencestringNoRecipient’s transaction ID for correlation
amountstringYesAmount as decimal string
currencystringYesISO 4217 currency code
timestampnumberYesUnix timestamp when transfer completed
memostringNoHuman-readable description

Proof Signature

The signature is over the canonical JSON of the proof object:
canonical = canonicalize(proof)  // Sorted keys, no whitespace
hash = SHA256(canonical)
signature = secp256k1_sign(issuer_private_key, hash)
Canonicalization: Keys sorted alphabetically at all levels, no whitespace, minimal escaping.

Verifying a Proof

1. Extract issuer OCID from proof
2. Fetch issuer's metadata from Router Registry
3. Extract publicKey from metadata
4. Canonicalize the proof object
5. Compute SHA256(canonical)
6. Verify signature against public key
7. Confirm issuer is in your settlement.accepts list
8. Confirm amount and currency match expected values
9. Store txid to prevent replay