Skip to content

Paid hosting marketplace: d1sks-picked preferred hosts, proof of storage, settlement (off by default) - #163

Merged
ralyodio merged 2 commits into
masterfrom
feat/hosting-marketplace
Nov 9, 2026
Merged

ralyodio merged 2 commits into
masterfrom
feat/hosting-marketplace

Conversation

@ralyodio

@ralyodio ralyodio commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator

Turns c0mpute hosting into a paid marketplace with d1sks.com as discovery only. Placement, proofs, serving and settlement stay peer to peer, and a site keeps being served if d1sks is down.

What ships

  • c0mpute hosting publish <dir> --name x --disks auto|<d1sks query> [--max-price 0.01] [--country DE,FI] [--copies 3] asks d1sks once (/api/v1/disks?hosting=1…). It keeps only c0mpute hosting nodes, which means a valid c0mpute.peer_id plus accepts.hosting or the hosting role. It ranks them by price, then standing (unrated last), then free space, then peer id, takes the first N, and signs them into the record. The agreed price is the highest ask among the chosen hosts. If d1sks is unreachable or nothing matches, the site publishes as a plain free site. c0mpute hosting disks shows what would be picked.
  • SiteRecord v2: preferred_hosts (1-5 peer ids), price_per_gib_month (canonical decimal), and optional payer. v1 records serialize and verify byte for byte as before. v2 signs under c0mpute-hosting-v2, so terms can't be stripped or added. Nodes older than this release ignore v2 records.
  • Placement (still leaderless and deterministic): a preferred host replicates whatever the copy count if it is live, asks no more than the agreed price (hosts now gossip their price) and has not been demoted. The rendezvous fill still reaches 3 copies without waiting for preferred hosts. Surplus free copies are released one per round and the total never drops below 3. With 2 preferred hosts among 5 nodes, the site settles at 2 preferred + 1 free.
  • Proof of storage (hosting/proof.rs): the challenger fetches one random chunk straight from each holder, checks the hash, signs a receipt and gossips it on c0mpute/hosting/v1 (old nodes skip the new variant). hosting.challenge = own|all|off, default own; all is capped at 32 challenges per round. A host is demoted when 3 of its last 5 receipts signed by the owner or payer are failures. Receipts from anyone else cannot demote it.
  • Settlement (hosting/settle.rs): price x GiB x window/30d x passed/challenged, in integer micro-USD, zero if under half passed. Each transfer has an idempotency key (site, holder, window), recorded in <storage>/hosting/ledger.json, and windows never overlap.
  • Shared payments module (c0mpute-core/src/payments.rs): a Rail trait (balance, pay), FakeRail, CoinPayRail (CoinPay POST /api/payouts/create with a business key that has the payouts:create scope), pay_all with a round cap and balance check, and Ledger. origin/feat/ads-billing did not exist when I started and master's ads has no billing, so this is the small interface for ads billing to adopt instead of a second rail.
  • OpenDisk descriptor: accepts.hosting, c0mpute.roles, c0mpute.hosting { price_per_gib_month, max_gib }. The d1sks side is in List c0mpute hosting nodes: ?hosting=1 filter, badge, host-a-site docs d1sks.com#5.
  • Docs: docs/hosting.md (marketplace flow, record v2, placement, proofs, pricing, switch-on steps) and docs/storage-opendisk.md. The manifest is updated, with c0mpute = ">=NEXT".

Settlement is OFF by default

[payments] enabled = false. Until it is turned on, the node only logs hosting settlement (dry run …) and moves no money. To turn it on:

  1. Create a CoinPay business API key with payouts:create.
  2. export C0MPUTE_COINPAY_PAYOUT_KEY=… in the node's environment.
  3. In config.toml set [payments] enabled = true, max_usd_per_round = "10" and [payments.coinpay] recipient_email = "…".
  4. Restart the node.

Third-party money movement goes live only with Anthony's approval.

Tests (docker, --network none --offline)

  • c0mpute-core --lib filtered to hosting/payments/opendisk/config: 52 passed. This covers d1sks query parsing and ranking against fixtures, record v2 compatibility and tamper checks, preferred-first placement determinism, fallback to 3 copies when preferred hosts are offline, overpriced or demoted, receipt verification and demotion, payment math, and fake-rail idempotency and caps.
  • New loopback e2e hosting_market_e2e: 2 preferred hosts out of 5 hold copies and the site settles at 3. A challenge round passes on all 3 holders, and the receipts are persisted and gossiped. A gateway's own receipts don't count. Settlement on the fake rail pays exactly the two preferred wallets, and a second round pays nothing (AlreadyPaid).
  • hosting_e2e, podcast_e2e and ads_e2e still pass.

