Skip to content

v2.0.0-rc.7

Pre-release
Pre-release

Choose a tag to compare

@bennyhodl bennyhodl released this 24 Sep 17:34
· 23 commits to master since this release
6acb538

DDK v2.0.0-rc.7

This release fixes settlement and splicing for single-funded contracts created before 2.0.0-rc.4. In rc.4 the CET fee rule changed, so rebuilding one of these older contracts from its messages produced different transactions than the ones both parties had signed. Neither party could settle or splice them. From rc.7, DDK finds which fee rule a signed contract was built under and rebuilds it with that rule.

⚠️ Breaking Changes

  • ddk::contract::create_dlc_splice_input takes a new prev_sign: &SignDlc argument (after prev_accept). The previous contract's sign message tells DDK which fee rule to use when rebuilding the funding output. The input's contract id now comes straight from prev_sign.contract_id and is no longer recomputed from the rebuilt transactions. Callers must pass the previous contract's SignDlc. (f0eb245)

    // before
    create_dlc_splice_input(&prev_offer, &prev_accept, local_party, serial_id, max_witness_len)
    // after
    create_dlc_splice_input(&prev_offer, &prev_accept, &prev_sign, local_party, serial_id, max_witness_len)

🐛 Bug Fixes

  • Settle and splice contracts built under the pre-rc.4 fee rule (f0eb245)
    • Cause: ddk-dlc 2.0.0-rc.4 made the party that funds the whole contract also pay the CET fee for the counterparty's payout output. For a single-funded contract this changes the fund output, and so the funding txid and the contract id. The signatures stored for contracts created before rc.4 cover the original transactions, so rebuilding under the new rule produced transactions those signatures don't match.
    • Fix: sign_cet, sign_refund and create_dlc_splice_input now rebuild the contract with a new internal signed_context helper. It tries the current rule first. If the result doesn't match the sign message's contract id, it tries the old rule and accepts it only if it reproduces that contract id exactly. If neither rule matches, the call returns an error.
    • Scope: Only rebuilding an existing signed contract uses the fallback. Creating a contract (offer, accept, sign, finalize, validate) still uses only the current rule, so new contracts are unaffected.
    • Tests: a single-funded contract captured from ddk 2.0.0-rc.3 is checked in as a fixture. Its refund and CET settle to exactly the bytes rc.3 produced.

✨ New APIs

These additions come with the fix above (f0eb245).

ddk-dlc

  • FeeRule enum, which sets how CET fees are split between the parties:

    • FeeRule::CounterpartyPayout (default, rc.4 and later): a party funding the whole contract also pays the CET fee for the counterparty's payout output.
    • FeeRule::OwnPayoutOnly (before rc.4): each party pays the CET fee for its own payout output only.
  • New variants that take an explicit FeeRule:

    • create_dlc_transactions_with_fee_rule
    • create_spliced_dlc_transactions_with_fee_rule
    • create_fund_transaction_with_fees_and_rule

    The existing create_dlc_transactions, create_spliced_dlc_transactions and create_fund_transaction_with_fees keep their signatures and use FeeRule::CounterpartyPayout.

ddk

  • ddk::contract::create_signed_dlc_transactions(offer, accept, sign) rebuilds a signed contract's transactions under the fee rule whose funding transaction matches sign's contract id. It tries CounterpartyPayout first, then OwnPayoutOnly, and fails if neither matches. Use it instead of create_dlc_transactions whenever you rebuild a contract that is already signed.

Upgrading

  • What keeps working: contracts created before rc.4 (including single-funded contracts from rc.3 and earlier) can settle through CETs, be refunded, and be spliced again. Their stored messages and signatures don't need to be migrated. DDK rebuilds the exact transactions that were originally signed.
  • Contracts from rc.4 to rc.6 are unaffected. They match the current rule on the first try.
  • Wire format: unchanged. New contracts are built the same way as in rc.4–rc.6.
  • Code changes:
    • Pass the previous contract's SignDlc to create_dlc_splice_input, as shown under Breaking Changes. ddk/examples/stateless_splice.rs shows the updated call.
    • If you call ddk::contract::create_dlc_transactions to rebuild a contract that is already signed (for example, to find the funding outpoint), switch to create_signed_dlc_transactions. Otherwise a pre-rc.4 single-funded contract will produce the wrong funding txid.

Crates Released

All workspace crates are published at 2.0.0-rc.7:

Crate Description
ddk Main DLC DevKit library
ddk-manager DLC management and coordination
ddk-dlc Core DLC functionality
ddk-messages DLC message protocol implementation
ddk-trie Trie data structure for DLC
ddk-payouts Payout calculation utilities
ddk-node DLC node implementation
kormir Oracle implementation

Installation

Add DDK to your Cargo.toml:

[dependencies]
ddk = "2.0.0-rc.7"

To use the lower-level crates directly, pin them to the same version:

[dependencies]
ddk = "2.0.0-rc.7"
ddk-dlc = "2.0.0-rc.7"
ddk-messages = "2.0.0-rc.7"

Full Changelog: v2.0.0-rc.6...v2.0.0-rc.7