People selling compute to people, paid in QALS — running today · 07_compute_marketplace/P2P_COMPUTE_MARKET.md
P2P Compute Market — people selling compute to each other, paid in QALS
Date: 2026-09-06 · Answer to: "Can we use QALS as a means for people to sell compute to each other on the network?" → Yes — demonstrated, not just designed. (qmarket/ running today)
1. What exists RIGHT NOW (built & tested today)
qmarket/ — a working two-party compute marketplace gateway on superlocal:
| Component | Status |
|---|---|
| Provider registry (sellers list compute + price) | ✅ live (POST /providers, GET /providers) |
| Buyer job flow: escrow → execute → attest → settle → receipt | ✅ live (POST /jobs), via loopd money rails |
| Provider earnings accrual (redeemable AU$1:1) | ✅ live (GET /earnings/:id) |
| Provenance anchoring of every output on Qalnet | ✅ live (via qalpipe → qal_data on-chain) |
| Gateway fee economics (10% treasury) | ✅ modelled in every settlement |
Today's test (real transactions): Local Media Studio sold a 240-frame render to the tulpa app — est AU$28.80 held, actual AU$28.80 settled, provider netted AU$25.92. minirig sold 3,000 tokens of inference to tradez — provider netted AU$54.00. Output verified against the chain: PASS. (qmarket/test_market.sh reproduces it all.)
2. Why this beats existing compute markets (Akash, io.net, Golem)
| Them | Qals | |
|---|---|---|
| What sellers are paid in | Volatile tokens (AKT/IO/GLM) | B-QALS = AU$1, redeemable — zero price risk for sellers |
| Escrow | Varies, often optimistic | Chain-enforced Holds (petrol-card model), auto-expiring |
| Trust in provider telemetry | Mostly trusted | Attested + slashing (stake-backed), sampling verification |
| Provenance of results | None | Every output hash anchored on-chain — AI outputs carry receipts |
| Cold start | Classic chicken-egg | qalarc's apps are the anchor demand (tulpa, tradez, hub buy first) |
| Regulatory posture | Token-first | Prepaid-credit-first, public rails only after licensing |
The seller pitch is one sentence: "Sell your spare GPU hours, get paid in credit that's worth a dollar and redeems for a dollar — no token rollercoaster."
3. How a person joins (target UX)
Seller: register a provider (name, kind, price) → gateway runs your adapter (or you run our agent binary) → jobs arrive, escrowed → your earnings accrue → redeem to bank (Phase 2+) or spend on qalarc services (today).
Buyer: your app calls POST /jobs {provider, kind, spec} → the money, escrow, attestation and provenance all happen inside — you get a receipt and an anchor.
4. Trust ladder (how strangers become trusted sellers)
- Invite (now): gateway operator (qalarc) registers known providers (Local Media Studio, fleet machines). Reputation starts at 100.
- Accreditation: providers get Qal ID device DIDs +
can-run-jobscredentials — revocable in ~2s. - Stake: providers post G-QALS stake; proven faults (wrong results, fake telemetry) slash stake into the FloorVault (
07_compute_marketplace/§4). - Verification: high-value jobs get sampled re-runs on a second node; mismatches trigger dispute.
- Open registration (much later, post-VASP): anyone with stake + accreditation.
5. The upgrade path from today's paper demo
| Today (running) | Phase 1-2 (on-chain) |
|---|---|
loopd JSON ledger |
qal_credit on Qalnet (already written, 5/5 tests) — real Holds/settle txs |
| Provider earnings in gateway file | provider CreditAccounts credited on-chain (EARN side of the loop) |
| Gateway-held fee | treasury address |
| Mock adapters | real ollama/ffmpeg adapters on the fleet; Local Media Studio's real API behind the same interface |
qal_data anchor per output (already real) |
+ ComputeReceipt NFT per job |
Nothing gets thrown away — qmarket's HTTP contract is the same; the guts swap from paper to chain.
6. Money flows (who gets what)
buyer pays actual ──► 90% provider earnings (redeemable AU$1:1, or spend on qalarc services)
──► 10% gateway/treasury fee (funds Qal Pass gas sponsorship + FloorVault)
escrow : ~115% held during job, difference auto-refunded at settle
earn side: providers accumulate → the reserve-backed cash-out path (Phase 2+) or internal spend (now)
7. Run it
python3 loopd/loopd.py & # money rails :8823
python3 qmarket/qmarket.py & # market :8824 (chain must be up for anchors)
bash qmarket/test_market.sh # two-party sale, end to end
v2 (2026-09-08) — skin in the game: stakes, slashing, reputation, remote providers
Companion research: COMPUTE_MARKET_COMPETITORS_2026.md (Akash, io.net, Golem, Render, Nosana, Fluence, Aethir, Bittensor, Morpheus — scanned 2026-09-08). Headline: nobody pays providers in a stable redeemable unit, nobody anchors output provenance, and no network has per-provider stake→dispute→slash→delist tied to output correctness. v2 builds the missing trust layer.
What shipped (all tested: qmarket/test_market_v2.sh, 30 assertions green)
| Piece | File | What it does |
|---|---|---|
| Stakes | qmarket.py + provider.py |
Providers register with stake_cents held in a loopd agent they own (stake:<name>; paper phase shares the HMAC secret with the gateway — on-chain this becomes a stake escrow object and the secret sharing disappears). Min stake 500c. |
| Disputes | POST /dispute {job_id, reason} |
Two independent checks: (1) integrity — output file hash vs the on-chain anchor; (2) recompute — deterministic re-execution of (kind, spec) on the trusted local adapter, hash comparison (Golem's consensus idea, sampled & cheap). Verdict persisted to data/disputes.jsonl; one verdict per job. |
| Slashing | slash_stake() |
UPHELD → slash 50% of current stake via a real loopd hold+settle on the stake agent (receipted, purpose slash:<job_id>): 50% → treasury FloorVault bucket (data/treasury.json), 50% → buyer refund bucket (data/refunds.json), + disputed-job earnings clawback. Provider keeps earnings from undisputed jobs. |
| Reputation | providers.json |
Start 100; +1 per clean settled job; −25 per upheld dispute; delisted below 40. Delisted providers: excluded from GET /providers (visible via ?all=1), POST /jobs rejects with 403 DELISTED. Reputation recovers through clean work (76→77 demonstrated). |
| Remote providers | provider.py (zero-dep) |
Sellers run their own agent: register --name X --kind render --price 12 --stake 2000 then run (serves POST /execute on :8850). Gateway POSTs {job_id, kind, spec}; agent returns metrics + base64 output. Register with adapter_url = your agent. |
| Deterministic outputs | shared spec in both files | v1 adapters were random; v2 outputs are a pure function of (kind, spec) — sha256-chain seeded from the spec — which is what makes recompute-verification possible. provider.py implements byte-identical builders; a --cheat flag doctors outputs for dispute testing. |
| Bench oracle | bench.py (zero-dep) |
Measures real sha256 MB/s; tokens/s from Ollama if up (OLLAMA_URL, else tagged estimate). Writes data/price_suggestions.json: price floors per kind from target-hourly-profit ÷ measured units/hour, plus an electricity+amortisation cost floor (AU$0.30/kWh, 250W, AU$2700/3yr). Sellers consult before pricing; it's a floor — market prices sit above. |
Scenario proven by the test (real money moves every step)
- lms-remote registers on :8850 with 2000c stake → tulpa buys a 48-frame render over HTTP (576c settled, net 519c, anchored on-chain) → rep 101.
- Buyer tampers output → dispute UPHELD (integrity vs anchor): slash 1000c = 500 FloorVault + 500 buyer refund (loopd receipt on stake agent), rep 76, earnings clawed.
- Seller turns rogue (
--cheat): two doctored jobs settle and EARN — cheating is profitable until disputed — then recompute-mismatch disputes slash 500c and 250c → rep 29 < 40 → DELISTED, purchase attempts rejected 403. - minirig-remote (inference, 1000c stake): clean job → dispute (rep 76) → clean job → recovery to 77.
- Final: FloorVault 1125c, refunds tulpa 875c + tradez 250c, 4/4 verdicts persisted.
Notes & known paper-phase quirks
- loopd
account()bug fixed (2026-09-08):agents.get(aid) or (None,)raisedKeyError:0for existing agents — nobody had hitGET /account/:idon a live agent before stake verification. Pre-fix copy:loopd/archive/loopd_pre_accountfix_20260908.py. - loopd paper semantics discovered:
hold/settlenever debitbalance_cents— balance is collateral,spent_centsis the usage counter (buyers work the same way). Slashes are therefore receipted spends on the stake agent, not balance debits. Also: settle releases the 15% hold margin into balance, so balances drift upward ~15% of hold volume. Both are fine for paper; both die when Holds graduate to realqal_creditresource moves. - Buyer agents now register with AU$1000/day caps (v2) so repeated test runs and app-scale buying fit; pre-existing buyer agents keep their old caps until re-registered.
- Dispute path for remote kinds relies on the gateway's trusted builder matching the provider's (
--cheattest proves mismatches are caught). Future: sample re-runs on a second independent node instead of the gateway.
Run v2
python3 loopd/loopd.py & # money rails :8823
python3 qmarket/qmarket.py & # market :8824 (chain up for anchors)
python3 qmarket/bench.py # price-floor oracle
python3 qmarket/provider.py register --name X --kind render --price 12 --stake 2000
python3 qmarket/provider.py run --port 8850 # your compute, your port
bash qmarket/test_market.sh # v1: two-party sale (still green)
bash qmarket/test_market_v2.sh # v2: stake/slash/reputation/remote