Close the farmer→user deployment loop: ledger write path + node identity mapping #67

Closed
opened 2026-04-08 19:06:58 +00:00 by mik-tf · 1 comment
Member

Problem

The marketplace can deploy VMs end-to-end (wallet → SPORE accounting → hero_compute → running VM), but the farmer→user circular economy has two manual bridges that prevent a full self-service loop.

What works today (verified 2026-04-08)

Step Status
User registers, tops up wallet Works
User adds SSH key Works
User rents a slice (nano tier, 5 MC) Works
Wallet debit (MC) Works
SPORE amount calculated (500 SPORE) Works
VM deployed via hero_compute Works — mkt-vm-nano-e4e7 running Ubuntu 24.04, SSH accessible on Mycelium IPv6
Farmer registers as resource provider Works (OSIS dashboard)
Farmer adds nodes in dashboard Works (OSIS-based)

What's missing

Gap 1: No write path from marketplace to hero_ledger

The farmer can add nodes in the resource provider dashboard (stored in OSIS), but there's no code that creates a marketplace.createListing() transaction on the hero_ledger NEAR contract. The 7 product listings currently visible (ledger_3 through ledger_9) were pre-seeded directly on the NEAR contract — not created through the marketplace UI.

The marketplace is read-only against the ledger for the product catalog (marketplace_list_listings()). There's no write path.

Gap 2: No node identity mapping (ledger ↔ hero_compute)

When a user rents ledger_4 (TFGrid Node 390), the backend ignores that node ID and calls hero_compute.node_list() to pick the first available online node. The code in slice_rental_manager.rs explicitly says:

// Resolve node: product IDs from hero_ledger (e.g. "ledger_3") don't match
// hero_compute node SIDs (e.g. "0001"). Find the first available compute node.

So the farmer's specific hardware is never targeted — any available node gets the workload.

Gap 3: SPORE transfer to farmer fails

The SPORE transfer code runs but returns spore_transferred: false because the farmer's NEAR account (extracted from the ledger listing) doesn't exist on the devnet. This would work if Gap 1 were closed (farmer account created during listing registration).

Proposed solution

1. Farmer listing write path

  • When a farmer adds a node in the resource provider dashboard AND has a hero_ledger account:
    • Marketplace calls marketplace.createListing() on hero_ledger with node specs, pricing, and farmer's NEAR account
    • Listing appears in product catalog automatically (already works via marketplace_list_listings())
    • Farmer can update/remove listings via dashboard → marketplace.updateListing() / marketplace.removeListing()

2. Node identity mapping

  • Each hero_compute node registers with a ledger_listing_id or node_identity that maps to the ledger listing
  • When a user rents ledger_4, the backend resolves it to the corresponding hero_compute node SID
  • Fallback: if no mapping exists, current behavior (first available) as graceful degradation

3. Farmer NEAR account provisioning

  • When a farmer registers as resource provider, auto-create a NEAR account on hero_ledger devnet
  • Fund it with initial devnet SPOREs for gas
  • Store the account ID in the farmer's OSIS profile

Full target flow

farmer@example.com                          user@example.com
       │                                           │
  1. Register as resource provider                 │
  2. Add node (OSIS + hero_compute)                │
  3. Create listing on hero_ledger ◄── NEW         │
       │                                           │
       │                                      4. Browse marketplace
       │                                      5. Select farmer's node
       │                                      6. Top up wallet (MC)
       │                                      7. Rent slice
       │                                           │
       │                              ┌─────────────┤
       │                              │  8. Debit MC from wallet
       │  ◄───────────────────────────│  9. Transfer SPORE to farmer ◄── FIX
       │                              │ 10. Deploy VM on farmer's node ◄── FIX
       │                              └─────────────┤
       │                                           │
  11. Receive SPOREs                          12. SSH into running VM

Test plan

  • Farmer registers, adds node, listing appears on ledger
  • User browses, sees farmer's node in product catalog
  • User rents → SPORE transferred to farmer's NEAR account
  • VM deploys on farmer's specific hero_compute node (not random)
  • Farmer's SPORE balance increases after rental
  • Full E2E: farmer@example.comuser@example.com on devnet

