ddk_messages/
channel.rs

1//! Contains messages used for the establishment and update of DLC channels.
2
3use bitcoin::{Amount, ScriptBuf};
4use ddk_dlc::Error;
5use lightning::ln::msgs::DecodeError;
6use lightning::util::ser::{Readable, Writeable, Writer};
7use secp256k1_zkp::{
8    ecdsa::Signature, EcdsaAdaptorSignature, PublicKey, Secp256k1, SecretKey, Verification,
9};
10
11use crate::FundingSignatures;
12use crate::{
13    contract_msgs::ContractInfo,
14    ser_impls::{read_ecdsa_adaptor_signature, write_ecdsa_adaptor_signature},
15    types::*,
16    CetAdaptorSignatures, FundingInput, NegotiationFields,
17};
18
19/// Contains information about a party wishing to enter into a DLC with
20/// another party. The contained information is sufficient for any other party
21/// to create a set of transactions representing the contract and its terms.
22#[derive(Clone, Debug, PartialEq)]
23#[cfg_attr(
24    feature = "use-serde",
25    derive(serde::Serialize, serde::Deserialize),
26    serde(rename_all = "camelCase")
27)]
28pub struct OfferChannel {
29    /// The version of the protocol used by the sending peer.
30    pub protocol_version: u32,
31    /// Indicates options and features selected for the offered contract.
32    pub contract_flags: u8,
33    /// The identifier of the chain on which the contract takes place.
34    #[cfg_attr(
35        feature = "use-serde",
36        serde(
37            serialize_with = "crate::serde_utils::serialize_hex",
38            deserialize_with = "crate::serde_utils::deserialize_hex_array"
39        )
40    )]
41    pub chain_hash: [u8; 32],
42    /// A random nonce identifying the contract until the fund transaction
43    /// is created.
44    pub temporary_contract_id: [u8; 32],
45    /// A random nonce identifying the channel until the fund transaction is
46    /// created.
47    pub temporary_channel_id: [u8; 32],
48    /// Information about the contract established during channel creation.
49    pub contract_info: ContractInfo,
50    /// The public key used by the offer party in the 2 of 2 funding output.
51    pub funding_pubkey: PublicKey,
52    /// The base point that will be used by the offer party for revocation.
53    pub revocation_basepoint: PublicKey,
54    /// The base point that will be used by the offer party for generating
55    /// adaptor signatures to revocable transactions.
56    pub publish_basepoint: PublicKey,
57    /// The base point that will be used by the offer party in the 2 of 2 output
58    /// of buffer transactions.
59    pub own_basepoint: PublicKey,
60    /// The first per update point of the offer party.
61    pub first_per_update_point: PublicKey,
62    /// Script used by the offer party to receive their payout on channel close.
63    pub payout_spk: ScriptBuf,
64    /// Serial id used to order outputs.
65    pub payout_serial_id: u64,
66    /// The collateral input by the offer party in the channel.
67    pub offer_collateral: Amount,
68    /// The inputs that the offer party will use to fund the channel.
69    pub funding_inputs: Vec<FundingInput>,
70    /// The script that the offer party to receive their change.
71    pub change_spk: ScriptBuf,
72    /// Serial id used to order outputs.
73    pub change_serial_id: u64,
74    /// Serial id used to order outputs.
75    pub fund_output_serial_id: u64,
76    /// The fee rate proposed by the offer party for the channel transactions.
77    pub fee_rate_per_vb: u64,
78    /// Lock time for the CETs.
79    pub cet_locktime: u32,
80    /// Lock time for the refund transaction.
81    pub refund_locktime: u32,
82    /// The nSequence value to use for the CETs.
83    pub cet_nsequence: u32,
84}
85
86impl_dlc_writeable!(OfferChannel, OFFER_CHANNEL_TYPE, {
87        (protocol_version, writeable),
88        (contract_flags, writeable),
89        (chain_hash, writeable),
90        (temporary_contract_id, writeable),
91        (temporary_channel_id, writeable),
92        (contract_info, writeable),
93        (funding_pubkey, writeable),
94        (revocation_basepoint, writeable),
95        (publish_basepoint, writeable),
96        (own_basepoint, writeable),
97        (first_per_update_point, writeable),
98        (payout_spk, writeable),
99        (payout_serial_id, writeable),
100        (offer_collateral, writeable),
101        (funding_inputs, vec),
102        (change_spk, writeable),
103        (change_serial_id, writeable),
104        (fund_output_serial_id, writeable),
105        (fee_rate_per_vb, writeable),
106        (cet_locktime, writeable),
107        (refund_locktime, writeable),
108        (cet_nsequence, writeable)
109});
110
111impl OfferChannel {
112    /// Returns whether the message satisfies validity requirements.
113    pub fn validate<C: Verification>(
114        &self,
115        secp: &Secp256k1<C>,
116        min_timeout_interval: u32,
117        max_timeout_interval: u32,
118        min_cet_nsequence: u32,
119        max_cet_nsequence: u32,
120    ) -> Result<(), Error> {
121        let closest_maturity_date = self.contract_info.get_closest_maturity_date();
122        let valid_dates = self.cet_locktime <= closest_maturity_date
123            && closest_maturity_date + min_timeout_interval <= self.refund_locktime
124            && self.refund_locktime <= closest_maturity_date + max_timeout_interval
125            && self.cet_nsequence >= min_cet_nsequence
126            && self.cet_nsequence <= max_cet_nsequence;
127        if !valid_dates {
128            return Err(Error::InvalidArgument(
129                "Locktime is less than closest maturity date".to_string(),
130            ));
131        }
132
133        match &self.contract_info {
134            ContractInfo::SingleContractInfo(s) => s.contract_info.oracle_info.validate(secp)?,
135            ContractInfo::DisjointContractInfo(d) => {
136                for c in &d.contract_infos {
137                    c.oracle_info.validate(secp)?;
138                }
139            }
140        }
141
142        Ok(())
143    }
144}
145
146/// Contains information about a party wishing to accept a DLC offer. The contained
147/// information is sufficient for the offering party to re-build the set of
148/// transactions representing the contract and its terms, and guarantees the offering
149/// party that they can safely provide signatures for their funding input.
150#[derive(Clone, Debug, PartialEq, Eq)]
151#[cfg_attr(
152    feature = "use-serde",
153    derive(serde::Serialize, serde::Deserialize),
154    serde(rename_all = "camelCase")
155)]
156pub struct AcceptChannel {
157    #[cfg_attr(
158        feature = "use-serde",
159        serde(
160            serialize_with = "crate::serde_utils::serialize_hex",
161            deserialize_with = "crate::serde_utils::deserialize_hex_array"
162        )
163    )]
164    /// The temporary id of the channel.
165    pub temporary_channel_id: [u8; 32],
166    /// The collateral input by the accept party.
167    pub accept_collateral: Amount,
168    /// The [`PublicKey`] used for the fund output by the accept party.
169    pub funding_pubkey: PublicKey,
170    /// The [`PublicKey`] used for deriving revocation points by the accept party.
171    pub revocation_basepoint: PublicKey,
172    /// The [`PublicKey`] used for deriving publish points by the accept party.
173    pub publish_basepoint: PublicKey,
174    /// The [`PublicKey`] used for deriving own points by the accept party.
175    pub own_basepoint: PublicKey,
176    /// The initial per update point used by the accept party.
177    pub first_per_update_point: PublicKey,
178    /// The script pubkey for the accept party to receive their payout.
179    pub payout_spk: ScriptBuf,
180    /// The serial id of the payout output used to order transaction outputs.
181    pub payout_serial_id: u64,
182    /// The set of inputs used by the accept party to fund the channel.
183    pub funding_inputs: Vec<FundingInput>,
184    /// The script pubkey used by the accept party to receive back their change.
185    pub change_spk: ScriptBuf,
186    /// The serial id of the change output used to order transaction outputs.
187    pub change_serial_id: u64,
188    /// The adaptor signatures for all CETs generated by the accept party.
189    pub cet_adaptor_signatures: CetAdaptorSignatures,
190    /// The adaptor signature for the buffer transaction generated by the accept
191    /// party.
192    pub buffer_adaptor_signature: EcdsaAdaptorSignature,
193    /// The refund signature generated by the accept party.
194    pub refund_signature: Signature,
195    /// Fields used to negotiate parameters with the counter party.
196    pub negotiation_fields: Option<NegotiationFields>,
197}
198
199impl_dlc_writeable!(AcceptChannel, ACCEPT_CHANNEL_TYPE, {
200    (temporary_channel_id, writeable),
201    (accept_collateral, writeable),
202    (funding_pubkey, writeable),
203    (revocation_basepoint, writeable),
204    (publish_basepoint, writeable),
205    (own_basepoint, writeable),
206    (first_per_update_point, writeable),
207    (payout_spk, writeable),
208    (payout_serial_id, writeable),
209    (funding_inputs, vec),
210    (change_spk, writeable),
211    (change_serial_id, writeable),
212    (cet_adaptor_signatures, writeable),
213    (buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}),
214    (refund_signature, writeable),
215    (negotiation_fields, option)
216});
217
218#[derive(Clone, Debug, PartialEq, Eq)]
219#[cfg_attr(
220    feature = "use-serde",
221    derive(serde::Serialize, serde::Deserialize),
222    serde(rename_all = "camelCase")
223)]
224/// Message used to finalize the setup of a DLC channel.
225pub struct SignChannel {
226    #[cfg_attr(
227        feature = "use-serde",
228        serde(
229            serialize_with = "crate::serde_utils::serialize_hex",
230            deserialize_with = "crate::serde_utils::deserialize_hex_array"
231        )
232    )]
233    /// The id of the channel referred to by the message.
234    pub channel_id: [u8; 32],
235    /// The adaptor signatures for all CETs generated by the offer party.
236    pub cet_adaptor_signatures: CetAdaptorSignatures,
237    /// The adaptor signature for the buffer transaction generated by the offer
238    /// party.
239    pub buffer_adaptor_signature: EcdsaAdaptorSignature,
240    /// The refund signature generated by the offer party.
241    pub refund_signature: Signature,
242    /// The signatures for the offer party's inputs.
243    pub funding_signatures: FundingSignatures,
244}
245
246impl_dlc_writeable!(SignChannel, SIGN_CHANNEL_TYPE, {
247    (channel_id, writeable),
248    (cet_adaptor_signatures, writeable),
249    (buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}),
250    (refund_signature, writeable),
251    (funding_signatures, writeable)
252});
253
254#[derive(Clone, Debug, PartialEq, Eq)]
255#[cfg_attr(
256    feature = "use-serde",
257    derive(serde::Serialize, serde::Deserialize),
258    serde(rename_all = "camelCase")
259)]
260/// Message used to offer a settlement of the channel by on of the parties.
261pub struct SettleOffer {
262    #[cfg_attr(
263        feature = "use-serde",
264        serde(
265            serialize_with = "crate::serde_utils::serialize_hex",
266            deserialize_with = "crate::serde_utils::deserialize_hex_array"
267        )
268    )]
269    /// The id of the channel referred to by the message.
270    pub channel_id: [u8; 32],
271    /// The payout offered to the receiving party.
272    pub counter_payout: Amount,
273    /// The per update point to be used by the sending party to setup the next
274    /// channel state.
275    pub next_per_update_point: PublicKey,
276}
277
278impl_dlc_writeable!(SettleOffer, SETTLE_CHANNEL_OFFER_TYPE, {
279    (channel_id, writeable),
280    (counter_payout, writeable),
281    (next_per_update_point, writeable)
282});
283
284#[derive(Clone, Debug, PartialEq, Eq)]
285#[cfg_attr(
286    feature = "use-serde",
287    derive(serde::Serialize, serde::Deserialize),
288    serde(rename_all = "camelCase")
289)]
290/// Message used to accept a previously received settlement offer.
291pub struct SettleAccept {
292    #[cfg_attr(
293        feature = "use-serde",
294        serde(
295            serialize_with = "crate::serde_utils::serialize_hex",
296            deserialize_with = "crate::serde_utils::deserialize_hex_array"
297        )
298    )]
299    /// The id of the channel referred to by the message.
300    pub channel_id: [u8; 32],
301    /// The per update point to be used by the sending party to setup the next
302    /// channel state.
303    pub next_per_update_point: PublicKey,
304    /// The adaptor signature for the settle transaction generated by the sending
305    /// party.
306    pub settle_adaptor_signature: EcdsaAdaptorSignature,
307}
308
309impl_dlc_writeable!(SettleAccept, SETTLE_CHANNEL_ACCEPT_TYPE, {
310    (channel_id, writeable),
311    (next_per_update_point, writeable),
312    (settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature})
313});
314
315#[derive(Clone, Debug, PartialEq, Eq)]
316#[cfg_attr(
317    feature = "use-serde",
318    derive(serde::Serialize, serde::Deserialize),
319    serde(rename_all = "camelCase")
320)]
321/// Message used to confirm the settlement of a channel.
322pub struct SettleConfirm {
323    #[cfg_attr(
324        feature = "use-serde",
325        serde(
326            serialize_with = "crate::serde_utils::serialize_hex",
327            deserialize_with = "crate::serde_utils::deserialize_hex_array"
328        )
329    )]
330    /// The id of the channel referred to by the message.
331    pub channel_id: [u8; 32],
332    /// The pre-image of the per update point used by the sending party during
333    /// the establishment of the previous channel state.
334    pub prev_per_update_secret: SecretKey,
335    /// The adaptor signature for the settlement transaction generated by the
336    /// sending party.
337    pub settle_adaptor_signature: EcdsaAdaptorSignature,
338}
339
340impl_dlc_writeable!(SettleConfirm, SETTLE_CHANNEL_CONFIRM_TYPE, {
341    (channel_id, writeable),
342    (prev_per_update_secret, writeable),
343    (settle_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature})
344});
345
346#[derive(Clone, Debug, PartialEq, Eq)]
347#[cfg_attr(
348    feature = "use-serde",
349    derive(serde::Serialize, serde::Deserialize),
350    serde(rename_all = "camelCase")
351)]
352/// Message used to finalize the settlement of a channel.
353pub struct SettleFinalize {
354    #[cfg_attr(
355        feature = "use-serde",
356        serde(
357            serialize_with = "crate::serde_utils::serialize_hex",
358            deserialize_with = "crate::serde_utils::deserialize_hex_array"
359        )
360    )]
361    /// The id of the channel referred to by the message.
362    pub channel_id: [u8; 32],
363    /// The pre-image of the per update point used by the sending party during
364    /// the establishment of the previous channel state.
365    pub prev_per_update_secret: SecretKey,
366}
367
368impl_dlc_writeable!(SettleFinalize, SETTLE_CHANNEL_FINALIZE_TYPE, {
369    (channel_id, writeable),
370    (prev_per_update_secret, writeable)
371});
372
373#[derive(Clone, Debug, PartialEq)]
374#[cfg_attr(
375    feature = "use-serde",
376    derive(serde::Serialize, serde::Deserialize),
377    serde(rename_all = "camelCase")
378)]
379/// Message used to offer to establish a new contract within the channel.
380pub struct RenewOffer {
381    #[cfg_attr(
382        feature = "use-serde",
383        serde(
384            serialize_with = "crate::serde_utils::serialize_hex",
385            deserialize_with = "crate::serde_utils::deserialize_hex_array"
386        )
387    )]
388    /// The id of the channel referred to by the message.
389    pub channel_id: [u8; 32],
390    /// The temporary id of the offered contract.
391    pub temporary_contract_id: [u8; 32],
392    /// The proposed payout for the receiving party for the previous channel
393    /// state.
394    pub counter_payout: Amount,
395    /// The per update point to be used by the sending party to setup the next
396    /// channel state.
397    pub next_per_update_point: PublicKey,
398    /// Information about the offered contract.
399    pub contract_info: ContractInfo,
400    /// Lock time for the CETs.
401    pub cet_locktime: u32,
402    /// Lock time for the refund transaction.
403    pub refund_locktime: u32,
404    /// The nSequence value to use for the CETs.
405    pub cet_nsequence: u32,
406}
407
408impl_dlc_writeable!(RenewOffer, RENEW_CHANNEL_OFFER_TYPE, {
409    (channel_id, writeable),
410    (temporary_contract_id, writeable),
411    (counter_payout, writeable),
412    (next_per_update_point, writeable),
413    (contract_info, writeable),
414    (cet_locktime, writeable),
415    (refund_locktime, writeable),
416    (cet_nsequence, writeable)
417});
418
419#[derive(Clone, Debug, PartialEq, Eq)]
420#[cfg_attr(
421    feature = "use-serde",
422    derive(serde::Serialize, serde::Deserialize),
423    serde(rename_all = "camelCase")
424)]
425/// Message used to accept the establishment of a new contract within a channel.
426pub struct RenewAccept {
427    #[cfg_attr(
428        feature = "use-serde",
429        serde(
430            serialize_with = "crate::serde_utils::serialize_hex",
431            deserialize_with = "crate::serde_utils::deserialize_hex_array"
432        )
433    )]
434    /// The id of the channel referred to by the message.
435    pub channel_id: [u8; 32],
436    /// The per update point to be used by the sending party to setup the next
437    /// channel state.
438    pub next_per_update_point: PublicKey,
439    /// The adaptor signatures for all CETs generated by the offer party.
440    pub cet_adaptor_signatures: CetAdaptorSignatures,
441    /// The refund signature generated by the offer party.
442    pub refund_signature: Signature,
443}
444
445impl_dlc_writeable!(RenewAccept, RENEW_CHANNEL_ACCEPT_TYPE, {
446    (channel_id, writeable),
447    (next_per_update_point, writeable),
448    (cet_adaptor_signatures, writeable),
449    (refund_signature, writeable)
450});
451
452#[derive(Clone, Debug, PartialEq, Eq)]
453#[cfg_attr(
454    feature = "use-serde",
455    derive(serde::Serialize, serde::Deserialize),
456    serde(rename_all = "camelCase")
457)]
458/// Message used to confirm the establishment of a new contract within a channel.
459pub struct RenewConfirm {
460    #[cfg_attr(
461        feature = "use-serde",
462        serde(
463            serialize_with = "crate::serde_utils::serialize_hex",
464            deserialize_with = "crate::serde_utils::deserialize_hex_array"
465        )
466    )]
467    /// The id of the channel referred to by the message.
468    pub channel_id: [u8; 32],
469    /// The adaptor signature for the buffer transaction generated by the offer
470    /// party.
471    pub buffer_adaptor_signature: EcdsaAdaptorSignature,
472    /// The adaptor signatures for all CETs generated by the offer party.
473    pub cet_adaptor_signatures: CetAdaptorSignatures,
474    /// The refund signature generated by the offer party.
475    pub refund_signature: Signature,
476}
477
478impl_dlc_writeable!(RenewConfirm, RENEW_CHANNEL_CONFIRM_TYPE, {
479    (channel_id, writeable),
480    (buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}),
481    (cet_adaptor_signatures, writeable),
482    (refund_signature, writeable)
483});
484
485#[derive(Clone, Debug, PartialEq, Eq)]
486#[cfg_attr(
487    feature = "use-serde",
488    derive(serde::Serialize, serde::Deserialize),
489    serde(rename_all = "camelCase")
490)]
491/// Message used to finalize the establishment of a new contract within a channel.
492pub struct RenewFinalize {
493    #[cfg_attr(
494        feature = "use-serde",
495        serde(
496            serialize_with = "crate::serde_utils::serialize_hex",
497            deserialize_with = "crate::serde_utils::deserialize_hex_array"
498        )
499    )]
500    /// The id of the channel referred to by the message.
501    pub channel_id: [u8; 32],
502    /// The pre image of the per update point used by the sending party to setup
503    /// the previous channel state.
504    pub per_update_secret: SecretKey,
505    /// The adaptor signature for the buffer transaction generated by the accept
506    /// party.
507    pub buffer_adaptor_signature: EcdsaAdaptorSignature,
508}
509
510impl_dlc_writeable!(RenewFinalize, RENEW_CHANNEL_FINALIZE_TYPE, {
511    (channel_id, writeable),
512    (per_update_secret, writeable),
513    (buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature})
514
515});
516
517#[derive(Clone, Debug, PartialEq, Eq)]
518#[cfg_attr(
519    feature = "serde",
520    derive(serde::Serialize, serde::Deserialize),
521    serde(rename_all = "camelCase")
522)]
523/// Message used to finalize the establishment of a new contract within a channel.
524pub struct RenewRevoke {
525    #[cfg_attr(
526        feature = "serde",
527        serde(
528            serialize_with = "crate::serde_utils::serialize_hex",
529            deserialize_with = "crate::serde_utils::deserialize_hex_array"
530        )
531    )]
532    /// The id of the channel referred to by the message.
533    pub channel_id: [u8; 32],
534    /// The pre image of the per update point used by the sending party to setup
535    /// the previous channel state.
536    pub per_update_secret: SecretKey,
537}
538
539impl_dlc_writeable!(RenewRevoke, RENEW_CHANNEL_REVOKE_TYPE, {
540    (channel_id, writeable),
541    (per_update_secret, writeable)
542});
543
544#[derive(Clone, Debug, PartialEq, Eq)]
545#[cfg_attr(
546    feature = "use-serde",
547    derive(serde::Serialize, serde::Deserialize),
548    serde(rename_all = "camelCase")
549)]
550/// Message used to offer to collaboratively close a channel.
551pub struct CollaborativeCloseOffer {
552    #[cfg_attr(
553        feature = "use-serde",
554        serde(
555            serialize_with = "crate::serde_utils::serialize_hex",
556            deserialize_with = "crate::serde_utils::deserialize_hex_array"
557        )
558    )]
559    /// The id of the channel referred to by the message.
560    pub channel_id: [u8; 32],
561    /// The proposed payout for the receiving party to close the channel with.
562    pub counter_payout: Amount,
563    /// The signature of the sending party for the closing transaction.
564    pub close_signature: Signature,
565}
566
567impl_dlc_writeable!(CollaborativeCloseOffer, COLLABORATIVE_CLOSE_OFFER_TYPE, {
568    (channel_id, writeable),
569    (counter_payout, writeable),
570    (close_signature, writeable)
571});
572
573#[derive(Clone, Debug, PartialEq, Eq)]
574#[cfg_attr(
575    feature = "use-serde",
576    derive(serde::Serialize, serde::Deserialize),
577    serde(rename_all = "camelCase")
578)]
579/// Message used to reject an received offer.
580pub struct Reject {
581    #[cfg_attr(
582        feature = "use-serde",
583        serde(
584            serialize_with = "crate::serde_utils::serialize_hex",
585            deserialize_with = "crate::serde_utils::deserialize_hex_array"
586        )
587    )]
588    /// The id of the channel referred to by the message.
589    pub channel_id: [u8; 32],
590}
591
592impl_dlc_writeable!(Reject, REJECT, { (channel_id, writeable) });