Thread fuzz test cases
[rust-lightning] / fuzz / src / full_stack.rs
index 242c5957f943deb42ae13c44a43cfc5af8753015..c759094306a8e3df666963d4050c11f3fa55bb82 100644 (file)
@@ -22,7 +22,7 @@ use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,C
 use lightning::chain::transaction::OutPoint;
 use lightning::chain::keysinterface::{InMemoryChannelKeys, KeysInterface};
 use lightning::ln::channelmonitor;
-use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage};
+use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret};
 use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
 use lightning::ln::router::Router;
 use lightning::util::events::{EventsProvider,Event};
@@ -99,7 +99,7 @@ impl FeeEstimator for FuzzEstimator {
                //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 u64, 253),
-                       None => 0
+                       None => 253
                }
        }
 }
@@ -343,7 +343,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
        }, our_network_key, &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0], Arc::clone(&logger)));
 
        let mut should_forward = false;
-       let mut payments_received: Vec<(PaymentHash, u64)> = Vec::new();
+       let mut payments_received: Vec<(PaymentHash, Option<PaymentSecret>, u64)> = Vec::new();
        let mut payments_sent = 0;
        let mut pending_funding_generation: Vec<([u8; 32], u64, Script)> = Vec::new();
        let mut pending_funding_signatures = HashMap::new();
@@ -384,7 +384,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                        3 => {
                                let peer_id = get_slice!(1)[0];
                                if !peers.borrow()[peer_id as usize] { return; }
-                               match loss_detector.handler.read_event(&mut Peer{id: peer_id, peers_connected: &peers}, get_slice!(get_slice!(1)[0]).to_vec()) {
+                               match loss_detector.handler.read_event(&mut Peer{id: peer_id, peers_connected: &peers}, get_slice!(get_slice!(1)[0])) {
                                        Ok(res) => assert!(!res),
                                        Err(_) => { peers.borrow_mut()[peer_id as usize] = false; }
                                }
@@ -401,7 +401,28 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                sha.input(&payment_hash.0[..]);
                                payment_hash.0 = Sha256::from_engine(sha).into_inner();
                                payments_sent += 1;
-                               match channelmanager.send_payment(route, payment_hash) {
+                               match channelmanager.send_payment(&route, payment_hash, &None) {
+                                       Ok(_) => {},
+                                       Err(_) => return,
+                               }
+                       },
+                       15 => {
+                               let value = slice_to_be24(get_slice!(3)) as u64;
+                               let mut route = match router.get_route(&get_pubkey!(), None, &Vec::new(), value, 42) {
+                                       Ok(route) => route,
+                                       Err(_) => return,
+                               };
+                               route.paths.push(route.paths[0].clone());
+                               let mut payment_hash = PaymentHash([0; 32]);
+                               payment_hash.0[0..8].copy_from_slice(&be64_to_array(payments_sent));
+                               let mut sha = Sha256::engine();
+                               sha.input(&payment_hash.0[..]);
+                               payment_hash.0 = Sha256::from_engine(sha).into_inner();
+                               payments_sent += 1;
+                               let mut payment_secret = PaymentSecret([0; 32]);
+                               payment_secret.0[0..8].copy_from_slice(&be64_to_array(payments_sent));
+                               payments_sent += 1;
+                               match channelmanager.send_payment(&route, payment_hash, &Some(payment_secret)) {
                                        Ok(_) => {},
                                        Err(_) => return,
                                }
@@ -412,7 +433,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                let their_key = get_pubkey!();
                                let chan_value = slice_to_be24(get_slice!(3)) as u64;
                                let push_msat_value = slice_to_be24(get_slice!(3)) as u64;
-                               if channelmanager.create_channel(their_key, chan_value, push_msat_value, 0).is_err() { return; }
+                               if channelmanager.create_channel(their_key, chan_value, push_msat_value, 0, None).is_err() { return; }
                        },
                        6 => {
                                let mut channels = channelmanager.list_channels();
@@ -428,23 +449,23 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                }
                        },
                        8 => {
-                               for (payment, amt) in payments_received.drain(..) {
+                               for (payment, payment_secret, amt) in payments_received.drain(..) {
                                        // SHA256 is defined as XOR of all input bytes placed in the first byte, and 0s
                                        // for the remaining bytes. Thus, if not all remaining bytes are 0s we cannot
                                        // fulfill this HTLC, but if they are, we can just take the first byte and
                                        // place that anywhere in our preimage.
                                        if &payment.0[1..] != &[0; 31] {
-                                               channelmanager.fail_htlc_backwards(&payment);
+                                               channelmanager.fail_htlc_backwards(&payment, &payment_secret);
                                        } else {
                                                let mut payment_preimage = PaymentPreimage([0; 32]);
                                                payment_preimage.0[0] = payment.0[0];
-                                               channelmanager.claim_funds(payment_preimage, amt);
+                                               channelmanager.claim_funds(payment_preimage, &payment_secret, amt);
                                        }
                                }
                        },
                        9 => {
-                               for (payment, _) in payments_received.drain(..) {
-                                       channelmanager.fail_htlc_backwards(&payment);
+                               for (payment, payment_secret, _) in payments_received.drain(..) {
+                                       channelmanager.fail_htlc_backwards(&payment, &payment_secret);
                                }
                        },
                        10 => {
@@ -513,6 +534,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                channels.sort_by(|a, b| { a.channel_id.cmp(&b.channel_id) });
                                channelmanager.force_close_channel(&channels[channel_id].channel_id);
                        },
+                       // 15 is above
                        _ => return,
                }
                loss_detector.handler.process_events();
@@ -524,9 +546,9 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                Event::FundingBroadcastSafe { funding_txo, .. } => {
                                        pending_funding_relay.push(pending_funding_signatures.remove(&funding_txo).unwrap());
                                },
-                               Event::PaymentReceived { payment_hash, amt } => {
+                               Event::PaymentReceived { payment_hash, payment_secret, amt } => {
                                        //TODO: enhance by fetching random amounts from fuzz input?
-                                       payments_received.push((payment_hash, amt));
+                                       payments_received.push((payment_hash, payment_secret, amt));
                                },
                                Event::PaymentSent {..} => {},
                                Event::PaymentFailed {..} => {},
@@ -539,15 +561,19 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
        }
 }
 
+pub fn full_stack_test<Out: test_logger::Output>(data: &[u8], out: Out) {
+       let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new("".to_owned(), out));
+       do_test(data, &logger);
+}
+
 #[no_mangle]
 pub extern "C" fn full_stack_run(data: *const u8, datalen: usize) {
-       let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new("".to_owned()));
+       let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new("".to_owned(), test_logger::DevNull {}));
        do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, &logger);
 }
 
 #[cfg(test)]
 mod tests {
-       use utils::test_logger;
        use lightning::util::logger::{Logger, Record};
        use std::collections::HashMap;
        use std::sync::{Arc, Mutex};