Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ package may import from a higher layer.
| [`lib/recovery`](lib/recovery/) | Immutable recovery proof graph, session state machine, TLV codec for unilateral exit |
| [`unrollplan`](unrollplan/) | Pure dependency-resolution planner driving unilateral-exit broadcast/sweep ordering |
| [`vhtlcrecovery`](vhtlcrecovery/) | Durable control-plane types for vHTLC on-chain recovery jobs (action, state, script parameters, swap linkage) |
| [`coinselect`](coinselect/) | Shared coin-type-agnostic largest-first coin-selection algorithm used by `vtxo` (reservations) and `swapwallet` (send preview) |
| [`credit`](credit/) | Durable protofsm-actor subsystem driving server-side credit account pay/receive/redeem operations, reconciling Ark top-ups and wallet-owned auto-redeem |

### Layer 2: Infrastructure (Chain, Storage, Messaging)

Expand All @@ -36,6 +38,8 @@ package may import from a higher layer.
| [`baselib`](baselib/) | Actor framework (`baselib/actor`) and protofsm state machine engine (`baselib/protofsm`) |
| [`chainsource`](chainsource/) | `ChainBackend` interface: fee estimation, block/conf/spend notifications |
| [`chainbackends`](chainbackends/) | LND-backed `ChainBackend` implementation plus lndclient adapters (`TxBroadcaster`, `PackageSubmitter`) |
| [`chainbackends/lndsubmitter`](chainbackends/lndsubmitter/) | `PackageSubmitter` implementation relaying v3/TRUC CPFP packages via lnd's `WalletKit.SubmitPackage` RPC (lnd-wallet alternative to `chainbackends/bitcoindrpc`) |
| [`chainfees`](chainfees/) | `chainfee.Estimator` implementations (WalletKit-backed, mempool.space) and a min-selecting combinator |
| [`chain`](chain/) | Bitcoind RPC utilities (package relay, `SubmitPackage`) |
| [`txconfirm`](txconfirm/) | Generic "broadcast + CPFP fee-bump + notify on confirm" actor with per-parent fee-input reservations and BIP-125 Rule 3/4 enforcement |
| [`unroll`](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 |
Expand All @@ -48,6 +52,7 @@ package may import from a higher layer.
| [`vhtlcrecovery/coordinator`](vhtlcrecovery/coordinator/) | Runtime coordinator for durable vHTLC recovery jobs: arms, escalates into unroll, cancels, and reconciles after restart |
| [`vhtlcrecovery/unrollpolicy`](vhtlcrecovery/unrollpolicy/) | Adapter that resolves `(exit_policy_kind, recovery_id)` into a concrete `unroll.ExitSpendPolicy` for vHTLC claim and refund exits |
| [`db`](db/) | SQLite/PostgreSQL persistence: boarding, rounds, VTXOs, OOR artifacts, fee ledger |
| [`internal/sqlbase`](internal/sqlbase/) | `walletdb.DB` implementation emulating bbolt's nested bucket/key-value model over `database/sql`, gated to `js && wasm` builds; backs `lwwallet`'s browser OPFS SQLite store |
| [`mailbox`](mailbox/) | Mailbox protocol primitives across three sub-packages (pb, rpc, conn) |
| [`serverconn`](serverconn/) | Unified server connector: durable egress, ingress polling, unary RPC facade |
| [`serverconn/mailboxpull`](serverconn/mailboxpull/) | Shared exponential-backoff retry primitives for mailbox pull loops (used by serverconn ingress and SDK swap consumers) |
Expand All @@ -61,10 +66,13 @@ package may import from a higher layer.
| [`sdk/ark`](sdk/ark/) | Consumer-facing Go SDK facade: remote or embedded daemon access with typed models |
| [`sdk/swaps`](sdk/swaps/) | Lightning-to-Ark / Ark-to-Lightning atomic swap SDK with durable FSM flows |
| [`sdk/walletdk`](sdk/walletdk/) | 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 `walletdkrpc.WalletService`. Wallet RPC methods gated behind `walletdkrpc` (which transitively requires `swapruntime`) |
| [`sdk/walletdk/mobile`](sdk/walletdk/mobile/) | Gomobile-safe JSON facade over `sdk/walletdk` for iOS/Android host bindings, built via `gen_bindings.sh` |
| [`swapwallet`](swapwallet/) | Optional daemon-side `walletdkrpc.WalletService` implementation (build tags `walletdkrpc swapruntime`): composes the swap subsystem, cooperative leave, boarding, ledger, and unilateral-exit registry behind one flat, swap-vocabulary-free wallet API |
| [`swapclientserver`](swapclientserver/) | Optional daemon-side swap subserver (build tag `swapruntime`): translates `swapclientrpc` RPCs into `sdk/swaps` operations and manages the daemon-local worker registry |
| [`cmd/darepod`](cmd/darepod/) | Daemon entry point |
| [`cmd/darepocli`](cmd/darepocli/) | CLI client |
| [`cmd/walletdk-wasm`](cmd/walletdk-wasm/) | Browser js/wasm bridge exposing `sdk/walletdk/mobile`'s JSON facade to JavaScript via a single `walletdkCall` Promise dispatcher |
| [`rpcauth`](rpcauth/) | Shared TLS-cert and macaroon-credential helpers used by `darepod`'s server and clients (`darepocli`, wallet SDK) to secure and dial the gRPC/REST surface |
| [`timeout`](timeout/) | Generic timeout scheduling actor |
| [`indexer`](indexer/) | Server indexing client for receive script registration |
| [`arkrpc`](arkrpc/) | Server-side gRPC service definitions (ArkService, IndexerService) |
Expand Down
38 changes: 26 additions & 12 deletions chainbackends/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ estimation, and optional v3 package relay via a pluggable `PackageSubmitter`.
- `TxBroadcaster` — Interface over transaction broadcasting (wraps
lndclient.WalletKitClient or in-process lnd).
- `PackageSubmitter` — Optional interface for v3 package relay:
`SubmitPackage(ctx, parents, child, maxFeeRate)`. Used by backends that need
a direct bitcoind path for atomic parent+child submission; absent in
environments that do not support package relay.
`SubmitPackage(ctx, parents, child, maxFeeRate)`. Pluggable: implementations
exist for a direct bitcoind path (`chainbackends/bitcoindrpc`) and for
relaying through lnd's own `WalletKit.SubmitPackage` RPC
(`chainbackends/lndsubmitter`); absent in environments that do not support
package relay.
- `LndClientTxBroadcaster` — Implements `TxBroadcaster` using
`lndclient.WalletKitClient`.
- `LndClientFeeEstimator` — Type alias for
Expand Down Expand Up @@ -48,20 +50,32 @@ estimation, and optional v3 package relay via a pluggable `PackageSubmitter`.

- **Depends on**: `chainsource` (implements `ChainBackend` interface).
- **Depended on by**: `darepod` (instantiates backend and wires a
`PackageSubmitter` from operator config: production uses
`chainbackends/bitcoindrpc.PackageSubmitter` directly, itests inject the
same submitter from the harness).
`PackageSubmitter`: an explicitly configured submitter — production's
`chainbackends/bitcoindrpc.PackageSubmitter` when bitcoind flags are set, or
the itest harness's injected submitter via `darepod.Config.PackageSubmitter`
— takes precedence; otherwise `darepod` falls back to
`chainbackends/lndsubmitter.New(lndSvc.WalletKit)` so an lnd-wallet-backed
daemon can relay packages through lnd's own chain connection with no
separate bitcoind RPC or Esplora endpoint); `chainbackends/lndsubmitter`
(sibling sub-package that implements `PackageSubmitter` against lnd's
`WalletKit.SubmitPackage` RPC).

## Invariants

- `LNDBackend` requires an lnd instance (local or remote via lndclient).
- Provides real-time notifications via lnd's chainntnfs package.
- `PackageSubmitter` is optional; package-capable backends return an error
from `SubmitPackage` when no submitter is set. In production `cmd/darepod`
injects
`chainbackends/bitcoindrpc.PackageSubmitter` when bitcoind flags are
configured; the itest harness injects the same type via
`darepod.Config.PackageSubmitter`.
- `PackageSubmitter` is optional at the `LNDBackend` level;
`SubmitPackage` returns an error when no submitter is set. In practice
`cmd/darepod` always wires one for the lnd wallet backend: an explicit
submitter (bitcoind flags / itest harness) takes precedence, otherwise it
defaults to `chainbackends/lndsubmitter` backed by lnd's own WalletKit.
- When the configured submitter reports lnd's neutrino
`"broadcast-unverified"` sentinel (`lndNeutrinoBroadcastMsg`) with no
per-tx errors, `LNDBackend.SubmitPackage` treats it as a successful
best-effort broadcast rather than a rejection — a light client has no
mempool and cannot return a real package-accept verdict, so it broadcasts
each tx individually over P2P and relies on peer relay/confirmation to
decide the outcome.
- `LndClientChainNotifier` enforces a 15-second timeout on registration to
prevent hanging under LND block load.
- Log messages use canonical txid strings (not reversed byte slices).
Expand Down
38 changes: 26 additions & 12 deletions chainbackends/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ estimation, and optional v3 package relay via a pluggable `PackageSubmitter`.
- `TxBroadcaster` — Interface over transaction broadcasting (wraps
lndclient.WalletKitClient or in-process lnd).
- `PackageSubmitter` — Optional interface for v3 package relay:
`SubmitPackage(ctx, parents, child, maxFeeRate)`. Used by backends that need
a direct bitcoind path for atomic parent+child submission; absent in
environments that do not support package relay.
`SubmitPackage(ctx, parents, child, maxFeeRate)`. Pluggable: implementations
exist for a direct bitcoind path (`chainbackends/bitcoindrpc`) and for
relaying through lnd's own `WalletKit.SubmitPackage` RPC
(`chainbackends/lndsubmitter`); absent in environments that do not support
package relay.
- `LndClientTxBroadcaster` — Implements `TxBroadcaster` using
`lndclient.WalletKitClient`.
- `LndClientFeeEstimator` — Type alias for
Expand Down Expand Up @@ -48,20 +50,32 @@ estimation, and optional v3 package relay via a pluggable `PackageSubmitter`.

- **Depends on**: `chainsource` (implements `ChainBackend` interface).
- **Depended on by**: `darepod` (instantiates backend and wires a
`PackageSubmitter` from operator config: production uses
`chainbackends/bitcoindrpc.PackageSubmitter` directly, itests inject the
same submitter from the harness).
`PackageSubmitter`: an explicitly configured submitter — production's
`chainbackends/bitcoindrpc.PackageSubmitter` when bitcoind flags are set, or
the itest harness's injected submitter via `darepod.Config.PackageSubmitter`
— takes precedence; otherwise `darepod` falls back to
`chainbackends/lndsubmitter.New(lndSvc.WalletKit)` so an lnd-wallet-backed
daemon can relay packages through lnd's own chain connection with no
separate bitcoind RPC or Esplora endpoint); `chainbackends/lndsubmitter`
(sibling sub-package that implements `PackageSubmitter` against lnd's
`WalletKit.SubmitPackage` RPC).

## Invariants

- `LNDBackend` requires an lnd instance (local or remote via lndclient).
- Provides real-time notifications via lnd's chainntnfs package.
- `PackageSubmitter` is optional; package-capable backends return an error
from `SubmitPackage` when no submitter is set. In production `cmd/darepod`
injects
`chainbackends/bitcoindrpc.PackageSubmitter` when bitcoind flags are
configured; the itest harness injects the same type via
`darepod.Config.PackageSubmitter`.
- `PackageSubmitter` is optional at the `LNDBackend` level;
`SubmitPackage` returns an error when no submitter is set. In practice
`cmd/darepod` always wires one for the lnd wallet backend: an explicit
submitter (bitcoind flags / itest harness) takes precedence, otherwise it
defaults to `chainbackends/lndsubmitter` backed by lnd's own WalletKit.
- When the configured submitter reports lnd's neutrino
`"broadcast-unverified"` sentinel (`lndNeutrinoBroadcastMsg`) with no
per-tx errors, `LNDBackend.SubmitPackage` treats it as a successful
best-effort broadcast rather than a rejection — a light client has no
mempool and cannot return a real package-accept verdict, so it broadcasts
each tx individually over P2P and relies on peer relay/confirmation to
decide the outcome.
- `LndClientChainNotifier` enforces a 15-second timeout on registration to
prevent hanging under LND block load.
- Log messages use canonical txid strings (not reversed byte slices).
Expand Down
46 changes: 46 additions & 0 deletions chainbackends/lndsubmitter/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# lndsubmitter

## Purpose

Implements `chainbackends.PackageSubmitter` by relaying v3/TRUC CPFP packages
through lnd's own `WalletKit.SubmitPackage` RPC. Lets a darepod running the
lnd wallet backend broadcast zero-fee unilateral-exit packages without a
separate bitcoind RPC or Esplora endpoint.

## Key Types

- `Submitter` — Relays a parents-first, child-last package to lnd's
`WalletKit.SubmitPackage` RPC and maps the lndclient-native result back to
`btcjson.SubmitPackageResult`. Constructed via `New(walletKit)`.
- `walletKitSubmitter` — Unexported interface narrowing
`lndclient.WalletKitClient` down to just `SubmitPackage`, so tests can fake
it without a full lndclient mock.

## Relationships

- **Depends on**: `lndclient` (WalletKit RPC client and
`SubmitPackageResult`), `lnd/lnwallet/chainfee` (`SatPerVByte` for the
max-fee-rate ceiling), `btcd/btcjson` (result type returned to callers),
`btcd/wire` (`MsgTx`).
- **Depended on by**: `darepod` (`darepod/server.go` constructs
`lndsubmitter.New(lndSvc.WalletKit)` and wires it in as the
`chainbackends.PackageSubmitter` when the daemon runs the lnd wallet
backend, instead of the bitcoind-direct `chainbackends/bitcoindrpc`
submitter).

## Invariants

- `SubmitPackage` rejects a nil child or any nil parent up front with a typed
error, rather than letting lndclient/wire serialization panic on a nil
pointer deep in the call stack.
- The optional `maxFeeRate` ceiling arrives as BTC/kvB (bitcoind's
`maxfeerate` shape, per the `chainbackends.PackageSubmitter` contract) and
must be converted to sat/vByte for lnd's RPC by rounding to the nearest
integer, not truncating — truncation would silently make the ceiling
stricter than the caller asked for (e.g. 12.5 sat/vByte → 12).
- `mapResult` only sets a `TxResults` entry's `Error` field when lnd reported
a non-empty rejection reason; an empty string means the tx was accepted.

## Deep Docs

- [ARCHITECTURE.md](../../ARCHITECTURE.md) — System-wide package map.
46 changes: 46 additions & 0 deletions chainbackends/lndsubmitter/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# lndsubmitter

## Purpose

Implements `chainbackends.PackageSubmitter` by relaying v3/TRUC CPFP packages
through lnd's own `WalletKit.SubmitPackage` RPC. Lets a darepod running the
lnd wallet backend broadcast zero-fee unilateral-exit packages without a
separate bitcoind RPC or Esplora endpoint.

## Key Types

- `Submitter` — Relays a parents-first, child-last package to lnd's
`WalletKit.SubmitPackage` RPC and maps the lndclient-native result back to
`btcjson.SubmitPackageResult`. Constructed via `New(walletKit)`.
- `walletKitSubmitter` — Unexported interface narrowing
`lndclient.WalletKitClient` down to just `SubmitPackage`, so tests can fake
it without a full lndclient mock.

## Relationships

- **Depends on**: `lndclient` (WalletKit RPC client and
`SubmitPackageResult`), `lnd/lnwallet/chainfee` (`SatPerVByte` for the
max-fee-rate ceiling), `btcd/btcjson` (result type returned to callers),
`btcd/wire` (`MsgTx`).
- **Depended on by**: `darepod` (`darepod/server.go` constructs
`lndsubmitter.New(lndSvc.WalletKit)` and wires it in as the
`chainbackends.PackageSubmitter` when the daemon runs the lnd wallet
backend, instead of the bitcoind-direct `chainbackends/bitcoindrpc`
submitter).

## Invariants

- `SubmitPackage` rejects a nil child or any nil parent up front with a typed
error, rather than letting lndclient/wire serialization panic on a nil
pointer deep in the call stack.
- The optional `maxFeeRate` ceiling arrives as BTC/kvB (bitcoind's
`maxfeerate` shape, per the `chainbackends.PackageSubmitter` contract) and
must be converted to sat/vByte for lnd's RPC by rounding to the nearest
integer, not truncating — truncation would silently make the ceiling
stricter than the caller asked for (e.g. 12.5 sat/vByte → 12).
- `mapResult` only sets a `TxResults` entry's `Error` field when lnd reported
a non-empty rejection reason; an empty string means the tx was accepted.

## Deep Docs

- [ARCHITECTURE.md](../../ARCHITECTURE.md) — System-wide package map.
62 changes: 62 additions & 0 deletions chainfees/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# chainfees

## Purpose

Reusable `chainfee.Estimator` implementations and combinators for wallet and
daemon chain backends: an lnd `WalletKit`-backed estimator, a mempool.space
HTTP-backed estimator, and a `MinEstimator` selector that composes several
providers and picks the lowest live rate.

## Key Types

- `WalletKitEstimator` — Proxies `EstimateFeePerKW` to an
`lndclient.WalletKitClient`. Fail-fast by default (`NewWalletKitEstimator`);
`NewFallbackWalletKitEstimator` instead serves the last successful rate (or
fails closed before any success) rather than propagating errors.
- `MempoolSpaceEstimator` — Queries mempool.space's recommended-fee HTTP
endpoint, mapping `fastestFee`/`halfHourFee`/`hourFee`/`economyFee`/
`minimumFee` buckets onto confirmation targets. Caches the response for
`CacheTTL` (default 30s) and rejects non-loopback plaintext HTTP endpoints.
- `MinEstimator` — Wraps one or more `NamedEstimator` children and returns the
minimum successful estimate per call; falls back to the last selected rate
(or the relay floor) only when every child fails.
- `NamedEstimator` — Pairs a `chainfee.Estimator` child with a stable `Name`
for logging inside `MinEstimator`.
- `DefaultMempoolSpaceURL(params)` — Resolves the network-specific
mempool.space recommended-fee URL (mainnet/testnet3/testnet4/signet).

## Relationships

- **Depends on**: `lndclient` (`WalletKitClient` for `WalletKitEstimator`),
`lnd/lnwallet/chainfee` (`Estimator` interface, `SatPerKWeight`,
`FeePerKwFloor`), `btcd/chaincfg` and `btcd/wire` (network selection in
`DefaultMempoolSpaceURL`), `btclog` (structured logging).
- **Depended on by**: `chainbackends` (`chainbackends/lndclient_adapters.go`
aliases `LndClientFeeEstimator = chainfees.WalletKitEstimator` and builds
the default lnd fee estimator via `NewFallbackWalletKitEstimator`),
`darepod` (`darepod/server.go`'s `lndFeeEstimator` composes a fail-fast
`WalletKitEstimator` and a `MempoolSpaceEstimator` under a `MinEstimator`
when the mempool.space provider is enabled; `darepod/logging.go` registers
`chainfees.Subsystem` as a log subsystem).

## Invariants

- A child estimator composed inside `MinEstimator` (or `WalletKitEstimator`
used there) must be fail-fast, not fallback-on-error: a stale fallback rate
could otherwise beat another provider's live estimate and win the minimum.
Never pass a `NewFallbackWalletKitEstimator` into `NewMinEstimator`.
- Every estimator clamps successful rates up to `chainfee.FeePerKwFloor`
before returning or caching them, so a cached value below the floor is the
sentinel for "no successful estimate yet" (see `WalletKitEstimator.
cachedRate`).
- `MempoolSpaceEstimator` requires an absolute `https` URL; plaintext `http`
is only accepted for a loopback host, and the HTTP response body is capped
at 64 KiB to bound memory from a misbehaving endpoint.
- `NewMinEstimator` and `NewWalletKitEstimatorWithConfig` validate inputs
(non-empty names, non-nil estimators/clients) at construction so callers
fail fast instead of panicking on first use of a malformed value boxed into
the `chainfee.Estimator` interface.

## Deep Docs

- [ARCHITECTURE.md](../ARCHITECTURE.md) — System-wide package map.
Loading
Loading