Skip to content

[FEAT] Spatial H3 Multi-Peer Liquidity Netting & Cross-Chain Atomic Swap Settlement Engine #372

Description

@jotel-dev

telegram link : t.me/nullifiersystem


1. Summary & Core Promise

Velo's current cash allocation engine in apps/api/src/lib/liquidity-netting.ts and apps/api/src/lib/order-allocator.ts processes cash requests as isolated, point-to-point trades. In high-density geographic areas, this creates capital inefficiency, high transaction fees, and high provider collateral lockups. Furthermore, cross-chain swaps rely on basic HTLC lockups without automated multi-hop circular clearing or session-account delegated quota enforcement (contracts/session-account/src/lib.rs).

This feature implements an automated Spatial H3 Multi-Peer Liquidity Netting & Cross-Chain Atomic Swap Engine. It combines Uber H3 spatial indexing (apps/api/src/lib/h3-spatial-index.ts), multi-party directed graph cycle detection (Johnson's algorithm), PostgreSQL dead-lock-free ordered pessimistic row locking (SELECT FOR UPDATE NOWAIT), Soroban Atomic Swap contracts (contracts/atomic-swap/src/lib.rs), and Session-Account quota authorization (contracts/session-account/src/lib.rs). It guarantees optimal collateral utilization, zero circular debt deadlocks, and automated HTLC secret preimage disclosure settlement across cross-chain relayer nodes.


2. Background & Architectural Risks

  • Circular Liquidity Deadlocks: Concurrent multi-hop settlement graph executions can cause database deadlock cascades (Postgres Error 40P01) if multiple providers are locked in arbitrary order across concurrent API threads.
  • Preimage Disclosure Front-Running & HTLC Timeouts: If an HTLC secret preimage is revealed on-chain by a peer but fail to be ingested by Velo's watcher before the ledger timeout expires, funds risk being permanently locked or refunded to the wrong party.
  • Delegated Session Quota Overruns: Unenforced session-account quotas (contracts/session-account/src/lib.rs) could allow compromised relayer keys to drain provider collateral reserves during automated netting execution.

3. Database Layer Specifications

Migration SQL (009_add_spatial_netting_atomic_swap.sql)

CREATE TYPE netting_session_status AS ENUM ('GRAPH_BUILDING', 'LOCKED', 'EXECUTING', 'SETTLED', 'FAILED');
CREATE TYPE swap_htlc_status AS ENUM ('OPEN', 'SECRET_REVEALED', 'CLAIMED', 'REFUNDED');

-- Table: liquidity_netting_batches
CREATE TABLE liquidity_netting_batches (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    h3_index VARCHAR(15) NOT NULL, -- H3 spatial cell index (e.g. 8828308281fffff)
    net_cleared_amount BIGINT NOT NULL,
    participant_count INT NOT NULL,
    status netting_session_status NOT NULL DEFAULT 'GRAPH_BUILDING',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    settled_at TIMESTAMP WITH TIME ZONE NULL
);

-- Table: atomic_swap_legs
CREATE TABLE atomic_swap_legs (
    swap_id VARCHAR(64) PRIMARY KEY,
    batch_id UUID NOT NULL REFERENCES liquidity_netting_batches(id) ON DELETE CASCADE,
    sender_address VARCHAR(56) NOT NULL,
    receiver_address VARCHAR(56) NOT NULL,
    amount BIGINT NOT NULL,
    hash_lock VARCHAR(64) NOT NULL,
    secret_preimage VARCHAR(64) NULL,
    timeout_ledger INT NOT NULL,
    status swap_htlc_status NOT NULL DEFAULT 'OPEN',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_netting_h3_status ON liquidity_netting_batches(h3_index, status);
CREATE INDEX idx_swap_hash_lock ON atomic_swap_legs(hash_lock);

Pessimistic Deadlock-Free Locking Protocol (SELECT FOR UPDATE NOWAIT)

To prevent circular database deadlocks during multi-party netting, all provider accounts MUST be sorted deterministically by primary key hex string before acquiring locks:

BEGIN ISOLATION LEVEL READ COMMITTED;

-- Lock provider accounts in strict ascending primary key order to eliminate circular deadlocks
SELECT id, available_collateral, reserved_collateral 
FROM provider_accounts 
WHERE id IN ($1, $2, $3) -- Array must be pre-sorted lexicographically in API code
ORDER BY id ASC 
FOR UPDATE NOWAIT;

-- Lock netting batch record
SELECT id, status FROM liquidity_netting_batches WHERE id = $4 FOR UPDATE;

COMMIT;

4. Backend Route & Service Layer Specifications

Route: POST /api/v1/netting/spatial-clear

  1. Spatial Aggregation & Validation: Resolves geographic coordinates into an H3 spatial index cell (resolution = 8). Validates active participant balances using Zod.
  2. Graph Cycle Discovery: Constructs a directed debt graph and applies Johnson's cycle detection algorithm to find netting loops (e.g., A -> B -> C -> A).
  3. Ordered Pessimistic Locking: Sorts all node participant IDs lexicographically and executes SELECT FOR UPDATE NOWAIT. If lock acquisition times out, aborts with HTTP 409 Conflict.
  4. Synchronous Transaction Boundary: Calculates net obligations, creates liquidity_netting_batches row, inserts corresponding atomic_swap_legs rows, updates provider reserved balances, and commits DB transaction.
  5. Async Relayer Dispatch: Emits velo:netting-execution-queue payload to Redis Stream for multi-party Soroban HTLC contract initialization.
  6. Response: Returns HTTP 202 Accepted with graph summary and execution tracker payload.

Request Schema (Zod)

export const SpatialClearRequestSchema = z.object({
  latitude: z.number().min(-90).max(90),
  longitude: z.number().min(-180).max(180),
  radiusMeters: z.number().positive().max(5000),
  maxCycleLength: z.number().int().min(2).max(10).default(5),
});

Exact Error Shapes

  • HTTP 409 Conflict (Locking contention / Deadlock avoidance):
    {
      "error": {
        "code": "NETTING_LOCK_CONTENTION",
        "message": "Concurrent liquidity netting operation active in H3 cell 8828308281fffff. Try again.",
        "requestId": "req-net-991"
      }
    }
  • HTTP 422 Unprocessable Entity (No clearable cycle found):
    {
      "error": {
        "code": "NO_NETTING_CYCLES_FOUND",
        "message": "No circular liquidity debt paths discovered within specified spatial radius.",
        "requestId": "req-net-992"
      }
    }

5. Background Processors / Workers

Redis Stream Netting Relayer Worker (apps/api/src/lib/workers/spatialNettingWorker.ts)

  • Queue: Redis Stream velo:netting-execution-queue (spatial-netting-group).
  • Secret Reveal Watcher: Listens for Soroban contract events emitting secret_reveal across contracts/atomic-swap/src/lib.rs.
  • Preimage Propagation: Upon detecting a secret revelation for a specific hash_lock, immediately executes secret claim on all dependent swap legs in the cycle before ledger timeout.
  • Retry Strategy: Max 5 retries with exponential backoff (delayMs = 500 * 2^attempt + jitter).
  • DLQ & Invariant Verification: If any leg in a netting cycle fails to settle before timeout, invokes contracts/invariant-verifier/src/checker.rs to revert unexecuted legs, update batch status to FAILED, and push alert to velo:netting-dlq.

6. Frontend / UI Component Specifications

Component: mobile/frontend/src/pages/SpatialNettingDashboard.tsx

+-------------------------------------------------------------+
|          H3 Spatial Liquidity Netting & Swaps               |
+-------------------------------------------------------------+
| Active H3 Cell:   [ 8828308281fffff ] (Resolution 8)        |
| Netting Loop:     Provider A ──► Provider B ──► Provider C   |
| Cleared Balance:  $12,500.00 USDC                           |
+-------------------------------------------------------------+
| HTLC Secret Key:  [ ****************** ] (Blur Validated)   |
| Status Progress:  [=========================>  ] 80%        |
| Relayer State:    Propagating Secret Preimage On-Chain...   |
+-------------------------------------------------------------+
|  [ Abort Netting ]                   [ Execute Atomic Swap ]|
+-------------------------------------------------------------+
  • Input Blur Validation: Secret key preimage input validates 64-char hex format on onBlur. Shows error "Secret preimage must be a valid 32-byte hex string".
  • Real-Time Canvas Visualization: Renders interactive H3 spatial grid cells using Deck.gl / Canvas API, highlighting directed debt clearing loops in cyan/green.
  • Pending vs. Anchored State: Displays real-time WebSocket state streaming (NETTING_LOCKED -> HTLC_COMMITTED -> SECRET_REVEALED -> SETTLED).
  • Error Recovery State: If an atomic leg times out, displays prominent red warning banner "HTLC Timeout Triggered: Refund Protocol Active" with a single-click "Revert Collateral" action.

7. Rigor & Test Plan

  1. Unit Tests (apps/api/src/lib/__tests__/spatial-netting.test.ts):
    • Verify Johnson's cycle detection algorithm correctly identifies 3-node, 4-node, and 5-node liquidity cycles.
    • Assert pre-sorting algorithm sorts database UUIDs in exact ascending order before lock execution.
  2. Concurrency & Deadlock Stress Test (tests/concurrency/netting_deadlock_stress.test.ts):
    • Execute 50 simultaneous parallel POST requests with overlapping provider sets across multi-threaded workers (Promise.all()).
    • Expectation: Zero database deadlocks (Postgres Error 40P01 = 0). All non-acquired locks return 409 Conflict gracefully via NOWAIT.
  3. On-Chain HTLC Preimage Invariant Test (contracts/atomic-swap/src/test.rs):
    • Simulate secret disclosure on Leg 1. Assert relayer worker automatically extracts secret preimage and claims Leg 2 and Leg 3 before timeout.

8. Relevant Files Inventory

New Files to Create

  • apps/api/src/db/migrations/009_add_spatial_netting_atomic_swap.sql
  • apps/api/src/routes/netting.ts
  • apps/api/src/lib/workers/spatialNettingWorker.ts
  • apps/api/src/lib/__tests__/spatial-netting.test.ts
  • tests/concurrency/netting_deadlock_stress.test.ts
  • mobile/frontend/src/pages/SpatialNettingDashboard.tsx
  • mobile/frontend/src/pages/SpatialNettingDashboard.css

Existing Files to Modify

  • contracts/atomic-swap/src/lib.rs
  • contracts/session-account/src/lib.rs
  • apps/api/src/app.ts
  • apps/api/src/lib/h3-spatial-index.ts
  • apps/api/src/lib/liquidity-netting.ts
  • apps/api/src/lib/stellar.ts
  • packages/shared/src/index.ts

9. Acceptance Criteria

  • Migration 009_add_spatial_netting_atomic_swap.sql creates liquidity_netting_batches and atomic_swap_legs tables.
  • Johnson's graph algorithm successfully extracts circular clearing cycles from H3 spatial cells.
  • Provider DB locks are acquired in strictly pre-sorted ascending order with SELECT FOR UPDATE NOWAIT.
  • 50-client parallel stress test executes with zero PostgreSQL deadlocks (0x 40P01).
  • Redis worker ingests Soroban on-chain secret_reveal events and propagates preimages across all cycle legs.
  • Frontend dashboard renders interactive H3 netting graphs with real-time status transitions and blur validation.

10. Contributor / Architectural Notes

  • ⚠️ Order of Operations: Apply DB migration -> Deploy updated atomic-swap & session-account contracts -> Register backend Fastify routes -> Update frontend dashboard.
  • ⚠️ Deadlock Safety Rule: NEVER acquire database locks on multiple provider rows without pre-sorting their IDs in ascending order first.
  • ⚠️ Session Quota Enforcement: ALWAYS check session quota limits (contracts/session-account/src/lib.rs) prior to submitting automated relayer transactions on-chain.

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions