Settlement & Audit

1) why we do that?

  • Transparency: Freeze all billable usage and prices for a cycle into a snapshot so any party can independently verify.

  • Verifiability: Every line item (including segmented routes) has a hash; the full set rolls up into a Merkle Root; the snapshot is signed.

  • Traceability: In case of dispute, you can drill down to the exact request record and its amount.


2) Billing Cycle & Artifacts

  • Cycle: Weekly.

  • Artifacts (at minimum):

    • snapshot.json – contains the Merkle Root of all successful call records in the cycle and the link to the price table for this epoch.

      • Example keys:

        • merkleRoot: Merkle root over all successful usage records.

        • priceUrl: URL to fetch the price table in effect for this cycle.


3) Snapshot Structure

3.1 Snapshot schema (example)

{
  "epoch": 1234,
  "merkleRoot": "0xabc...",
  "priceUrl": "https://proxy.sightai.io/priceUrl/"
}

3.2 Subset export (private to User/Provider)

Exports are provided per account (e.g., my-records.jsonl / CSV). Field names may include requestId, model, tokenIn, tokenOut, proof, etc.

  • If a proof is present, you can validate each record’s inclusion against the Merkle Root.

  • Without proof, you can still recompute amounts and reconcile totals, but you cannot independently prove inclusion.

3.3 Merkle construction & proofs

  • Leaf: Compute keccak256 over the canonical JSON of each normalized record.

  • Ordering: Sort leaves by their hash (ascending) to form the leaf sequence.

  • Tree: Binary Merkle; if a level has an odd count, duplicate the last leaf to fill the pair.

    Internal node: H = keccak256(left || right).

  • Root: Write the resulting merkleRoot into snapshot.json.

  • Proofs (optional): A proofs.jsonl may be provided:

{ "recordId": "...", "leaf": "0x...", "proof": ["0x...", "..."] }
  • Use it to verify leaf → merkleRoot membership.


4) Price Table & Units

  • Currency & precision: USD-stable, typically 6 decimal places.

  • Unit: per_1k_tokens (price per 1,000 tokens).

  • Structure (example):

"priceTable": [
  {
    "epoch": 1234,
    "model": "gpt-4o",
    "priceIn":   0.005,  // expense price for input  (USD / 1k tokens)
    "priceOut":  0.015,  // expense price for output (USD / 1k tokens)
    "rewardIn":  0.004,  // reward price for input  (USD / 1k tokens)
    "rewardOut": 0.013,  // reward price for output (USD / 1k tokens)
    "currency": "USD",
    "unit": "per_1k_tokens"
  }
]

Meaning

  • price* → Baseline expense prices for user billing.

  • reward* → Baseline reward prices for provider payouts.


5) Amount Formulas (as implemented)

User expense

userCostUSD = (priceIn  * Tin / 1000) + (priceOut  * Tout / 1000)

Provider reward

providerRewardUSD = (rewardIn * Tin / 1000) + (rewardOut * Tout / 1000)

Precision & rounding

  • Use fixed-point decimals (e.g., Decimal with 6 fractional digits) for monetary values.

  • Token counts are integers; amounts are stored/rounded to USD with 6 decimals.


6) Local Self-Verification (Offline)

6.1 Steps

  1. Fetch the snapshot: Download snapshot.json for the cycle to get epoch, merkleRoot, and priceUrl.

  2. Fetch the price table: Retrieve the priceTable for that epoch via priceUrl.

  3. Export your subset: From the Console, export your relevant records (e.g., my-records.jsonl / CSV).

  4. Verify Merkle inclusion (if proof is present):

    • Canonicalize each record JSON and hash → leaf.

    • Verify the path using the provided proof up to the merkleRoot.

    • (If no proof, skip—membership cannot be independently proven.)

  5. Recompute amounts:

    • For each record, match on model and time/epoch to select priceIn/priceOut and rewardIn/rewardOut.

    • Compute userCostUSD and providerRewardUSD per record, then aggregate at your export’s granularity.

    • Totals should match the Console’s statements (any tiny deltas stem from rounding—align to 6 decimal places).

  6. Handle discrepancies:

    • If you find mismatches (e.g., price tier selection, token counting method), note the requestId and contact Support with context.

    • Failed calls are not included in the Merkle tree.

Reference verifier: https://github.com/sight-ai/api-key-merkle-root-verifier

Last updated