lightning_signer/util/
debug_utils.rs

1use crate::node::{PaymentState, RoutedPayment};
2use crate::prelude::*;
3use bitcoin::address::Payload;
4use bitcoin::secp256k1::SecretKey;
5use bitcoin::{Address, Network, ScriptBuf};
6use lightning::ln::chan_utils::{
7    BuiltCommitmentTransaction, ChannelPublicKeys, CommitmentTransaction, HTLCOutputInCommitment,
8    TxCreationKeys,
9};
10use lightning::ln::PaymentHash;
11use lightning::sign::InMemorySigner;
12use vls_common::HexEncode;
13
14/// Debug printer for ChannelPublicKeys which doesn't have one.
15pub struct DebugChannelPublicKeys<'a>(pub &'a ChannelPublicKeys);
16impl<'a> core::fmt::Debug for DebugChannelPublicKeys<'a> {
17    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
18        f.debug_struct("ChannelPublicKeys")
19            .field("funding_pubkey", &self.0.funding_pubkey)
20            .field("revocation_basepoint", &self.0.revocation_basepoint)
21            .field("payment_point", &self.0.payment_point)
22            .field("delayed_payment_basepoint", &self.0.delayed_payment_basepoint)
23            .field("htlc_basepoint", &self.0.htlc_basepoint)
24            .finish()
25    }
26}
27
28macro_rules! log_channel_public_keys {
29    ($obj: expr) => {
30        &crate::util::debug_utils::DebugChannelPublicKeys(&$obj)
31    };
32}
33
34/// log the enforcement state
35#[doc(hidden)]
36#[macro_export]
37macro_rules! trace_enforcement_state {
38    ($chan: expr) => {
39        #[cfg(not(feature = "debug_enforcement_state"))]
40        {
41            #[cfg(not(feature = "log_pretty_print"))]
42            trace!("{}:{:?}{:?}", function!(), &$chan.enforcement_state, &$chan.get_chain_state());
43            #[cfg(feature = "log_pretty_print")]
44            trace!(
45                "{}:\n{:#?}\n{:#?}",
46                function!(),
47                &$chan.enforcement_state,
48                &$chan.get_chain_state()
49            );
50        }
51        #[cfg(feature = "debug_enforcement_state")]
52        {
53            #[cfg(not(feature = "log_pretty_print"))]
54            debug!("{}:{:?}{:?}", function!(), &$chan.enforcement_state, &$chan.get_chain_state());
55            #[cfg(feature = "log_pretty_print")]
56            debug!(
57                "{}:\n{:#?}\n{:#?}",
58                function!(),
59                &$chan.enforcement_state,
60                &$chan.get_chain_state()
61            );
62        }
63    };
64}
65
66/// log the node state
67#[doc(hidden)]
68#[macro_export]
69macro_rules! trace_node_state {
70    ($nodestate: expr) => {
71        #[cfg(not(feature = "debug_node_state"))]
72        {
73            #[cfg(not(feature = "log_pretty_print"))]
74            trace!("{}:{:?}", function!(), &$nodestate);
75            #[cfg(feature = "log_pretty_print")]
76            trace!("{}:\n{#:?}", function!(), &$nodestate);
77        }
78        #[cfg(feature = "debug_node_state")]
79        {
80            #[cfg(not(feature = "log_pretty_print"))]
81            debug!("{}:{:?}", function!(), &$nodestate);
82            #[cfg(feature = "log_pretty_print")]
83            debug!("{}:\n{:#?}", function!(), &$nodestate);
84        }
85        // log the summary if it changed
86        let (summary, changed) = &$nodestate.summary();
87        if *changed {
88            info!("{}: {}", function!(), summary);
89        }
90    };
91}
92
93/// Debug printer for Payload which uses hex encoded strings.
94pub struct DebugPayload<'a>(pub &'a Payload);
95impl<'a> core::fmt::Debug for DebugPayload<'a> {
96    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
97        match *self.0 {
98            Payload::PubkeyHash(ref hash) =>
99                f.debug_struct("PubkeyHash").field("hash", &hex::encode(hash)).finish(),
100            Payload::ScriptHash(ref hash) =>
101                f.debug_struct("ScriptHash").field("hash", &hex::encode(hash)).finish(),
102            Payload::WitnessProgram(ref program) => f
103                .debug_struct("WitnessProgram")
104                .field("version", &program.version())
105                .field("program", &program.program().to_hex())
106                .finish(),
107            _ => unreachable!(),
108        }
109    }
110}
111
112/// Debug printer for HTLCOutputInCommitment which doesn't have one.
113pub struct DebugHTLCOutputInCommitment<'a>(pub &'a HTLCOutputInCommitment);
114impl<'a> core::fmt::Debug for DebugHTLCOutputInCommitment<'a> {
115    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
116        f.debug_struct("HTLCOutputInCommitment")
117            .field("offered", &self.0.offered)
118            .field("amount_msat", &self.0.amount_msat)
119            .field("cltv_expiry", &self.0.cltv_expiry)
120            .field("payment_hash", &self.0.payment_hash.0.to_hex())
121            .field("transaction_output_index", &self.0.transaction_output_index)
122            .finish()
123    }
124}
125
126/// Debug support for Vec<HTLCOutputInCommitment>
127pub struct DebugVecHTLCOutputInCommitment<'a>(pub &'a Vec<HTLCOutputInCommitment>);
128impl<'a> core::fmt::Debug for DebugVecHTLCOutputInCommitment<'a> {
129    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
130        f.debug_list().entries(self.0.iter().map(|vv| DebugHTLCOutputInCommitment(&vv))).finish()
131    }
132}
133
134/// Debug printer for TxCreationKeys which doesn't have one.
135pub struct DebugTxCreationKeys<'a>(pub &'a TxCreationKeys);
136impl<'a> core::fmt::Debug for DebugTxCreationKeys<'a> {
137    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
138        f.debug_struct("TxCreationKeys")
139            .field("per_commitment_point", &self.0.per_commitment_point)
140            .field("revocation_key", &self.0.revocation_key)
141            .field("broadcaster_htlc_key", &self.0.broadcaster_htlc_key)
142            .field("countersignatory_htlc_key", &self.0.countersignatory_htlc_key)
143            .field("broadcaster_delayed_payment_key", &self.0.broadcaster_delayed_payment_key)
144            .finish()
145    }
146}
147
148/// Debug printer for InMemorySigner which doesn't have one.
149pub struct DebugInMemorySigner<'a>(pub &'a InMemorySigner);
150impl<'a> core::fmt::Debug for DebugInMemorySigner<'a> {
151    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
152        f.debug_struct("InMemorySigner")
153            .field("funding_key", &self.0.funding_key)
154            .field("revocation_base_key", &self.0.revocation_base_key)
155            .field("payment_key", &self.0.payment_key)
156            .field("delayed_payment_base_key", &self.0.delayed_payment_base_key)
157            .field("htlc_base_key", &self.0.htlc_base_key)
158            .field("commitment_seed", &DebugBytes(&self.0.commitment_seed))
159            .finish()
160    }
161}
162
163/// Debug printer for BuiltCommitmentTransaction which doesn't have one.
164pub struct DebugBuiltCommitmentTransaction<'a>(pub &'a BuiltCommitmentTransaction);
165impl<'a> core::fmt::Debug for DebugBuiltCommitmentTransaction<'a> {
166    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
167        f.debug_struct("BuiltCommitmentTransaction")
168            .field("transaction", &self.0.transaction)
169            .field("txid", &self.0.txid)
170            .finish()
171    }
172}
173
174/// Debug printer for CommitmentTransaction which doesn't have one.
175pub struct DebugCommitmentTransaction<'a>(pub &'a CommitmentTransaction);
176impl<'a> core::fmt::Debug for DebugCommitmentTransaction<'a> {
177    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
178        f.debug_struct("CommitmentTransaction")
179            .field("commitment_number", &self.0.commitment_number())
180            .field("to_broadcaster_value_sat", &self.0.to_broadcaster_value_sat())
181            .field("to_countersignatory_value_sat", &self.0.to_countersignatory_value_sat())
182            .field("feerate_per_kw", &self.0.feerate_per_kw())
183            .field("htlcs", &DebugVecHTLCOutputInCommitment(&self.0.htlcs()))
184            .field("keys", &DebugTxCreationKeys(&self.0.trust().keys()))
185            .field("built", &DebugBuiltCommitmentTransaction(&self.0.trust().built_transaction()))
186            .finish()
187    }
188}
189
190/// Debug support for bytes
191#[derive(Clone)]
192pub struct DebugBytes<'a>(pub &'a [u8]);
193impl<'a> core::fmt::Debug for DebugBytes<'a> {
194    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
195        for i in self.0 {
196            write!(f, "{:02x}", i)?;
197        }
198        Ok(())
199    }
200}
201
202/// Debug support for Vec<Vec<u8>>
203pub struct DebugVecVecU8<'a>(pub &'a [Vec<u8>]);
204impl<'a> core::fmt::Debug for DebugVecVecU8<'a> {
205    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
206        f.debug_list().entries(self.0.iter().map(|vv| DebugBytes(&vv[..]))).finish()
207    }
208}
209
210/// Debug support for a two element witness stack
211pub struct DebugWitness<'a>(pub &'a (Vec<u8>, Vec<u8>));
212impl<'a> core::fmt::Debug for DebugWitness<'a> {
213    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
214        f.debug_tuple("Witness")
215            .field(&DebugBytes(&self.0 .0))
216            .field(&DebugBytes(&self.0 .1))
217            .finish()
218    }
219}
220
221/// Debug support for a collection of two-element witness stacks
222pub struct DebugWitVec<'a>(pub &'a Vec<(Vec<u8>, Vec<u8>)>);
223impl<'a> core::fmt::Debug for DebugWitVec<'a> {
224    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
225        f.debug_list().entries(self.0.iter().map(|ww| DebugWitness(ww))).finish()
226    }
227}
228
229/// Debug support for a unilateral close key
230pub struct DebugUnilateralCloseKey<'a>(pub &'a (SecretKey, Vec<Vec<u8>>));
231impl<'a> core::fmt::Debug for DebugUnilateralCloseKey<'a> {
232    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
233        f.debug_tuple("UnilateralCloseKey")
234            .field(&self.0 .0)
235            .field(&DebugVecVecU8(&self.0 .1))
236            .finish()
237    }
238}
239
240/// Debug support for unilateral close info
241pub struct DebugUnilateralCloseInfo<'a>(pub &'a Vec<Option<(SecretKey, Vec<Vec<u8>>)>>);
242impl<'a> core::fmt::Debug for DebugUnilateralCloseInfo<'a> {
243    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
244        f.debug_list()
245            .entries(self.0.iter().map(|o| o.as_ref().map(|vv| DebugUnilateralCloseKey(&vv))))
246            .finish()
247    }
248}
249
250/// Debug support for Map<PaymentHash, PaymentState>
251pub struct DebugMapPaymentState<'a>(pub &'a Map<PaymentHash, PaymentState>);
252impl<'a> core::fmt::Debug for DebugMapPaymentState<'a> {
253    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
254        f.debug_map().entries(self.0.iter().map(|(k, v)| (DebugBytes(&k.0), v))).finish()
255    }
256}
257
258/// Debug support for Map<PaymentHash, RoutedPayment>
259pub struct DebugMapRoutedPayment<'a>(pub &'a Map<PaymentHash, RoutedPayment>);
260impl<'a> core::fmt::Debug for DebugMapRoutedPayment<'a> {
261    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
262        f.debug_map().entries(self.0.iter().map(|(k, v)| (DebugBytes(&k.0), v))).finish()
263    }
264}
265
266/// Debug support for Map<PaymentHash, u64>
267pub struct DebugMapPaymentSummary<'a>(pub &'a Map<PaymentHash, u64>);
268impl<'a> core::fmt::Debug for DebugMapPaymentSummary<'a> {
269    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
270        f.debug_map().entries(self.0.iter().map(|(k, v)| (DebugBytes(&k.0), v))).finish()
271    }
272}
273
274/// Return a debug string for a bitcoin::Script
275pub fn script_debug(script: &ScriptBuf, network: Network) -> String {
276    format!(
277        "script={} {}={}",
278        script.to_hex(),
279        network,
280        match Address::from_script(script, network) {
281            Ok(addr) => addr.to_string(),
282            Err(_) => "<bad-address>".to_string(),
283        },
284    )
285}
286
287/// Return a scopeguard which debugs args on return unless disabled.
288#[doc(hidden)]
289#[macro_export]
290macro_rules! scoped_debug_return {
291    ( $($arg:tt)* ) => {{
292        let should_debug = true;
293        scopeguard::guard(should_debug, |should_debug| {
294            if should_debug {
295                if log::log_enabled!(log::Level::Debug) {
296                    debug!("{} failed:", containing_function!());
297                    dbgvals!($($arg)*);
298                }
299            }
300        })
301    }};
302}
303
304#[doc(hidden)]
305#[macro_export]
306#[cfg(not(feature = "log_pretty_print"))]
307macro_rules! dbgvals {
308    ($($val:expr),* $(,)?) => {
309        $(debug!("{:?}: {:?}", stringify!($val), $val);)*
310    }
311}
312
313#[doc(hidden)]
314#[macro_export]
315#[cfg(feature = "log_pretty_print")]
316macro_rules! dbgvals {
317    ($($val:expr),* $(,)?) => {
318        $(debug!("{:?}: {:#?}", stringify!($val), $val);)*
319    }
320}