Repository navigation
Conversation
Owner
Author
|
Note 馃 Claude Opus 5.5 responding on behalf of bennyhodl Review against orange-grove's consumers ( This deletes about 200 lines of witness construction, decryption and signature checks from
|
Both parties' CET adaptor signatures are encrypted to the same point, so the sum of the oracle signatures decrypts either one. Settling from the messages alone needs that sum outside the crate. Rename the private signatures_to_secret to the public adaptor_secret; sign_cet uses it.
Each party's CET adaptor signatures and refund signature travel in the message it sent, so either party, a watchtower or a server can close the contract without a funding key. Add settle_cet_from_messages and settle_refund_from_messages. settle.rs now has one path for CET selection, attestation validation and verification of signatures taken from the messages, and one witness assembly ordered by the funding script's keys. The key-based and keyless functions differ only in where the settling party's half comes from, and return the same transaction (same txid; the refund is byte-identical). sign_cet's output is unchanged byte for byte.
CET settlement now checks every oracle announcement of the contract before any adaptor work. OracleEvent::validate already requires exactly one nonce on an enum event, so an announcement that uses one nonce per outcome (the Magnolia convention) is refused up front with InvalidOffer, instead of failing in the positional nonce check of OracleAttestation::validate. The per-outcome convention is documented as unsupported. Refund settlement does not check announcements, so such a contract can still be refunded. OracleAttestation::validate now also binds the attestation's event id to the announcement's. The nonce check already binds it in practice; this is defence in depth. Every in-tree oracle builds its attestation from the announcement's event id, so the manager's callers are unaffected. settle_cet_from_messages returns a CetSettlement carrying the CET's index among the contract's CETs alongside the transaction, so consumers no longer recompute it from the descriptor. The contract docs now say what settlement verifies: the signatures it needs to close, not the whole signed contract. Callers that want the full check are pointed to verify_signed_contract.
bennyhodl
force-pushed
the
benny/225-keyless-settlement
branch
from
October 15, 2026 18:40
3a27ba0 to
52c3a1d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Item 3 of #225. Both parties' CET adaptor signatures and both refund signatures are already in the offer, accept and sign messages. So anyone holding the three messages can close a contract without a key: either party, a watchtower, or a server. Today
sign_cet/sign_refundrequire the funding secret key, and the adaptor-secret sum in ddk-dlc is private.Changes
ddk::contract::settle_cet_from_messages(offer, accept, sign, attestations): decrypts both parties' adaptor signatures with the oracle secret, verifies each against the CET under its party's funding key, and orders the witness by key. It covers enum, numeric and multi-oracle contracts.ddk::contract::settle_refund_from_messages(offer, accept, sign): verifies both stored refund signatures, then combines them.ddk_dlc::adaptor_secretis public. It is the former privatesignatures_to_secret;ddk_dlc::sign_cetuses it.settle.rsis restructured around one privateSettlement. CET selection, attestation validation and signature checks live there once. The key-based and keyless functions differ only in where the settling party's half comes from.Compatibility
sign_cetandsign_refundproduce the same transactions as before, witness bytes included. On a key tie the witness ordering followsddk_dlc::util::sign_multi_sig_input.InvalidAttestation, and an adaptor signature that won't decrypt is nowInvalidAccept/InvalidSign(naming the message that carried it). Both wereContractError::Dlcbefore. I kept the more precise variants rather than give the key-based path its own error mapping.Follow-ups
settle.rsshould switch toddk_dlc::util::multisig_witnessonce the verify-signed-contract PR (item 2) lands. The two PRs are independent.sign_refundis now redundant:settle_refund_from_messagesreturns identical bytes for either party.sign_cetmostly is too. Deprecating them is a separate decision.Testing
ddk/tests/stateless.rs:sign_cet's txid for both parties, and the witness signatures are verified asOP_CHECKMULTISIGwould.sign_refundbyte for byte.ddk/tests/stateless_execution.rs, regtest broadcast and confirm:enum_three_of_five_oracles_closes_from_the_messages,numeric_with_difference_three_of_five_oracles_closes_from_the_messages,refund_closes_the_contract_from_the_messages.-D warningsclean.