Skip to content

Latest commit

 

History

History
254 lines (225 loc) · 17.5 KB

File metadata and controls

254 lines (225 loc) · 17.5 KB

Wavelength Architecture

This document provides a top-level map of the wavelength codebase: an Ark protocol client daemon that manages VTXOs, participates in rounds, and communicates with the Ark operator via a mailbox-based RPC protocol.

Domain Layers

The codebase is organized into four layers. Dependencies flow downward; no package may import from a higher layer.

Layer 1: Core Domain (Business Logic)

Package Purpose
round Client-side Ark round participation FSM (boarding, refresh, leave)
vtxo VTXO lifecycle FSM (live, forfeiting, forfeited, spent, expiring)
oor Out-of-round transfer coordination FSM
wallet On-chain boarding wallet actor (address derivation, UTXO monitoring)
ledger Client-side durable ledger actor for double-entry fee accounting
lib Shared domain utilities: tree paths, BIP-322, arkscript policy, types
lib/arkscript Tapscript AST compiler and policy system for Ark taproot outputs
lib/bip322 BIP-322 intent-bound message authentication
lib/tx/arktx Canonical Ark transaction ordering and validation
lib/tx/checkpoint Checkpoint PSBT construction for OOR transfers
lib/tx/oor OOR submit/finalize package builders and validators
lib/tx/psbtutil PSBT encoding, decoding, and signature attachment helpers
lib/recovery Immutable recovery proof graph, session state machine, TLV codec for unilateral exit
unrollplan Pure dependency-resolution planner driving unilateral-exit broadcast/sweep ordering
vhtlcrecovery Durable control-plane types for vHTLC on-chain recovery jobs (action, state, script parameters, swap linkage)
credit Client-side credit subsystem: supervisor/per-operation-actor pair driving fault-tolerant sub-floor pay, credit-receive, and redeem flows against the authoritative server ledger
coinselect Single coin-type-agnostic coin-selection algorithm shared across wallet backends

Layer 2: Infrastructure (Chain, Storage, Messaging)

Package Purpose
baselib Actor framework (baselib/actor) and protofsm state machine engine (baselib/protofsm)
build Cross-cutting build metadata and logging infrastructure: deployment mode, build-tag-controlled log type/level, context logger propagation, subsystem logger factory, version string. Imports no repo package
chainsource ChainBackend interface: fee estimation, block/conf/spend notifications
chainbackends LND-backed ChainBackend implementation plus lndclient adapters (TxBroadcaster, PackageSubmitter)
chainbackends/lndsubmitter chainbackends.PackageSubmitter over lnd's WalletKit; the default LND package-relay submitter
chainfees Reusable chainfee.Estimator implementations and combinators for pricing transactions
chain Bitcoind RPC utilities (package relay, SubmitPackage)
txconfirm Generic "broadcast + CPFP fee-bump + notify on confirm" actor with per-parent fee-input reservations and BIP-125 Rule 3/4 enforcement
unroll Durable per-target unilateral-exit actor + thin registry: owns proof assembly, materialization, CSV maturity, final sweep build, persist-before-broadcast, and control-plane record persistence
lndbackend BoardingBackend implementation via LND's wallet kit
lwwallet Lightweight in-process wallet (btcwallet + Esplora, no external LND)
btcwbackend Neutrino-backed wallet backend (btcwallet + compact block filters)
walletcore Shared wallet abstractions and boarding logic used by lwwallet and btcwbackend
proofkeys Interface for wallet-managed key derivation and indexer proof signing
fraud Fraud detection actor: watches OOR ancestor outpoints on-chain and triggers unilateral exit when an ancestor is spent
vhtlcrecovery/coordinator Runtime coordinator for durable vHTLC recovery jobs: arms, escalates into unroll, cancels, and reconciles after restart
vhtlcrecovery/unrollpolicy Adapter that resolves (exit_policy_kind, recovery_id) into a concrete unroll.ExitSpendPolicy for vHTLC claim and refund exits
db SQLite/PostgreSQL persistence: boarding, rounds, VTXOs, OOR artifacts, fee ledger
mailbox Mailbox protocol primitives across three sub-packages (pb, rpc, conn)
serverconn Unified server connector: durable egress, ingress polling, unary RPC facade
serverconn/mailboxpull Shared exponential-backoff retry primitives for mailbox pull loops (used by serverconn ingress and SDK swap consumers)
rpcauth Shared macaroon and TLS helpers securing gRPC/REST connections
metrics Prometheus instrumentation namespaced under waved_: event-driven counter actor pool plus a scrape-time SystemCollector for live gauges, and an opt-in /metrics HTTP server
internal/sqlbase walletdb-compatible key/value backend over database/sql (js/wasm walletdb storage for lwwallet browser builds)
internal/wasmhost js/wasm host detection (browser vs Node) and the durable SQLite VFS name that follows from it; imported by db, lwwallet, and cmd/wavewalletdk-wasm

