Expose send_payment_for_bolt12_invoice
[rust-lightning] / fuzz / src / full_stack.rs
index 89212e5837073342a4a7f569411b07badc5fe247..10328cdce812d2992f8d53f18c1102bea7cde444 100644 (file)
 //! or payments to send/ways to handle events generated.
 //! This test has been very useful, though due to its complexity good starting inputs are critical.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::blockdata::transaction::{Transaction, TxOut};
 use bitcoin::blockdata::script::{Builder, ScriptBuf};
 use bitcoin::blockdata::opcodes;
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::consensus::encode::deserialize;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
+use bitcoin::transaction::Version;
 
+use bitcoin::WPubkeyHash;
 use bitcoin::hashes::hex::FromHex;
 use bitcoin::hashes::Hash as _;
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::sha256d::Hash as Sha256dHash;
-use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
+use bitcoin::hash_types::{Txid, BlockHash};
 
 use lightning::blinded_path::BlindedPath;
 use lightning::blinded_path::payment::ReceiveTlvs;
@@ -37,7 +40,8 @@ use lightning::chain::transaction::OutPoint;
 use lightning::sign::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
 use lightning::events::Event;
 use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
-use lightning::ln::channelmanager::{ChainParameters, ChannelDetails, ChannelManager, PaymentId, RecipientOnionFields, Retry, InterceptId};
+use lightning::ln::channel_state::ChannelDetails;
+use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentId, RecipientOnionFields, Retry, InterceptId};
 use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,IgnoringMessageHandler};
 use lightning::ln::msgs::{self, DecodeError};
 use lightning::ln::script::ShutdownScript;
@@ -67,8 +71,8 @@ use std::cell::RefCell;
 use std::convert::TryInto;
 use std::cmp;
 use std::sync::{Arc, Mutex};
