vls_protocol/
model.rs

1use alloc::format;
2use bitcoin::consensus::{Decodable, Encodable};
3use bitcoin::Txid;
4use bitcoin_consensus_derive::{Decodable, Encodable};
5use core::fmt::{self, Debug, Formatter};
6use lightning_signer::lightning;
7use lightning_signer::lightning::io::{self, Read, Write};
8use lightning_signer::lightning::ln::channel_keys::{
9    DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint,
10};
11use lightning_signer::lightning::ln::msgs::DecodeError;
12use lightning_signer::lightning::util::ser::{Readable, Writeable, Writer};
13use serde_bolt::bitcoin;
14use serde_bolt::bitcoin::consensus::encode::Error as BitcoinError;
15use serde_bolt::Octets;
16use txoo::bitcoin::secp256k1::PublicKey;
17
18macro_rules! secret_array_impl {
19    ($ty:ident, $len:tt) => {
20        #[derive(Clone, Encodable, Decodable)]
21        pub struct $ty(pub [u8; $len]);
22
23        impl Debug for $ty {
24            #[cfg(feature = "log-secrets")]
25            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
26                write!(f, "{}", hex::encode(&self.0))
27            }
28            #[cfg(not(feature = "log-secrets"))]
29            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
30                write!(f, "******")
31            }
32        }
33    };
34}
35
36macro_rules! array_impl {
37    ($ty:ident, $len:tt) => {
38        #[derive(Clone, Encodable, Decodable)]
39        #[cfg_attr(test, derive(PartialEq))]
40        pub struct $ty(pub [u8; $len]);
41
42        impl Debug for $ty {
43            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
44                write!(f, "{}", hex::encode(&self.0))
45            }
46        }
47
48        impl Readable for $ty {
49            fn read<R: Read>(reader: &mut R) -> Result<Self, lightning::ln::msgs::DecodeError> {
50                Ok($ty::consensus_decode(reader)
51                    .map_err(|_| lightning::ln::msgs::DecodeError::InvalidValue)?)
52            }
53        }
54
55        impl Writeable for $ty {
56            fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
57                self.consensus_encode(&mut LdkWriterWriteAdaptor(writer)).map_err(|_e| {
58                    io::Error::new(io::ErrorKind::Other, "Error during consensus encoding")
59                })?;
60                Ok(())
61            }
62        }
63    };
64}
65
66/// A wrapper that allows consensus_encode to use Writer.
67// cribbed from rust-lightning/lightning/src/util/ser.rs
68pub struct LdkWriterWriteAdaptor<'a, W: Writer + 'a>(pub &'a mut W);
69impl<'a, W: Writer + 'a> Write for LdkWriterWriteAdaptor<'a, W> {
70    #[inline]
71    fn write_all(&mut self, buf: &[u8]) -> Result<(), io::Error> {
72        self.0.write_all(buf)
73    }
74    #[inline]
75    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
76        self.0.write_all(buf)?;
77        Ok(buf.len())
78    }
79    #[inline]
80    fn flush(&mut self) -> Result<(), io::Error> {
81        Ok(())
82    }
83}
84
85/// Another wrapper
86pub struct SerBoltTlvWriteWrap<T: Encodable>(pub T);
87
88impl<T: Encodable> Writeable for SerBoltTlvWriteWrap<T> {
89    fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
90        self.0.consensus_encode(&mut LdkWriterWriteAdaptor(writer)).map_err(|_e| {
91            io::Error::new(io::ErrorKind::Other, "Error during consensus encoding")
92        })?;
93        Ok(())
94    }
95}
96
97impl<T: Encodable> From<T> for SerBoltTlvWriteWrap<T> {
98    fn from(t: T) -> Self {
99        SerBoltTlvWriteWrap(t)
100    }
101}
102
103pub struct SerBoltTlvReadWrap<T: Decodable>(pub T);
104
105impl<T: Decodable> Decodable for SerBoltTlvReadWrap<T> {
106    fn consensus_decode<D: Read + ?Sized>(d: &mut D) -> Result<Self, BitcoinError> {
107        T::consensus_decode(d).map(|t| SerBoltTlvReadWrap(t))
108    }
109}
110
111impl<T: Decodable> Readable for SerBoltTlvReadWrap<T> {
112    fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
113        Ok(SerBoltTlvReadWrap::<T>::consensus_decode(reader)
114            .map_err(|_| lightning::ln::msgs::DecodeError::InvalidValue)?)
115    }
116}
117
118#[derive(Encodable, Decodable)]
119pub struct Bip32KeyVersion {
120    pub pubkey_version: u32,
121    pub privkey_version: u32,
122}
123
124impl Debug for Bip32KeyVersion {
125    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
126        f.debug_struct("Bip32KeyVersion")
127            .field("pubkey_version", &format!("0x{:x?}", self.pubkey_version))
128            .field("privkey_version", &format!("0x{:x?}", self.privkey_version))
129            .finish()
130    }
131}
132
133// A 32-byte secret that is sensitive
134secret_array_impl!(Secret, 32);
135
136// A 32-byte secret that is no longer sensitive, because it is known or will
137// soon be known to our counterparty
138array_impl!(DisclosedSecret, 32);
139
140// A 32-byte secret that is not sensitive, because it is used for testing / development
141array_impl!(DevSecret, 32);
142
143// A 32-byte secret that is not sensitive, because it is used for testing / development
144array_impl!(DevPrivKey, 32);
145
146array_impl!(PubKey32, 32);
147
148array_impl!(PubKey, 33);
149
150array_impl!(ExtKey, 78);
151
152array_impl!(Sha256, 32);
153
154#[derive(Debug, Encodable, Decodable)]
155pub struct Basepoints {
156    pub revocation: PubKey,
157    pub payment: PubKey,
158    pub htlc: PubKey,
159    pub delayed_payment: PubKey,
160}
161
162impl Into<RevocationBasepoint> for PubKey {
163    fn into(self) -> RevocationBasepoint {
164        RevocationBasepoint(self.into())
165    }
166}
167
168impl Into<HtlcBasepoint> for PubKey {
169    fn into(self) -> HtlcBasepoint {
170        HtlcBasepoint(self.into())
171    }
172}
173
174impl Into<DelayedPaymentBasepoint> for PubKey {
175    fn into(self) -> DelayedPaymentBasepoint {
176        DelayedPaymentBasepoint(self.into())
177    }
178}
179
180impl Into<PublicKey> for PubKey {
181    fn into(self) -> PublicKey {
182        PublicKey::from_slice(&self.0).expect("PublicKey::from_slice")
183    }
184}
185
186array_impl!(Signature, 64);
187array_impl!(RecoverableSignature, 65);
188
189array_impl!(OnionRoutingPacket, 1366);
190
191#[derive(Debug, Encodable, Decodable)]
192pub struct FailedHtlc {
193    pub id: u64,
194}
195
196#[derive(Debug, Encodable, Decodable)]
197pub struct BitcoinSignature {
198    pub signature: Signature,
199    pub sighash: u8,
200}
201
202#[derive(Debug, Encodable, Decodable)]
203pub struct Htlc {
204    pub side: u8, // 0 = local, 1 = remote
205    pub amount: u64,
206    pub payment_hash: Sha256,
207    pub ctlv_expiry: u32,
208}
209
210impl Htlc {
211    pub const LOCAL: u8 = 0;
212    pub const REMOTE: u8 = 1;
213}
214
215#[derive(Debug, Encodable, Decodable)]
216pub struct CloseInfo {
217    pub channel_id: u64,
218    pub peer_id: PubKey,
219    pub commitment_point: Option<PubKey>,
220    // TODO this is unused
221    pub is_anchors: bool,
222    pub csv: u32,
223}
224
225#[derive(Debug, Encodable, Decodable)]
226pub struct Utxo {
227    pub txid: Txid,
228    pub outnum: u32,
229    pub amount: u64,
230    pub keyindex: u32,
231    pub is_p2sh: bool,
232    pub script: Octets,
233    pub close_info: Option<CloseInfo>,
234    pub is_in_coinbase: bool,
235}
236
237#[cfg(test)]
238mod tests {
239    #[test]
240    fn debug_secret_test() {
241        let secret = super::Secret([0; 32]);
242        let debug = format!("{:?}", secret);
243        #[cfg(feature = "log-secrets")]
244        assert_eq!(debug, "0000000000000000000000000000000000000000000000000000000000000000");
245        #[cfg(not(feature = "log-secrets"))]
246        assert_eq!(debug, "******");
247    }
248}