Layer 3: Application & Orchestration

Package Purpose
waved Daemon orchestrator: wires all subsystems, exposes gRPC API
gateway HTTP gateway utilities (mux options, CORS, endpoint normalization) for grpc-gateway integration
sdk/ark Consumer-facing Go SDK facade: remote or embedded daemon access with typed models
sdk/swaps Lightning-to-Ark / Ark-to-Lightning atomic swap SDK with durable FSM flows
sdk/wavewalletdk Wallet-shaped SDK facade for host apps: embeds the daemon in-process, dials it over a private bufconn transport, exposes typed methods for the seven core wallet verbs (create, unlock, send, recv, list, balance, exit). The highest-level layer in the stack; wraps wavewalletrpc.WalletService. Wallet RPC methods gated behind wavewalletrpc (which transitively requires swapruntime)
sdk/wavewalletdk/mobile Gomobile-safe facade over sdk/wavewalletdk for Android/iOS host apps: drives an embedded in-process wallet over the private bufconn transport
swapwallet Optional daemon-side wavewalletrpc.WalletService implementation (build tags wavewalletrpc swapruntime): composes the swap subsystem, cooperative leave, boarding, ledger, and unilateral-exit registry behind one flat, swap-vocabulary-free wallet API
swapclientserver Optional daemon-side swap subserver (build tag swapruntime): translates swapclientrpc RPCs into sdk/swaps operations and manages the daemon-local worker registry
cmd/waved Daemon entry point
cmd/wavecli CLI client
cmd/wavewalletdk-wasm Command compiling the embedded wavewalletdk runtime to a browser WASM binary
timeout Generic timeout scheduling actor
indexer Server indexing client for receive script registration
arkrpc Server-side gRPC service definitions (ArkService, IndexerService)
arkrpc/treeconv Narrow re-export of tree-path conversion helpers without the full gRPC surface
rpc Client-side RPC message definitions (roundpb, oorpb, swapclientrpc, wavewalletrpc) and HTTP transport (rpc/restclient)
rpc/wavewalletrpc Highest-level gRPC surface: WalletService with the seven core wallet verbs. Composes waverpc and rpc/swapclientrpc server-side via swapwallet
rpc/restclient HTTP/protoJSON transport adapter: Client, StreamClient[T], and per-service factory functions implementing the same gRPC stub interfaces over REST
waverpc Daemon gRPC API definitions
swaprpc Generated gRPC/REST/mailbox-RPC stubs for the external SwapService

Layer 4: Testing & Tooling