Context

  • Marketplace runs on TFGrid v3 node 50 (185.69.166.158)
  • hero_compute_explorer on port 9002, hero_compute_server on Unix socket
  • hero_ledger devnet in Docker container
  • Current code: src/services/impl_ledger/product_catalog.rs (read-only), src/services/impl_compute/slice_rental_manager.rs (ignores node mapping)
  • Related: src/axum_app/controllers/rental.rs:225 (rent_slice_full handler)
## Problem The marketplace can deploy VMs end-to-end (wallet → SPORE accounting → hero_compute → running VM), but the farmer→user circular economy has two manual bridges that prevent a full self-service loop. ### What works today (verified 2026-04-08) | Step | Status | |------|--------| | User registers, tops up wallet | Works | | User adds SSH key | Works | | User rents a slice (nano tier, 5 MC) | Works | | Wallet debit (MC) | Works | | SPORE amount calculated (500 SPORE) | Works | | VM deployed via hero_compute | Works — `mkt-vm-nano-e4e7` running Ubuntu 24.04, SSH accessible on Mycelium IPv6 | | Farmer registers as resource provider | Works (OSIS dashboard) | | Farmer adds nodes in dashboard | Works (OSIS-based) | ### What's missing **Gap 1: No write path from marketplace to hero_ledger** The farmer can add nodes in the resource provider dashboard (stored in OSIS), but there's no code that creates a `marketplace.createListing()` transaction on the hero_ledger NEAR contract. The 7 product listings currently visible (`ledger_3` through `ledger_9`) were pre-seeded directly on the NEAR contract — not created through the marketplace UI. The marketplace is **read-only** against the ledger for the product catalog (`marketplace_list_listings()`). There's no write path. **Gap 2: No node identity mapping (ledger ↔ hero_compute)** When a user rents `ledger_4` (TFGrid Node 390), the backend **ignores** that node ID and calls `hero_compute.node_list()` to pick the first available online node. The code in `slice_rental_manager.rs` explicitly says: ```rust // Resolve node: product IDs from hero_ledger (e.g. "ledger_3") don't match // hero_compute node SIDs (e.g. "0001"). Find the first available compute node. ``` So the farmer's specific hardware is never targeted — any available node gets the workload. **Gap 3: SPORE transfer to farmer fails** The SPORE transfer code runs but returns `spore_transferred: false` because the farmer's NEAR account (extracted from the ledger listing) doesn't exist on the devnet. This would work if Gap 1 were closed (farmer account created during listing registration). ## Proposed solution ### 1. Farmer listing write path - When a farmer adds a node in the resource provider dashboard AND has a hero_ledger account: - Marketplace calls `marketplace.createListing()` on hero_ledger with node specs, pricing, and farmer's NEAR account - Listing appears in product catalog automatically (already works via `marketplace_list_listings()`) - Farmer can update/remove listings via dashboard → `marketplace.updateListing()` / `marketplace.removeListing()` ### 2. Node identity mapping - Each hero_compute node registers with a `ledger_listing_id` or `node_identity` that maps to the ledger listing - When a user rents `ledger_4`, the backend resolves it to the corresponding hero_compute node SID - Fallback: if no mapping exists, current behavior (first available) as graceful degradation ### 3. Farmer NEAR account provisioning - When a farmer registers as resource provider, auto-create a NEAR account on hero_ledger devnet - Fund it with initial devnet SPOREs for gas - Store the account ID in the farmer's OSIS profile ## Full target flow ``` farmer@example.com user@example.com │ │ 1. Register as resource provider │ 2. Add node (OSIS + hero_compute) │ 3. Create listing on hero_ledger ◄── NEW │ │ │ │ 4. Browse marketplace │ 5. Select farmer's node │ 6. Top up wallet (MC) │ 7. Rent slice │ │ │ ┌─────────────┤ │ │ 8. Debit MC from wallet │ ◄───────────────────────────│ 9. Transfer SPORE to farmer ◄── FIX │ │ 10. Deploy VM on farmer's node ◄── FIX │ └─────────────┤ │ │ 11. Receive SPOREs 12. SSH into running VM ``` ## Test plan - [ ] Farmer registers, adds node, listing appears on ledger - [ ] User browses, sees farmer's node in product catalog - [ ] User rents → SPORE transferred to farmer's NEAR account - [ ] VM deploys on farmer's specific hero_compute node (not random) - [ ] Farmer's SPORE balance increases after rental - [ ] Full E2E: farmer@example.com ↔ user@example.com on devnet ## Context - Marketplace runs on TFGrid v3 node 50 (`185.69.166.158`) - hero_compute_explorer on port 9002, hero_compute_server on Unix socket - hero_ledger devnet in Docker container - Current code: `src/services/impl_ledger/product_catalog.rs` (read-only), `src/services/impl_compute/slice_rental_manager.rs` (ignores node mapping) - Related: `src/axum_app/controllers/rental.rs:225` (`rent_slice_full` handler)
Author
Member

Resolved — All 5 Steps Implemented and Verified

Changes (2 repos pushed)

projectmycelium_marketplace_backend (d749e0c on development):

  1. farmer_id attribute — Added to LedgerProductCatalog so rental code can find farmer account for SPORE transfers
  2. Node schema — Added ledger_listing_id, compute_node_sid, ledger_account_id optional fields to Node type in OSchema + all generated types
  3. activate_ledger_account — Replaced no-op with real account_activate() call on hero_ledger gateway (derives {name}.mycelium domain)
  4. Ledger listing creation — When farmer adds node in dashboard, calls marketplace_create_listing() on hero_ledger with resources/pricing, stores listing_id back in OSIS
  5. Node identity mapping — Slice rental resolves ledger_{id} → OSIS node → compute_node_sid for hero_compute deployment (fallback: first available)

projectmycelium_marketplace_deploy (4d10840 on development):

  • New farmer_integration.sh test suite (27 tests)
  • Fixed stale Playwright assertions (users now start with 0 MC under hero_ledger)
  • Updated visual snapshots

Test Results — 354/354 PASS

Suite Result
Unit tests 25/25
API Smoke 27/27
API Integration 65/65
Provider Integration 34/34
Messaging & SSH 13/13
Rental Integration 11/11
Pool Integration 5/5
Farmer Integration (NEW) 27/27
Admin Smoke 25/25
Playwright SPA E2E 48/48
Playwright Admin E2E 41/41
Content Regression 33/33

Verified on dev VM

  • farmer_id visible in product catalog
  • SPORE transfer: 500.0 SPORE logged on rental
  • Full flow: register farmer → add node → user rents → SPORE to farmer
  • Deployed at https://dev-app.projectmycelium.org
## Resolved — All 5 Steps Implemented and Verified ### Changes (2 repos pushed) **projectmycelium_marketplace_backend** (`d749e0c` on development): 1. **farmer_id attribute** — Added to `LedgerProductCatalog` so rental code can find farmer account for SPORE transfers 2. **Node schema** — Added `ledger_listing_id`, `compute_node_sid`, `ledger_account_id` optional fields to Node type in OSchema + all generated types 3. **activate_ledger_account** — Replaced no-op with real `account_activate()` call on hero_ledger gateway (derives `{name}.mycelium` domain) 4. **Ledger listing creation** — When farmer adds node in dashboard, calls `marketplace_create_listing()` on hero_ledger with resources/pricing, stores listing_id back in OSIS 5. **Node identity mapping** — Slice rental resolves `ledger_{id}` → OSIS node → `compute_node_sid` for hero_compute deployment (fallback: first available) **projectmycelium_marketplace_deploy** (`4d10840` on development): - New `farmer_integration.sh` test suite (27 tests) - Fixed stale Playwright assertions (users now start with 0 MC under hero_ledger) - Updated visual snapshots ### Test Results — 354/354 PASS | Suite | Result | |-------|--------| | Unit tests | 25/25 | | API Smoke | 27/27 | | API Integration | 65/65 | | Provider Integration | 34/34 | | Messaging & SSH | 13/13 | | Rental Integration | 11/11 | | Pool Integration | 5/5 | | **Farmer Integration (NEW)** | **27/27** | | Admin Smoke | 25/25 | | Playwright SPA E2E | 48/48 | | Playwright Admin E2E | 41/41 | | Content Regression | 33/33 | ### Verified on dev VM - farmer_id visible in product catalog ✅ - SPORE transfer: 500.0 SPORE logged on rental ✅ - Full flow: register farmer → add node → user rents → SPORE to farmer ✅ - Deployed at https://dev-app.projectmycelium.org
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coopcloud_code/home#67
No description provided.