X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=50dd6b956318c54545974fdcba5537c7c4fc435f;hb=5bd7f24634a983326924f200bfff7c7c0fa56601;hp=8a887e7fab0353b69d6ca1a9d70bb9b18931e83a;hpb=b2c9941015007702a87dbc9a8ea00fa0f2a45a74;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 8a887e7f..50dd6b95 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -6,7 +6,7 @@ use chain::transaction::OutPoint; use chain::keysinterface::KeysInterface; use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure}; use ln::channelmonitor::{ChannelMonitor, ManyChannelMonitor}; -use ln::router::{Route, Router, RouterReadArgs}; +use routing::router::{Route, Router, RouterReadArgs}; use ln::features::InitFeatures; use ln::msgs; use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler}; @@ -24,12 +24,12 @@ use bitcoin::blockdata::block::BlockHeader; use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::network::constants::Network; -use bitcoin_hashes::sha256::Hash as Sha256; -use bitcoin_hashes::sha256d::Hash as Sha256d; -use bitcoin_hashes::Hash; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::Hash; +use bitcoin::hash_types::BlockHash; -use secp256k1::Secp256k1; -use secp256k1::key::PublicKey; +use bitcoin::secp256k1::Secp256k1; +use bitcoin::secp256k1::key::PublicKey; use rand::{thread_rng,Rng}; @@ -50,7 +50,7 @@ pub fn confirm_transaction<'a, 'b: 'a>(notifier: &'a chaininterface::BlockNotifi } } -pub fn connect_blocks<'a, 'b>(notifier: &'a chaininterface::BlockNotifierRef<'b>, depth: u32, height: u32, parent: bool, prev_blockhash: Sha256d) -> Sha256d { +pub fn connect_blocks<'a, 'b>(notifier: &'a chaininterface::BlockNotifierRef<'b>, depth: u32, height: u32, parent: bool, prev_blockhash: BlockHash) -> BlockHash { let mut header = BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; notifier.block_connected_checked(&header, height + 1, &Vec::new(), &Vec::new()); for i in 2..depth + 1 { @@ -137,7 +137,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { for (_, old_monitor) in old_monitors.iter() { let mut w = test_utils::TestVecWriter(Vec::new()); old_monitor.write_for_disk(&mut w).unwrap(); - let (_, deserialized_monitor) = <(Sha256d, ChannelMonitor)>::read( + let (_, deserialized_monitor) = <(BlockHash, ChannelMonitor)>::read( &mut ::std::io::Cursor::new(&w.0), Arc::clone(&self.logger) as Arc).unwrap(); deserialized_monitors.push(deserialized_monitor); } @@ -148,12 +148,12 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { { let mut channel_monitors = HashMap::new(); for monitor in deserialized_monitors.iter_mut() { - channel_monitors.insert(monitor.get_funding_txo().unwrap(), monitor); + channel_monitors.insert(monitor.get_funding_txo(), monitor); } let mut w = test_utils::TestVecWriter(Vec::new()); self.node.write(&mut w).unwrap(); - <(Sha256d, ChannelManager)>::read(&mut ::std::io::Cursor::new(w.0), ChannelManagerReadArgs { + <(BlockHash, ChannelManager)>::read(&mut ::std::io::Cursor::new(w.0), ChannelManagerReadArgs { default_config: UserConfig::default(), keys_manager: self.keys_manager, fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: 253 }, @@ -167,7 +167,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { let chain_watch = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&self.logger) as Arc)); let channel_monitor = test_utils::TestChannelMonitor::new(chain_watch.clone(), self.tx_broadcaster.clone(), self.logger.clone(), &feeest); for deserialized_monitor in deserialized_monitors.drain(..) { - if let Err(_) = channel_monitor.add_monitor(deserialized_monitor.get_funding_txo().unwrap(), deserialized_monitor) { + if let Err(_) = channel_monitor.add_monitor(deserialized_monitor.get_funding_txo(), deserialized_monitor) { panic!(); } } @@ -264,7 +264,7 @@ macro_rules! get_local_commitment_txn { let mut commitment_txn = None; for (funding_txo, monitor) in monitors.iter_mut() { if funding_txo.to_channel_id() == $channel_id { - commitment_txn = Some(monitor.get_latest_local_commitment_txn()); + commitment_txn = Some(monitor.unsafe_get_latest_local_commitment_txn()); break; } } @@ -295,6 +295,16 @@ macro_rules! unwrap_send_err { } } +macro_rules! check_added_monitors { + ($node: expr, $count: expr) => { + { + let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap(); + assert_eq!(added_monitors.len(), $count); + added_monitors.clear(); + } + } +} + pub fn create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, expected_chan_value: u64, expected_user_chan_id: u64) -> ([u8; 32], Transaction, OutPoint) { let chan_id = *node.network_chan_count.borrow(); @@ -322,13 +332,8 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, ' let (temporary_channel_id, tx, funding_output) = create_funding_transaction(node_a, channel_value, 42); - { - node_a.node.funding_transaction_generated(&temporary_channel_id, funding_output); - let mut added_monitors = node_a.chan_monitor.added_monitors.lock().unwrap(); - assert_eq!(added_monitors.len(), 1); - assert_eq!(added_monitors[0].0, funding_output); - added_monitors.clear(); - } + node_a.node.funding_transaction_generated(&temporary_channel_id, funding_output); + check_added_monitors!(node_a, 0); node_b.node.handle_funding_created(&node_a.node.get_our_node_id(), &get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id())); { @@ -620,16 +625,6 @@ impl SendEvent { } } -macro_rules! check_added_monitors { - ($node: expr, $count: expr) => { - { - let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap(); - assert_eq!(added_monitors.len(), $count); - added_monitors.clear(); - } - } -} - macro_rules! commitment_signed_dance { ($node_a: expr, $node_b: expr, $commitment_signed: expr, $fail_backwards: expr, true /* skip last step */) => { { @@ -722,7 +717,7 @@ macro_rules! get_payment_preimage_hash { } } -macro_rules! expect_pending_htlcs_forwardable { +macro_rules! expect_pending_htlcs_forwardable_ignore { ($node: expr) => {{ let events = $node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); @@ -730,6 +725,12 @@ macro_rules! expect_pending_htlcs_forwardable { Event::PendingHTLCsForwardable { .. } => { }, _ => panic!("Unexpected event"), }; + }} +} + +macro_rules! expect_pending_htlcs_forwardable { + ($node: expr) => {{ + expect_pending_htlcs_forwardable_ignore!($node); $node.node.process_pending_htlc_forwards(); }} } @@ -763,31 +764,36 @@ macro_rules! expect_payment_sent { } macro_rules! expect_payment_failed { - ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr) => { + ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr $(, $expected_error_code: expr, $expected_error_data: expr)*) => { let events = $node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentFailed { ref payment_hash, rejected_by_dest, .. } => { + Event::PaymentFailed { ref payment_hash, rejected_by_dest, ref error_code, ref error_data } => { assert_eq!(*payment_hash, $expected_payment_hash); assert_eq!(rejected_by_dest, $rejected_by_dest); + assert!(error_code.is_some()); + assert!(error_data.is_some()); + $( + assert_eq!(error_code.unwrap(), $expected_error_code); + assert_eq!(&error_data.as_ref().unwrap()[..], $expected_error_data); + )* }, _ => panic!("Unexpected event"), } } } -pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option) { - let mut payment_event = { - origin_node.node.send_payment(route, our_payment_hash, &our_payment_secret).unwrap(); - check_added_monitors!(origin_node, 1); +pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_paths: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option) { + origin_node.node.send_payment(&route, our_payment_hash, &our_payment_secret).unwrap(); + check_added_monitors!(origin_node, expected_paths.len()); + pass_along_route(origin_node, expected_paths, recv_value, our_payment_hash, our_payment_secret); +} - let mut events = origin_node.node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - SendEvent::from_event(events.remove(0)) - }; +pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option, ev: MessageSendEvent, payment_received_expected: bool) { + let mut payment_event = SendEvent::from_event(ev); let mut prev_node = origin_node; - for (idx, &node) in expected_route.iter().enumerate() { + for (idx, &node) in expected_path.iter().enumerate() { assert_eq!(node.node.get_our_node_id(), payment_event.node_id); node.node.handle_update_add_htlc(&prev_node.node.get_our_node_id(), &payment_event.msgs[0]); @@ -796,16 +802,20 @@ pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expect_pending_htlcs_forwardable!(node); - if idx == expected_route.len() - 1 { + if idx == expected_path.len() - 1 { let events_2 = node.node.get_and_clear_pending_events(); - assert_eq!(events_2.len(), 1); - match events_2[0] { - Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => { - assert_eq!(our_payment_hash, *payment_hash); - assert_eq!(our_payment_secret, *payment_secret); - assert_eq!(amt, recv_value); - }, - _ => panic!("Unexpected event"), + if payment_received_expected { + assert_eq!(events_2.len(), 1); + match events_2[0] { + Event::PaymentReceived { ref payment_hash, ref payment_secret, amt } => { + assert_eq!(our_payment_hash, *payment_hash); + assert_eq!(our_payment_secret, *payment_secret); + assert_eq!(amt, recv_value); + }, + _ => panic!("Unexpected event"), + } + } else { + assert!(events_2.is_empty()); } } else { let mut events_2 = node.node.get_and_clear_pending_msg_events(); @@ -819,8 +829,19 @@ pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, } } +pub fn pass_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option) { + let mut events = origin_node.node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), expected_route.len()); + for (path_idx, (ev, expected_path)) in events.drain(..).zip(expected_route.iter()).enumerate() { + // Once we've gotten through all the HTLCs, the last one should result in a + // PaymentReceived (but each previous one should not!), . + let expect_payment = path_idx == expected_route.len() - 1; + pass_along_path(origin_node, expected_path, recv_value, our_payment_hash.clone(), our_payment_secret, ev, expect_payment); + } +} + pub fn send_along_route_with_hash<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash) { - send_along_route_with_secret(origin_node, route, expected_route, recv_value, our_payment_hash, None); + send_along_route_with_secret(origin_node, route, &[expected_route], recv_value, our_payment_hash, None); } pub fn send_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash) { @@ -829,86 +850,96 @@ pub fn send_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route (our_payment_preimage, our_payment_hash) } -pub fn claim_payment_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_preimage: PaymentPreimage, our_payment_secret: Option, expected_amount: u64) { - assert!(expected_route.last().unwrap().node.claim_funds(our_payment_preimage, &our_payment_secret, expected_amount)); - check_added_monitors!(expected_route.last().unwrap(), 1); +pub fn claim_payment_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage, our_payment_secret: Option, expected_amount: u64) { + for path in expected_paths.iter() { + assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id()); + } + assert!(expected_paths[0].last().unwrap().node.claim_funds(our_payment_preimage, &our_payment_secret, expected_amount)); + check_added_monitors!(expected_paths[0].last().unwrap(), expected_paths.len()); - let mut next_msgs: Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)> = None; - let mut expected_next_node = expected_route.last().unwrap().node.get_our_node_id(); - macro_rules! get_next_msgs { - ($node: expr) => { - { - let events = $node.node.get_and_clear_pending_msg_events(); - assert_eq!(events.len(), 1); - match events[0] { - MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { - assert!(update_add_htlcs.is_empty()); - assert_eq!(update_fulfill_htlcs.len(), 1); - assert!(update_fail_htlcs.is_empty()); - assert!(update_fail_malformed_htlcs.is_empty()); - assert!(update_fee.is_none()); - expected_next_node = node_id.clone(); - Some((update_fulfill_htlcs[0].clone(), commitment_signed.clone())) - }, - _ => panic!("Unexpected event"), - } + macro_rules! msgs_from_ev { + ($ev: expr) => { + match $ev { + &MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { + assert!(update_add_htlcs.is_empty()); + assert_eq!(update_fulfill_htlcs.len(), 1); + assert!(update_fail_htlcs.is_empty()); + assert!(update_fail_malformed_htlcs.is_empty()); + assert!(update_fee.is_none()); + ((update_fulfill_htlcs[0].clone(), commitment_signed.clone()), node_id.clone()) + }, + _ => panic!("Unexpected event"), } } } + let mut per_path_msgs: Vec<((msgs::UpdateFulfillHTLC, msgs::CommitmentSigned), PublicKey)> = Vec::with_capacity(expected_paths.len()); + let events = expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), expected_paths.len()); + for ev in events.iter() { + per_path_msgs.push(msgs_from_ev!(ev)); + } - macro_rules! last_update_fulfill_dance { - ($node: expr, $prev_node: expr) => { - { - $node.node.handle_update_fulfill_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); - check_added_monitors!($node, 0); - assert!($node.node.get_and_clear_pending_msg_events().is_empty()); - commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, false); + for (expected_route, (path_msgs, next_hop)) in expected_paths.iter().zip(per_path_msgs.drain(..)) { + let mut next_msgs = Some(path_msgs); + let mut expected_next_node = next_hop; + + macro_rules! last_update_fulfill_dance { + ($node: expr, $prev_node: expr) => { + { + $node.node.handle_update_fulfill_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); + check_added_monitors!($node, 0); + assert!($node.node.get_and_clear_pending_msg_events().is_empty()); + commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, false); + } } } - } - macro_rules! mid_update_fulfill_dance { - ($node: expr, $prev_node: expr, $new_msgs: expr) => { - { - $node.node.handle_update_fulfill_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); - check_added_monitors!($node, 1); - let new_next_msgs = if $new_msgs { - get_next_msgs!($node) - } else { - assert!($node.node.get_and_clear_pending_msg_events().is_empty()); - None - }; - commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, false); - next_msgs = new_next_msgs; + macro_rules! mid_update_fulfill_dance { + ($node: expr, $prev_node: expr, $new_msgs: expr) => { + { + $node.node.handle_update_fulfill_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); + check_added_monitors!($node, 1); + let new_next_msgs = if $new_msgs { + let events = $node.node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let (res, nexthop) = msgs_from_ev!(&events[0]); + expected_next_node = nexthop; + Some(res) + } else { + assert!($node.node.get_and_clear_pending_msg_events().is_empty()); + None + }; + commitment_signed_dance!($node, $prev_node, next_msgs.as_ref().unwrap().1, false); + next_msgs = new_next_msgs; + } } } - } - let mut prev_node = expected_route.last().unwrap(); - for (idx, node) in expected_route.iter().rev().enumerate() { - assert_eq!(expected_next_node, node.node.get_our_node_id()); - let update_next_msgs = !skip_last || idx != expected_route.len() - 1; - if next_msgs.is_some() { - mid_update_fulfill_dance!(node, prev_node, update_next_msgs); - } else if update_next_msgs { - next_msgs = get_next_msgs!(node); - } else { - assert!(node.node.get_and_clear_pending_msg_events().is_empty()); - } - if !skip_last && idx == expected_route.len() - 1 { - assert_eq!(expected_next_node, origin_node.node.get_our_node_id()); - } + let mut prev_node = expected_route.last().unwrap(); + for (idx, node) in expected_route.iter().rev().enumerate().skip(1) { + assert_eq!(expected_next_node, node.node.get_our_node_id()); + let update_next_msgs = !skip_last || idx != expected_route.len() - 1; + if next_msgs.is_some() { + mid_update_fulfill_dance!(node, prev_node, update_next_msgs); + } else { + assert!(!update_next_msgs); + assert!(node.node.get_and_clear_pending_msg_events().is_empty()); + } + if !skip_last && idx == expected_route.len() - 1 { + assert_eq!(expected_next_node, origin_node.node.get_our_node_id()); + } - prev_node = node; - } + prev_node = node; + } - if !skip_last { - last_update_fulfill_dance!(origin_node, expected_route.first().unwrap()); - expect_payment_sent!(origin_node, our_payment_preimage); + if !skip_last { + last_update_fulfill_dance!(origin_node, expected_route.first().unwrap()); + expect_payment_sent!(origin_node, our_payment_preimage); + } } } pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], skip_last: bool, our_payment_preimage: PaymentPreimage, expected_amount: u64) { - claim_payment_along_route_with_secret(origin_node, expected_route, skip_last, our_payment_preimage, None, expected_amount); + claim_payment_along_route_with_secret(origin_node, &[expected_route], skip_last, our_payment_preimage, None, expected_amount); } pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], our_payment_preimage: PaymentPreimage, expected_amount: u64) { @@ -937,7 +968,7 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou } let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node); - unwrap_send_err!(origin_node.node.send_payment(route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err }, + unwrap_send_err!(origin_node.node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err }, assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept")); }