Package Purpose
p-models Executable P formal models and Go conformance bridge for distributed-systems properties (durable mailbox, Read/Commit fence, ingress deferral and redrive)
p-models/durableactor/bridge Go conformance harness: replays P model mailbox traces against the real db/actordelivery store
harness Docker-based Bitcoin/LND integration test environment
systest System-level end-to-end tests
internal/actortest Durable actor integration tests with real DB backends
internal/testutils Deterministic key/signature generation for tests
internal/indexerlimits Client-side bounds for indexer pagination cursors (defense-in-depth against misbehaving remotes)
rules ast-grep linting rules for code style enforcement
tools Development tool dependencies (protoc plugins, sqlc)
cmd/protoc-gen-mailboxrpc protoc plugin generating typed mailbox/rpc client/server stubs from .proto service definitions
scripts Build and verification scripts

Key Dependency Flows

waved (orchestrator)
├── round ──────────┐
│   ├── vtxo        │ (bidirectional: forfeit requests/confirmations)
│   ├── serverconn  │ (outbound RPCs to operator)
│   ├── timeout     │ (scheduling)
│   ├── wallet      │ (boarding intents)
│   ├── ledger      │ (VTXOReceivedMsg / FeePaidMsg via ledger.Sink)
│   └── lib         │ (tree, types, arkscript, bip322)
├── vtxo            │
│   ├── chainsource │ (block epoch events)
│   ├── ledger      │ (ExitCostMsg via ledger.Sink — emission planned)
│   └── db          │ (vtxo store)
├── wallet          │
│   ├── chainsource │ (UTXO confirmation monitoring)
│   ├── ledger      │ (UTXOCreatedMsg via ledger.Sink)
│   └── db          │ (boarding store)
├── oor             │
│   ├── db          │ (oor artifact store)
│   ├── ledger      │ (VTXOSentMsg / VTXOReceivedMsg via ledger.Sink)
│   └── lib/tx      │ (arktx, checkpoint, oor, psbtutil)
├── unroll          │ (unilateral-exit registry + per-target actor)
│   ├── txconfirm   │ (CPFP / confirmation tracking)
│   ├── lib/recovery│ (recovery proof graph)
│   ├── unrollplan  │ (pure dependency-resolution planner)
│   └── db          │ (unilateral_exit_jobs store)
├── txconfirm       │ (shared tx confirmation + CPFP actor; wired by waved)
├── ledger          │
│   ├── baselib/actor (durable mailbox, TLV codec)
│   └── db          │ (LedgerStoreDB + UTXOAuditStoreDB adapters)
├── serverconn      │
│   ├── mailbox     │ (protocol primitives)
│   └── db          │ (durable delivery store)
├── proofkeys       │ (wallet key derivation for indexer proofs)
│   └── walletcore / lndbackend (implementations)
├── chainsource     │
│   └── chainbackends (pluggable: LND, lwwallet, or btcwbackend)
└── db              │
    └── (SQLite | PostgreSQL)

Architectural Patterns

Protofsm State Machines

Business logic lives in pure FSM transition functions that take (State, Event) → (State, []OutboxEvent). Side effects are separated into outbox messages dispatched by the actor runtime. See baselib/protofsm.

Actor System

Concurrent, message-driven components communicate via Tell (fire-and-forget) and Ask (request-response). Actors are registered with a Receptionist for service discovery. See baselib/actor.

Durable Actors

Crash-safe actors persist FSM state + outbox atomically. On restart, undelivered outbox messages are replayed. At-least-once delivery with deduplication ensures exactly-once semantics. See docs/durable_actor_architecture.md.

RPC-over-Mailbox

All server communication flows through serverconn, which implements unary RPCs (low-latency) and durable event egress (crash-safe) over the mailbox protocol. Inbound events are dispatched via EventRouter. Registered routes currently include OOR lifecycle pushes, round progress pushes, and MethodIncomingVTXO (which delivers arkrpc.IncomingVTXOEvent notifications to the vtxo.IncomingVTXOHandler actor for local materialization of round-produced VTXOs owned by the local wallet). See docs/mailbox_architecture.md.

Data-Driven Script Ownership

Local wallet ownership of a VTXO is resolved at round confirmation time by looking up its pkScript in a persistent "owned receive scripts" table (the OOR artifact store). The round FSM calls OwnedScriptChecker.IsOwnedScript for every VTXO in a completed round and only persists the ones the wallet recognizes. The round actor populates this table via OwnedScriptRegistrar when it builds change/refresh intents and when it accepts a RegisterIntentMsg whose owner key has a non-zero KeyLocator. Directed-send recipient keys intentionally carry a zero KeyLocator so they are not registered on the sender side — the recipient materializes those VTXOs via the incoming VTXO push path instead.

Outbox Pattern

FSMs emit messages as data (outbox events). The actor runtime dispatches them after state is persisted. This ensures no message is sent without the corresponding state transition being durable.

Key Types and Interfaces

Type Package Purpose
ChainBackend chainsource Fee estimation, block/conf/spend notifications
BoardingBackend wallet Key derivation, taproot import, UTXO enumeration
VTXO.Descriptor vtxo Canonical VTXO: outpoint, amount, tapscript, tree path, CSV expiry
RoundClientActor round Primary FSM actor for interactive round phases
IntentPackage round Accumulated boarding/VTXO/forfeit/leave pools
BoardingAddress wallet 2-of-2 multisig (client+operator) with CSV timeout
Envelope mailbox/pb Durable unit of mailbox transport
RPCClient mailbox/rpc SendRPC/AwaitRPC interface for generated stubs
Message baselib/actor Sealed interface for actor messages
Ref[Msg, Resp] baselib/actor Typed actor reference (Tell, Ask)
ClientWallet round MuSig2 signing + key derivation interface for round participation
OwnedScriptChecker round Data-driven pkScript ownership lookup used by the round FSM at confirmation time (replaces the old IsOwner flag)
OwnedScriptRegistrar round Persists locally-owned pkScripts when the round actor builds/accepts VTXO intents so the checker recognizes them on confirmation
IncomingVTXOHandler vtxo Materializes round-produced VTXOs from indexer push notifications when the local wallet owns the receive script
OwnedScriptLookup vtxo Read-only view of the owned receive scripts store used by IncomingVTXOHandler
VTXOReader wallet Read-only VTXO descriptor access (breaks import cycle)
SelectedVTXO wallet Locked VTXO descriptor for transfer inputs (breaks import cycle)
TxInfo wallet Confirmed transaction with block hash and height
Backend proofkeys Wallet key derivation and proof signing interface
Node lib/arkscript Sealed AST node interface for tapscript compilation
VTXOPolicy lib/arkscript Compiled VTXO taproot policy with collab/exit spend paths

State Machines

Round FSM

Idle → PendingRoundAssembly → RegistrationSent → RoundJoined →
CommitmentTxReceived → CommitmentTxValidated → NoncesSent →
NoncesAggregated → PartialSigsSent → [ForfeitSignaturesCollecting] →
InputSigSent → Confirmed → Idle

ForfeitSignaturesCollecting is entered only when len(ForfeitMappings) > 0 (i.e., the round includes refresh or leave VTXOs). Boarding-only rounds skip directly from PartialSigsSent to InputSigSent. Forfeit collection happens after VTXO tree signing to ensure clients only forfeit old VTXOs once new ones are confirmed signed.

VTXO FSM

Live → PendingForfeit → Forfeiting → Forfeited
Live → Forfeiting → Forfeited  (fast path: ForfeitRequestEvent in LiveState)
PendingForfeit → UnilateralExit  (critical expiry while pending)
Live → UnilateralExit  (critical expiry)
Live → Spent
Any → Failed

OOR FSM

Manages outgoing/incoming transfer state through checkpoint signing with deterministic retry semantics. See oor/README.md (if present) or oor/doc.go.

Per-Package Agent Context

Each major package contains a CLAUDE.md/AGENTS.md with:

  • Purpose, key types, relationships (imports/imported-by)
  • Actor message flows and invariants
  • Links to deeper documentation

These files form a navigable graph. Start here, then follow links into packages relevant to your task.