ddk_messages/
types.rs

1//! Type definitions and constants for DLC messages
2
3use lightning::ln::wire::Type;
4
5// Define all type constants and implement Type trait using macro
6macro_rules! impl_type {
7    ($const_name: ident, $type_name: ident, $type_val: expr) => {
8        /// The type prefix for a message.
9        pub const $const_name: u16 = $type_val;
10
11        impl Type for $type_name {
12            fn type_id(&self) -> u16 {
13                $const_name
14            }
15        }
16    };
17}
18
19// Re-export the types that will get impl_type
20pub use crate::{AcceptDlc, CloseDlc, OfferDlc, SignDlc};
21
22pub use crate::channel::{
23    AcceptChannel, CollaborativeCloseOffer, OfferChannel, Reject, RenewAccept, RenewConfirm,
24    RenewFinalize, RenewOffer, RenewRevoke, SettleAccept, SettleConfirm, SettleFinalize,
25    SettleOffer, SignChannel,
26};
27
28// DLC message types
29impl_type!(OFFER_TYPE, OfferDlc, 42778);
30impl_type!(ACCEPT_TYPE, AcceptDlc, 42780);
31impl_type!(SIGN_TYPE, SignDlc, 42782);
32impl_type!(CLOSE_TYPE, CloseDlc, 42784);
33
34// Channel message types
35impl_type!(OFFER_CHANNEL_TYPE, OfferChannel, 43000);
36impl_type!(ACCEPT_CHANNEL_TYPE, AcceptChannel, 43002);
37impl_type!(SIGN_CHANNEL_TYPE, SignChannel, 43004);
38impl_type!(SETTLE_CHANNEL_OFFER_TYPE, SettleOffer, 43006);
39impl_type!(SETTLE_CHANNEL_ACCEPT_TYPE, SettleAccept, 43008);
40impl_type!(SETTLE_CHANNEL_CONFIRM_TYPE, SettleConfirm, 43010);
41impl_type!(SETTLE_CHANNEL_FINALIZE_TYPE, SettleFinalize, 43012);
42impl_type!(RENEW_CHANNEL_OFFER_TYPE, RenewOffer, 43014);
43impl_type!(RENEW_CHANNEL_ACCEPT_TYPE, RenewAccept, 43016);
44impl_type!(RENEW_CHANNEL_CONFIRM_TYPE, RenewConfirm, 43018);
45impl_type!(RENEW_CHANNEL_FINALIZE_TYPE, RenewFinalize, 43020);
46impl_type!(RENEW_CHANNEL_REVOKE_TYPE, RenewRevoke, 43026);
47impl_type!(
48    COLLABORATIVE_CLOSE_OFFER_TYPE,
49    CollaborativeCloseOffer,
50    43022
51);
52impl_type!(REJECT, Reject, 43024);
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use crate::contract_msgs::{
58        ContractDescriptor, ContractInfo, ContractInfoInner, EnumeratedContractDescriptor,
59    };
60    use crate::oracle_msgs::{OracleEvent, OracleInfo};
61    use crate::OfferDlc;
62    use bitcoin::Amount;
63    use bitcoin::ScriptBuf;
64    use lightning::util::ser::{Readable, Writeable};
65    use secp256k1_zkp::{rand, SECP256K1};
66
67    fn xonly_pubkey() -> secp256k1_zkp::XOnlyPublicKey {
68        secp256k1_zkp::Keypair::new(SECP256K1, &mut rand::thread_rng())
69            .x_only_public_key()
70            .0
71    }
72
73    fn pubkey() -> secp256k1_zkp::PublicKey {
74        secp256k1_zkp::Keypair::new(SECP256K1, &mut rand::thread_rng()).public_key()
75    }
76
77    #[test]
78    fn test_type_id_serialization() {
79        // Create a minimal OfferDlc for testing
80        let offer = OfferDlc {
81            protocol_version: 1,
82            contract_flags: 0,
83            chain_hash: [0u8; 32],
84            temporary_contract_id: [1u8; 32],
85            contract_info: ContractInfo::SingleContractInfo(
86                crate::contract_msgs::SingleContractInfo {
87                    total_collateral: Amount::from_sat(100000),
88                    contract_info: ContractInfoInner {
89                        contract_descriptor: ContractDescriptor::EnumeratedContractDescriptor(
90                            EnumeratedContractDescriptor { payouts: vec![] },
91                        ),
92                        oracle_info: OracleInfo::Single(crate::oracle_msgs::SingleOracleInfo {
93                            oracle_announcement: crate::oracle_msgs::OracleAnnouncement {
94                                announcement_signature:
95                                    secp256k1_zkp::schnorr::Signature::from_slice(&[0u8; 64])
96                                        .unwrap(),
97                                oracle_public_key: xonly_pubkey(),
98                                oracle_event: OracleEvent {
99                                    oracle_nonces: vec![xonly_pubkey()],
100                                    event_maturity_epoch: 1,
101                                    event_id: "oracle".to_string(),
102                                    event_descriptor:
103                                        crate::oracle_msgs::EventDescriptor::EnumEvent(
104                                            crate::oracle_msgs::EnumEventDescriptor {
105                                                outcomes: vec!["1".to_string(), "2".to_string()],
106                                            },
107                                        ),
108                                },
109                            },
110                        }),
111                    },
112                },
113            ),
114            funding_pubkey: pubkey(),
115            payout_spk: ScriptBuf::new(),
116            payout_serial_id: 0,
117            offer_collateral: Amount::from_sat(50000),
118            funding_inputs: vec![],
119            change_spk: ScriptBuf::new(),
120            change_serial_id: 1,
121            fund_output_serial_id: 2,
122            fee_rate_per_vb: 1,
123            cet_locktime: 100,
124            refund_locktime: 200,
125        };
126
127        // Serialize the offer
128        let mut serialized = Vec::new();
129        offer.write(&mut serialized).unwrap();
130
131        // Check that the first 2 bytes are the type_id
132        assert_eq!(&serialized[0..2], &OFFER_TYPE.to_be_bytes());
133
134        // Deserialize and check we get the same offer back
135        let deserialized = OfferDlc::read(&mut &serialized[..]).unwrap();
136        assert_eq!(offer.protocol_version, deserialized.protocol_version);
137        assert_eq!(
138            offer.temporary_contract_id,
139            deserialized.temporary_contract_id
140        );
141    }
142
143    #[test]
144    fn test_wrong_type_id_fails() {
145        // Create a buffer with wrong type_id
146        let mut bad_data = Vec::new();
147        bad_data.extend_from_slice(&9999u16.to_be_bytes()); // Wrong type_id
148        bad_data.extend_from_slice(&[0u8; 100]); // Some dummy data
149
150        // Should fail to deserialize
151        let result = OfferDlc::read(&mut &bad_data[..]);
152        assert!(result.is_err());
153    }
154}