-use std::sync::atomic::{AtomicU64,AtomicUsize,Ordering};
-use bitcoin::bech32::u5;
+use std::sync::atomic::{AtomicU64,AtomicUsize,AtomicBool,Ordering};
+use bech32::u5;
 
 #[inline]
 pub fn slice_to_be16(v: &[u8]) -> u16 {
@@ -94,6 +98,7 @@ pub fn slice_to_be24(v: &[u8]) -> u32 {
 struct InputData {
        data: Vec<u8>,
        read_pos: AtomicUsize,
+       halt_fee_est_reads: AtomicBool,
 }
 impl InputData {
        fn get_slice(&self, len: usize) -> Option<&[u8]> {
@@ -120,6 +125,9 @@ struct FuzzEstimator {
 }
 impl FeeEstimator for FuzzEstimator {
        fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u32 {
+               if self.input.halt_fee_est_reads.load(Ordering::Acquire) {
+                       return 253;
+               }
                //TODO: We should actually be testing at least much more than 64k...
                match self.input.get_slice(2) {
                        Some(slice) => cmp::max(slice_to_be16(slice) as u32, 253),
@@ -216,6 +224,7 @@ struct MoneyLossDetector<'a> {
        height: usize,
        max_height: usize,
        blocks_connected: u32,
+       error_message: String,
 }
 impl<'a> MoneyLossDetector<'a> {
        pub fn new(peers: &'a RefCell<[bool; 256]>,
@@ -234,6 +243,7 @@ impl<'a> MoneyLossDetector<'a> {
                        height: 0,
                        max_height: 0,
                        blocks_connected: 0,
+                       error_message: "Channel force-closed".to_string(),
                }
        }
 
@@ -288,7 +298,7 @@ impl<'a> Drop for MoneyLossDetector<'a> {
                        }
 
                        // Force all channels onto the chain (and time out claim txn)
-                       self.manager.force_close_all_channels_broadcasting_latest_txn();
+                       self.manager.force_close_all_channels_broadcasting_latest_txn(self.error_message.to_string());
                }
        }
 }
@@ -349,7 +359,7 @@ impl NodeSigner for KeyProvider {
        }
 
        fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
-               let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
+               let msg_hash = Message::from_digest(Sha256dHash::hash(&msg.encode()[..]).to_byte_array());
                let secp_ctx = Secp256k1::signing_only();
                Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret))
        }
@@ -440,6 +450,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
        let input = Arc::new(InputData {
                data: data.to_vec(),
                read_pos: AtomicUsize::new(0),
+               halt_fee_est_reads: AtomicBool::new(false),
        });
        let fee_est = Arc::new(FuzzEstimator {
                input: input.clone(),
@@ -650,11 +661,11 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                                }
                        },
                        10 => {
-                               let mut tx = Transaction { version: 0, lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
+                               let mut tx = Transaction { version: Version(0), lock_time: LockTime::ZERO, input: Vec::new(), output: Vec::new() };
                                let mut channels = Vec::new();
                                for funding_generation in pending_funding_generation.drain(..) {
                                        let txout = TxOut {
-                                               value: funding_generation.2, script_pubkey: funding_generation.3,
+                                               value: Amount::from_sat(funding_generation.2), script_pubkey: funding_generation.3,
                                        };
                                        if !tx.output.contains(&txout) {
                                                tx.output.push(txout);
@@ -664,7 +675,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                                // Once we switch to V2 channel opens we should be able to drop this entirely as
                                // channel_ids no longer change when we set the funding tx.
                                'search_loop: loop {
-                                       if tx.version > 0xff {
+                                       if tx.version.0 > 0xff {
                                                break;
                                        }
                                        let funding_txid = tx.txid();
@@ -672,15 +683,15 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                                                let outpoint = OutPoint { txid: funding_txid, index: 0 };
                                                for chan in channelmanager.list_channels() {
                                                        if chan.channel_id == ChannelId::v1_from_funding_outpoint(outpoint) {
-                                                               tx.version += 1;
+                                                               tx.version = Version(tx.version.0 + 1);
                                                                continue 'search_loop;
                                                        }
                                                }
                                                break;
                                        }
-                                       tx.version += 1;
+                                       tx.version = Version(tx.version.0 + 1);
                                }
-                               if tx.version <= 0xff && !channels.is_empty() {
+                               if tx.version.0 <= 0xff && !channels.is_empty() {
                                        let chans = channels.iter().map(|(a, b)| (a, b)).collect::<Vec<_>>();
                                        if let Err(e) = channelmanager.batch_funding_transaction_generated(&chans, tx.clone()) {
                                                // It's possible the channel has been closed in the mean time, but any other
@@ -697,10 +708,12 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                        11 => {
                                let mut txn = broadcast.txn_broadcasted.lock().unwrap().split_off(0);
                                if !txn.is_empty() {
+                                       input.halt_fee_est_reads.store(true, Ordering::Release);
                                        loss_detector.connect_block(&txn[..]);
                                        for _ in 2..100 {
                                                loss_detector.connect_block(&[]);
                                        }
+                                       input.halt_fee_est_reads.store(false, Ordering::Release);
                                }
                                for tx in txn.drain(..) {
                                        loss_detector.funding_txn.push(tx);
@@ -713,11 +726,11 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                                } else {
                                        let txres: Result<Transaction, _> = deserialize(get_slice!(txlen));
                                        if let Ok(tx) = txres {
-                                               let mut output_val = 0;
+                                               let mut output_val = Amount::ZERO;
                                                for out in tx.output.iter() {
-                                                       if out.value > 21_000_000_0000_0000 { return; }
+                                                       if out.value > Amount::MAX_MONEY { return; }
                                                        output_val += out.value;
-                                                       if output_val > 21_000_000_0000_0000 { return; }
+                                                       if output_val > Amount::MAX_MONEY { return; }
                                                }
                                                loss_detector.connect_block(&[tx]);
                                        } else {
@@ -731,16 +744,17 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
                        14 => {
                                let mut channels = channelmanager.list_channels();
                                let channel_id = get_slice!(1)[0] as usize;
+                               let error_message = "Channel force-closed";
                                if channel_id >= channels.len() { return; }
                                channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) });
-                               channelmanager.force_close_broadcasting_latest_txn(&channels[channel_id].channel_id, &channels[channel_id].counterparty.node_id).unwrap();
+                               channelmanager.force_close_broadcasting_latest_txn(&channels[channel_id].channel_id, &channels[channel_id].counterparty.node_id, error_message.to_string()).unwrap();
                        },
                        // 15, 16, 17, 18 is above
                        19 => {
-                               let mut list = loss_detector.handler.get_peer_node_ids();
-                               list.sort_by_key(|v| v.0);
-                               if let Some((id, _)) = list.get(0) {
-                                       loss_detector.handler.disconnect_by_node_id(*id);
+                               let mut list = loss_detector.handler.list_peers();
+                               list.sort_by_key(|v| v.counterparty_node_id);
+                               if let Some(peer_details) = list.get(0) {
+                                       loss_detector.handler.disconnect_by_node_id(peer_details.counterparty_node_id);
                                }
                        },
                        20 => loss_detector.handler.disconnect_all_peers(),
@@ -856,7 +870,7 @@ mod tests {
                // our network key
                ext_from_hex("0100000000000000000000000000000000000000000000000000000000000000", &mut test);
                // config
-               ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff0001000000", &mut test);
+               ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff000100000000", &mut test);
 
                // new outbound connection with id 0
                ext_from_hex("00", &mut test);
@@ -907,19 +921,32 @@ mod tests {
                ext_from_hex("0c005e", &mut test);
                // the funding transaction
                ext_from_hex("020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae0000000000000000000000000000000000000000000000000000000000000000000000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                // connect a block with no transactions, one per line
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                // by now client should have sent a channel_ready (CHECK 3: SendChannelReady to 03000000 for chan 3d000000)
 
                // inbound read from peer id 0 of len 18
@@ -971,6 +998,8 @@ mod tests {
 
                // create the funding transaction (client should send funding_created now)
                ext_from_hex("0a", &mut test);
+               // Two feerate requests to check the dust exposure on the initial commitment tx
+               ext_from_hex("00fd00fd", &mut test);
 
                // inbound read from peer id 1 of len 18
                ext_from_hex("030112", &mut test);
@@ -1019,6 +1048,9 @@ mod tests {
                // end of update_add_htlc from 0 to 1 via client and mac
                ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ab00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);
 
+               // Two feerate requests to check dust exposure
+               ext_from_hex("00fd00fd", &mut test);
+
                // inbound read from peer id 0 of len 18
                ext_from_hex("030012", &mut test);
                // message header indicating message length 100
@@ -1040,6 +1072,8 @@ mod tests {
 
                // process the now-pending HTLC forward
                ext_from_hex("07", &mut test);
+               // Two feerate requests to check dust exposure
+               ext_from_hex("00fd00fd", &mut test);
                // client now sends id 1 update_add_htlc and commitment_signed (CHECK 7: UpdateHTLCs event for node 03020000 with 1 HTLCs for channel 3f000000)
 
                // we respond with commitment_signed then revoke_and_ack (a weird, but valid, order)
@@ -1115,6 +1149,9 @@ mod tests {
                // end of update_add_htlc from 0 to 1 via client and mac
                ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ab00000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);
 
+               // Two feerate requests to check dust exposure
+               ext_from_hex("00fd00fd", &mut test);
+
                // now respond to the update_fulfill_htlc+commitment_signed messages the client sent to peer 0
                // inbound read from peer id 0 of len 18
                ext_from_hex("030012", &mut test);
@@ -1146,6 +1183,10 @@ mod tests {
 
                // process the now-pending HTLC forward
                ext_from_hex("07", &mut test);
+
+               // Two feerate requests to check dust exposure
+               ext_from_hex("00fd00fd", &mut test);
+
                // client now sends id 1 update_add_htlc and commitment_signed (CHECK 7 duplicate)
                // we respond with revoke_and_ack, then commitment_signed, then update_fail_htlc
 
@@ -1243,6 +1284,9 @@ mod tests {
                // end of update_add_htlc from 0 to 1 via client and mac
                ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 5300000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);
 
+               // Two feerate requests to check dust exposure
+               ext_from_hex("00fd00fd", &mut test);
+
                // inbound read from peer id 0 of len 18
                ext_from_hex("030012", &mut test);
                // message header indicating message length 164
@@ -1264,27 +1308,36 @@ mod tests {
 
                // process the now-pending HTLC forward
                ext_from_hex("07", &mut test);
+               // Two feerate requests to check dust exposure
+               ext_from_hex("00fd00fd", &mut test);
                // client now sends id 1 update_add_htlc and commitment_signed (CHECK 7 duplicate)
 
                // connect a block with one transaction of len 125
                ext_from_hex("0c007d", &mut test);
                // the commitment transaction for channel 3f00000000000000000000000000000000000000000000000000000000000000
                ext_from_hex("02000000013a000000000000000000000000000000000000000000000000000000000000000000000000000000800258020000000000002200204b0000000000000000000000000000000000000000000000000000000000000014c0000000000000160014280000000000000000000000000000000000000005000020", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                //
                // connect a block with one transaction of len 94
                ext_from_hex("0c005e", &mut test);
                // the HTLC timeout transaction
                ext_from_hex("0200000001730000000000000000000000000000000000000000000000000000000000000000000000000000000001a701000000000000220020b20000000000000000000000000000000000000000000000000000000000000000000000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                // connect a block with no transactions
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                // connect a block with no transactions
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                // connect a block with no transactions
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                // connect a block with no transactions
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
                // connect a block with no transactions
                ext_from_hex("0c0000", &mut test);
+               ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
 
                // process the now-pending HTLC forward
                ext_from_hex("07", &mut test);
@@ -1330,7 +1383,7 @@ mod tests {
                // our network key
                ext_from_hex("0100000000000000000000000000000000000000000000000000000000000000", &mut test);
                // config
-               ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff0001000000", &mut test);
+               ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff000100000000", &mut test);
 
                // new outbound connection with id 0
                ext_from_hex("00", &mut test);