lightning_signer/util/
debug_utils.rs

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