Not covered: escrow (payers pay after the fact from their own wallet), and DIP-0015 proof-of-serve. A receipt proves the holder returned the right bytes for an unpredictable chunk. It does not prove the holder keeps its own copy rather than relaying from another holder.

🤖 Generated with Claude Code

ralyodio and others added 2 commits November 9, 2026 04:21
…ettlement (off by default)

- `c0mpute hosting publish --disks auto|<d1sks query> [--max-price] [--country] [--copies]`
  asks d1sks once for c0mpute hosting nodes, ranks them (price, standing, free space,
  peer id) and signs the chosen peer ids and agreed price into a v2 SiteRecord
  (preferred_hosts, price_per_gib_month, payer). v1 records are unchanged byte for byte;
  v2 signs under its own domain. `c0mpute hosting disks` previews the pick.
- Placement: live, price-compatible, non-demoted preferred hosts replicate first; the
  rendezvous fill still brings every site to 3 copies on its own; surplus free copies are
  released one per round, never below 3. Deterministic on every node.
- Proof of storage: random-chunk challenges straight from each holder, hash-verified,
  signed receipts gossiped on c0mpute/hosting/v1. A preferred host loses preference after
  3 of its last 5 owner/payer-signed receipts fail; strangers cannot demote anyone.
- Settlement: price x GiB x window/30d x passed/challenged, integer micro-USD, idempotent
  keys and an on-disk ledger. New shared `payments` module (Rail trait, FakeRail,
  CoinPay payouts rail, pay_all with caps) for ads billing to reuse. `[payments]` is off
  by default: settlement is a logged dry run until enabled with a CoinPay key in the env.
- OpenDisk descriptor: accepts.hosting, c0mpute.roles, c0mpute.hosting {price, max_gib}.
- Hosting gossip carries each node's hosting price and payout wallet.
- docs/hosting.md: marketplace flow, record v2, placement, proofs, pricing, switch-on.
- Tests: query parsing + ranking fixtures, record v2 compat, preferred-first placement
  determinism and fallback to 3, receipt verification and demotion, payment math on the
  fake rail, and a loopback e2e (2 preferred of 5 hosts hold, challenges pass, a
  settlement round pays exactly them, a repeat pays nothing).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown

ThreatCrush Security Scan

12 finding(s)

HIGH/CRITICAL: 1 | MEDIUM: 8 | LOW: 3

Severity Rule Location
HIGH js-ssrf-outbound-request apps/web/public/sw.js:24
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:53
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:80
MEDIUM sh-remote-script-execution scripts/dev-setup.sh:25
MEDIUM sh-eval-expansion scripts/dev-setup.sh:35
MEDIUM sh-remote-script-execution scripts/install.sh:173
MEDIUM sh-remote-script-execution scripts/install.sh:198
MEDIUM sh-remote-script-execution scripts/install.sh:316
MEDIUM sh-remote-script-execution scripts/install.sh:354
LOW py-ssrf-outbound-request examples/business-strategist-agent/chat.py:37
LOW py-ssrf-outbound-request examples/business-strategist-agent/train.py:54
LOW secret-generic-credential node/crates/c0mpute-core/src/webhook.rs:1165

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit cad96cd into master Nov 9, 2026
12 checks passed
ralyodio added a commit that referenced this pull request Nov 9, 2026
…t-in; honest payout status (#184)

Answers public feedback on the r/LocalLLM launch post:

- Installer starts the worker as a systemd *user* service with lingering
  (no root, nothing outside $HOME). A root-managed system service only
  with --system-service, or when an earlier install made one; with such a
  unit present and no sudo it no longer starts a second worker beside it.
- --uncensored-models opts in to uncensored house models (off by default
  from Infernet with InfernetProtocol/infernet-protocol#178).
- docs/node-safety.md: what the installer and worker can touch, that jobs
  are not sandboxed beyond your user, models served, outbound requests,
  what pays today, and how to remove it.
- README + /providers: same facts; settlement for hosting/ads is built but
  off by default, storage payouts not live.
- CIP-006 status table (In progress; payments.rs #163, ads #162/#166).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant