Skip to content

feat: stateless contract construction - #164

Merged
bennyhodl merged 5 commits into
masterfrom
stateless-dlc-creation
Aug 4, 2026
Merged

feat: stateless contract construction#164
bennyhodl merged 5 commits into
masterfrom
stateless-dlc-creation

Conversation

@bennyhodl

Copy link
Copy Markdown
Owner

No description provided.

@bennyhodl
bennyhodl force-pushed the stateless-dlc-creation branch 3 times, most recently from ff38318 to bf7746c Compare July 27, 2026 18:16
bennyhodl and others added 5 commits August 3, 2026 21:15
Add splicing — spending a previous contract's 2-of-2 funding output as an
input to a new contract — to the stateless ddk/src/contract API, mirroring
the ddk-manager / dlc-crate flow. This is what rollovers and collateral
changes require.

- create_dlc_splice_input rebuilds the splice funding input from the
  previous contract's offer and accept messages
- build_context routes to create_spliced_dlc_transactions when a DLC input
  is present; dlc_party_params populates PartyParams.dlc_inputs
- sign_accept_spliced / finalize_sign_spliced add the 2-of-2 signing path:
  the offer party produces its half, the accept party verifies it and
  combines both halves into the final witness
- DLC inputs are held out of the wallet-PSBT path and validated on the
  offer side (2-of-2 script, witness length, no redeem script)

Scope is offer-only, matching ddk-manager and the borrower-is-offerer app
flow. Covered by guard unit tests and end-to-end splice-in / splice-out
integration tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add ContractKeyProvider, a standalone deterministic derivation of DLC
contract funding keys from a master extended private key: a contract's
funding key is a pure function of its temporary id (keys_id), so keys are
recomputed on demand and never stored. This is what the stateless splice
API needs — dlc_input_signing_key re-derives a previous contract's funding
key from its temporary id.

- Construct from an xpriv, seed, BIP39 mnemonic, or a private descriptor
- funding_pubkey / funding_secret_key / dlc_input_signing_key helpers
- implements ddk_manager::ContractSignerProvider, so it also drives a
  manager directly
- DlcDevKitWallet now delegates its derivation to ContractKeyProvider,
  making it the single source of truth (keys interchangeable between the
  stateful manager path and the stateless API)
- stateless examples derive their DLC funding keys via the provider; the
  splice example uses dlc_input_signing_key to recover prior keys

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The stateless `contract` module (and `ContractKeyProvider`) is pure and
sync, but the rest of `ddk` is async top-to-bottom and pulls zeromq,
tokio (full), and bdk_esplora — none of which cross-compile cleanly to
iOS/Android. FFI/mobile consumers (ddk-ffi) only need `contract`.

Add a default-on `manager` feature that gates every async/app module
(builder, chain, ddk, error, json, logger, oracle, storage, transport,
util, wallet) and the root Transport/Storage/Oracle/KeyStorage/Balance
items. The heavy deps are now optional and enabled only by `manager`;
existing flags (nostr/lightning/kormir/postgres/sled/p2pderivatives)
imply it. `contract` is the only module compiled without `manager` and
needs nothing heavier than ddk-manager (tokio "sync").

Consumers using `default-features = false` (the ddk-manager dev-dep) opt
back in with `features = ["manager"]`. External `ddk = "1.x"` users are
unaffected (default = manager = current behavior).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bennyhodl
bennyhodl force-pushed the stateless-dlc-creation branch from b6a7033 to 3868897 Compare August 4, 2026 02:09
@bennyhodl
bennyhodl merged commit c00a101 into master Aug 4, 2026
88 checks passed
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