+
+ macro_rules! handle_chan_reestablish_msgs {
+ ($src_node: expr, $dst_node: expr) => {
+ {
+ let msg_events = $src_node.node.get_and_clear_pending_msg_events();
+ let mut idx = 0;
+ let funding_locked = if let Some(&MessageSendEvent::SendFundingLocked { ref node_id, ref msg }) = msg_events.get(0) {
+ idx += 1;
+ assert_eq!(*node_id, $dst_node.node.get_our_node_id());
+ Some(msg.clone())
+ } else {
+ None
+ };
+
+ let mut revoke_and_ack = None;
+ let mut commitment_update = None;
+ let order = if let Some(ev) = msg_events.get(idx) {
+ idx += 1;
+ match ev {
+ &MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
+ assert_eq!(*node_id, $dst_node.node.get_our_node_id());
+ revoke_and_ack = Some(msg.clone());
+ RAACommitmentOrder::RevokeAndACKFirst
+ },
+ &MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => {
+ assert_eq!(*node_id, $dst_node.node.get_our_node_id());
+ commitment_update = Some(updates.clone());
+ RAACommitmentOrder::CommitmentFirst
+ },
+ _ => panic!("Unexpected event"),
+ }
+ } else {
+ RAACommitmentOrder::CommitmentFirst
+ };
+
+ if let Some(ev) = msg_events.get(idx) {
+ match ev {
+ &MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
+ assert_eq!(*node_id, $dst_node.node.get_our_node_id());
+ assert!(revoke_and_ack.is_none());
+ revoke_and_ack = Some(msg.clone());
+ },
+ &MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => {
+ assert_eq!(*node_id, $dst_node.node.get_our_node_id());
+ assert!(commitment_update.is_none());
+ commitment_update = Some(updates.clone());
+ },
+ _ => panic!("Unexpected event"),
+ }
+ }
+
+ (funding_locked, revoke_and_ack, commitment_update, order)
+ }
+ }
+ }
+
+ /// pending_htlc_adds includes both the holding cell and in-flight update_add_htlcs, whereas
+ /// for claims/fails they are separated out.
+ fn reconnect_nodes(node_a: &Node, node_b: &Node, send_funding_locked: (bool, bool), pending_htlc_adds: (i64, i64), pending_htlc_claims: (usize, usize), pending_cell_htlc_claims: (usize, usize), pending_cell_htlc_fails: (usize, usize), pending_raa: (bool, bool)) {
+ node_a.node.peer_connected(&node_b.node.get_our_node_id());
+ let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b);
+ node_b.node.peer_connected(&node_a.node.get_our_node_id());
+ let reestablish_2 = get_chan_reestablish_msgs!(node_b, node_a);
+
+ if send_funding_locked.0 {
+ // If a expects a funding_locked, it better not think it has received a revoke_and_ack
+ // from b
+ for reestablish in reestablish_1.iter() {
+ assert_eq!(reestablish.next_remote_commitment_number, 0);
+ }
+ }
+ if send_funding_locked.1 {
+ // If b expects a funding_locked, it better not think it has received a revoke_and_ack
+ // from a
+ for reestablish in reestablish_2.iter() {
+ assert_eq!(reestablish.next_remote_commitment_number, 0);
+ }
+ }
+ if send_funding_locked.0 || send_funding_locked.1 {
+ // If we expect any funding_locked's, both sides better have set
+ // next_local_commitment_number to 1
+ for reestablish in reestablish_1.iter() {
+ assert_eq!(reestablish.next_local_commitment_number, 1);
+ }
+ for reestablish in reestablish_2.iter() {
+ assert_eq!(reestablish.next_local_commitment_number, 1);
+ }
+ }
+
+ let mut resp_1 = Vec::new();
+ for msg in reestablish_1 {
+ node_b.node.handle_channel_reestablish(&node_a.node.get_our_node_id(), &msg).unwrap();
+ resp_1.push(handle_chan_reestablish_msgs!(node_b, node_a));
+ }
+ if pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 {
+ check_added_monitors!(node_b, 1);
+ } else {
+ check_added_monitors!(node_b, 0);
+ }
+
+ let mut resp_2 = Vec::new();
+ for msg in reestablish_2 {
+ node_a.node.handle_channel_reestablish(&node_b.node.get_our_node_id(), &msg).unwrap();
+ resp_2.push(handle_chan_reestablish_msgs!(node_a, node_b));
+ }
+ if pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 {
+ check_added_monitors!(node_a, 1);
+ } else {
+ check_added_monitors!(node_a, 0);
+ }
+
+ // We dont yet support both needing updates, as that would require a different commitment dance:
+ assert!((pending_htlc_adds.0 == 0 && pending_htlc_claims.0 == 0 && pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0) ||
+ (pending_htlc_adds.1 == 0 && pending_htlc_claims.1 == 0 && pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0));
+
+ for chan_msgs in resp_1.drain(..) {
+ if send_funding_locked.0 {
+ node_a.node.handle_funding_locked(&node_b.node.get_our_node_id(), &chan_msgs.0.unwrap()).unwrap();
+ let announcement_event = node_a.node.get_and_clear_pending_msg_events();
+ if !announcement_event.is_empty() {
+ assert_eq!(announcement_event.len(), 1);
+ if let MessageSendEvent::SendAnnouncementSignatures { .. } = announcement_event[0] {
+ //TODO: Test announcement_sigs re-sending
+ } else { panic!("Unexpected event!"); }
+ }
+ } else {
+ assert!(chan_msgs.0.is_none());
+ }
+ if pending_raa.0 {
+ assert!(chan_msgs.3 == RAACommitmentOrder::RevokeAndACKFirst);
+ node_a.node.handle_revoke_and_ack(&node_b.node.get_our_node_id(), &chan_msgs.1.unwrap()).unwrap();
+ assert!(node_a.node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(node_a, 1);
+ } else {
+ assert!(chan_msgs.1.is_none());
+ }
+ if pending_htlc_adds.0 != 0 || pending_htlc_claims.0 != 0 || pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 {
+ let commitment_update = chan_msgs.2.unwrap();
+ if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed
+ assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.0 as usize);
+ } else {
+ assert!(commitment_update.update_add_htlcs.is_empty());
+ }
+ assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0 + pending_cell_htlc_claims.0);
+ assert_eq!(commitment_update.update_fail_htlcs.len(), pending_cell_htlc_fails.0);
+ assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
+ for update_add in commitment_update.update_add_htlcs {
+ node_a.node.handle_update_add_htlc(&node_b.node.get_our_node_id(), &update_add).unwrap();
+ }
+ for update_fulfill in commitment_update.update_fulfill_htlcs {
+ node_a.node.handle_update_fulfill_htlc(&node_b.node.get_our_node_id(), &update_fulfill).unwrap();
+ }
+ for update_fail in commitment_update.update_fail_htlcs {
+ node_a.node.handle_update_fail_htlc(&node_b.node.get_our_node_id(), &update_fail).unwrap();
+ }
+
+ if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed
+ commitment_signed_dance!(node_a, node_b, commitment_update.commitment_signed, false);
+ } else {
+ node_a.node.handle_commitment_signed(&node_b.node.get_our_node_id(), &commitment_update.commitment_signed).unwrap();
+ check_added_monitors!(node_a, 1);
+ let as_revoke_and_ack = get_event_msg!(node_a, MessageSendEvent::SendRevokeAndACK, node_b.node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ node_b.node.handle_revoke_and_ack(&node_a.node.get_our_node_id(), &as_revoke_and_ack).unwrap();
+ assert!(node_b.node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(node_b, 1);
+ }
+ } else {
+ assert!(chan_msgs.2.is_none());
+ }
+ }
+
+ for chan_msgs in resp_2.drain(..) {
+ if send_funding_locked.1 {
+ node_b.node.handle_funding_locked(&node_a.node.get_our_node_id(), &chan_msgs.0.unwrap()).unwrap();
+ let announcement_event = node_b.node.get_and_clear_pending_msg_events();
+ if !announcement_event.is_empty() {
+ assert_eq!(announcement_event.len(), 1);
+ if let MessageSendEvent::SendAnnouncementSignatures { .. } = announcement_event[0] {
+ //TODO: Test announcement_sigs re-sending
+ } else { panic!("Unexpected event!"); }
+ }
+ } else {
+ assert!(chan_msgs.0.is_none());
+ }
+ if pending_raa.1 {
+ assert!(chan_msgs.3 == RAACommitmentOrder::RevokeAndACKFirst);
+ node_b.node.handle_revoke_and_ack(&node_a.node.get_our_node_id(), &chan_msgs.1.unwrap()).unwrap();
+ assert!(node_b.node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(node_b, 1);
+ } else {
+ assert!(chan_msgs.1.is_none());
+ }
+ if pending_htlc_adds.1 != 0 || pending_htlc_claims.1 != 0 || pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 {
+ let commitment_update = chan_msgs.2.unwrap();
+ if pending_htlc_adds.1 != -1 { // We use -1 to denote a response commitment_signed
+ assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.1 as usize);
+ }
+ assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0 + pending_cell_htlc_claims.0);
+ assert_eq!(commitment_update.update_fail_htlcs.len(), pending_cell_htlc_fails.0);
+ assert!(commitment_update.update_fail_malformed_htlcs.is_empty());
+ for update_add in commitment_update.update_add_htlcs {
+ node_b.node.handle_update_add_htlc(&node_a.node.get_our_node_id(), &update_add).unwrap();
+ }
+ for update_fulfill in commitment_update.update_fulfill_htlcs {
+ node_b.node.handle_update_fulfill_htlc(&node_a.node.get_our_node_id(), &update_fulfill).unwrap();
+ }
+ for update_fail in commitment_update.update_fail_htlcs {
+ node_b.node.handle_update_fail_htlc(&node_a.node.get_our_node_id(), &update_fail).unwrap();
+ }
+
+ if pending_htlc_adds.1 != -1 { // We use -1 to denote a response commitment_signed
+ commitment_signed_dance!(node_b, node_a, commitment_update.commitment_signed, false);
+ } else {
+ node_b.node.handle_commitment_signed(&node_a.node.get_our_node_id(), &commitment_update.commitment_signed).unwrap();
+ check_added_monitors!(node_b, 1);
+ let bs_revoke_and_ack = get_event_msg!(node_b, MessageSendEvent::SendRevokeAndACK, node_a.node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ node_a.node.handle_revoke_and_ack(&node_b.node.get_our_node_id(), &bs_revoke_and_ack).unwrap();
+ assert!(node_a.node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(node_a, 1);
+ }
+ } else {
+ assert!(chan_msgs.2.is_none());
+ }
+ }
+ }
+
+ #[test]
+ fn test_simple_peer_disconnect() {
+ // Test that we can reconnect when there are no lost messages
+ let nodes = create_network(3);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+ create_announced_chan_between_nodes(&nodes, 1, 2);
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0;
+ let payment_hash_2 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
+ fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_2);
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_1);
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0;
+ let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).0;
+ let payment_hash_5 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
+ let payment_hash_6 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 1000000).1;
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+ claim_payment_along_route(&nodes[0], &vec!(&nodes[1], &nodes[2]), true, payment_preimage_3);
+ fail_payment_along_route(&nodes[0], &[&nodes[1], &nodes[2]], true, payment_hash_5);
+
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (1, 0), (1, 0), (false, false));
+ {
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 2);
+ match events[0] {
+ Event::PaymentSent { payment_preimage } => {
+ assert_eq!(payment_preimage, payment_preimage_3);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ match events[1] {
+ Event::PaymentFailed { payment_hash, rejected_by_dest } => {
+ assert_eq!(payment_hash, payment_hash_5);
+ assert!(rejected_by_dest);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ }
+
+ claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_preimage_4);
+ fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), payment_hash_6);
+ }
+
+ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8) {
+ // Test that we can reconnect when in-flight HTLC updates get dropped
+ let mut nodes = create_network(2);
+ if messages_delivered == 0 {
+ create_chan_between_nodes_with_value_a(&nodes[0], &nodes[1], 100000, 10001);
+ // nodes[1] doesn't receive the funding_locked message (it'll be re-sent on reconnect)
+ } else {
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+ }
+
+ let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), Some(&nodes[0].node.list_usable_channels()), &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+
+ let payment_event = {
+ nodes[0].node.send_payment(route.clone(), payment_hash_1).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 1);
+ SendEvent::from_event(events.remove(0))
+ };
+ assert_eq!(nodes[1].node.get_our_node_id(), payment_event.node_id);
+
+ if messages_delivered < 2 {
+ // Drop the payment_event messages, and let them get re-generated in reconnect_nodes!
+ } else {
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]).unwrap();
+ if messages_delivered >= 3 {
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg).unwrap();
+ check_added_monitors!(nodes[1], 1);
+ let (bs_revoke_and_ack, bs_commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+
+ if messages_delivered >= 4 {
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_revoke_and_ack).unwrap();
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[0], 1);
+
+ if messages_delivered >= 5 {
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_commitment_signed).unwrap();
+ let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[0], 1);
+
+ if messages_delivered >= 6 {
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_revoke_and_ack).unwrap();
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[1], 1);
+ }
+ }
+ }
+ }
+ }
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ if messages_delivered < 3 {
+ // Even if the funding_locked messages get exchanged, as long as nothing further was
+ // received on either side, both sides will need to resend them.
+ reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 1), (0, 0), (0, 0), (0, 0), (false, false));
+ } else if messages_delivered == 3 {
+ // nodes[0] still wants its RAA + commitment_signed
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (-1, 0), (0, 0), (0, 0), (0, 0), (true, false));
+ } else if messages_delivered == 4 {
+ // nodes[0] still wants its commitment_signed
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (-1, 0), (0, 0), (0, 0), (0, 0), (false, false));
+ } else if messages_delivered == 5 {
+ // nodes[1] still wants its final RAA
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, true));
+ } else if messages_delivered == 6 {
+ // Everything was delivered...
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+ }
+
+ let events_1 = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events_1.len(), 1);
+ match events_1[0] {
+ Event::PendingHTLCsForwardable { .. } => { },
+ _ => panic!("Unexpected event"),
+ };
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ nodes[1].node.channel_state.lock().unwrap().next_forward = Instant::now();
+ nodes[1].node.process_pending_htlc_forwards();
+
+ let events_2 = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events_2.len(), 1);
+ match events_2[0] {
+ Event::PaymentReceived { ref payment_hash, amt } => {
+ assert_eq!(payment_hash_1, *payment_hash);
+ assert_eq!(amt, 1000000);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ nodes[1].node.claim_funds(payment_preimage_1);
+ check_added_monitors!(nodes[1], 1);
+
+ let events_3 = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_3.len(), 1);
+ let (update_fulfill_htlc, commitment_signed) = match events_3[0] {
+ MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => {
+ assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fail_htlcs.is_empty());
+ assert_eq!(updates.update_fulfill_htlcs.len(), 1);
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ (updates.update_fulfill_htlcs[0].clone(), updates.commitment_signed.clone())
+ },
+ _ => panic!("Unexpected event"),
+ };
+
+ if messages_delivered >= 1 {
+ nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_fulfill_htlc).unwrap();
+
+ let events_4 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_4.len(), 1);
+ match events_4[0] {
+ Event::PaymentSent { ref payment_preimage } => {
+ assert_eq!(payment_preimage_1, *payment_preimage);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ if messages_delivered >= 2 {
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &commitment_signed).unwrap();
+ check_added_monitors!(nodes[0], 1);
+ let (as_revoke_and_ack, as_commitment_signed) = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+
+ if messages_delivered >= 3 {
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_revoke_and_ack).unwrap();
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[1], 1);
+
+ if messages_delivered >= 4 {
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_commitment_signed).unwrap();
+ let bs_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[1], 1);
+
+ if messages_delivered >= 5 {
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_revoke_and_ack).unwrap();
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[0], 1);
+ }
+ }
+ }
+ }
+ }
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ if messages_delivered < 2 {
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (1, 0), (0, 0), (0, 0), (false, false));
+ //TODO: Deduplicate PaymentSent events, then enable this if:
+ //if messages_delivered < 1 {
+ let events_4 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_4.len(), 1);
+ match events_4[0] {
+ Event::PaymentSent { ref payment_preimage } => {
+ assert_eq!(payment_preimage_1, *payment_preimage);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ //}
+ } else if messages_delivered == 2 {
+ // nodes[0] still wants its RAA + commitment_signed
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, -1), (0, 0), (0, 0), (0, 0), (false, true));
+ } else if messages_delivered == 3 {
+ // nodes[0] still wants its commitment_signed
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, -1), (0, 0), (0, 0), (0, 0), (false, false));
+ } else if messages_delivered == 4 {
+ // nodes[1] still wants its final RAA
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (true, false));
+ } else if messages_delivered == 5 {
+ // Everything was delivered...
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+ }
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ // Channel should still work fine...
+ let payment_preimage_2 = send_along_route(&nodes[0], route, &[&nodes[1]], 1000000).0;
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
+ }
+
+ #[test]
+ fn test_drop_messages_peer_disconnect_a() {
+ do_test_drop_messages_peer_disconnect(0);
+ do_test_drop_messages_peer_disconnect(1);
+ do_test_drop_messages_peer_disconnect(2);
+ do_test_drop_messages_peer_disconnect(3);
+ }
+
+ #[test]
+ fn test_drop_messages_peer_disconnect_b() {
+ do_test_drop_messages_peer_disconnect(4);
+ do_test_drop_messages_peer_disconnect(5);
+ do_test_drop_messages_peer_disconnect(6);
+ }
+
+ #[test]
+ fn test_funding_peer_disconnect() {
+ // Test that we can lock in our funding tx while disconnected
+ let nodes = create_network(2);
+ let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001);
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+ confirm_transaction(&nodes[0].chain_monitor, &tx, tx.version);
+ let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_1.len(), 1);
+ match events_1[0] {
+ MessageSendEvent::SendFundingLocked { ref node_id, msg: _ } => {
+ assert_eq!(*node_id, nodes[1].node.get_our_node_id());
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ reconnect_nodes(&nodes[0], &nodes[1], (false, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+ confirm_transaction(&nodes[1].chain_monitor, &tx, tx.version);
+ let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_2.len(), 2);
+ match events_2[0] {
+ MessageSendEvent::SendFundingLocked { ref node_id, msg: _ } => {
+ assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+ },
+ _ => panic!("Unexpected event"),
+ }
+ match events_2[1] {
+ MessageSendEvent::SendAnnouncementSignatures { ref node_id, msg: _ } => {
+ assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ // TODO: We shouldn't need to manually pass list_usable_chanels here once we support
+ // rebroadcasting announcement_signatures upon reconnect.
+
+ let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), Some(&nodes[0].node.list_usable_channels()), &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ let (payment_preimage, _) = send_along_route(&nodes[0], route, &[&nodes[1]], 1000000);
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
+ }
+
+ #[test]
+ fn test_drop_messages_peer_disconnect_dual_htlc() {
+ // Test that we can handle reconnecting when both sides of a channel have pending
+ // commitment_updates when we disconnect.
+ let mut nodes = create_network(2);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+
+ // Now try to send a second payment which will fail to send
+ let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+
+ nodes[0].node.send_payment(route.clone(), payment_hash_2).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_1.len(), 1);
+ match events_1[0] {
+ MessageSendEvent::UpdateHTLCs { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+
+ assert!(nodes[1].node.claim_funds(payment_preimage_1));
+ check_added_monitors!(nodes[1], 1);
+
+ let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_2.len(), 1);
+ match events_2[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_eq!(*node_id, nodes[0].node.get_our_node_id());
+ 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());
+
+ nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_fulfill_htlcs[0]).unwrap();
+ let events_3 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_3.len(), 1);
+ match events_3[0] {
+ Event::PaymentSent { ref payment_preimage } => {
+ assert_eq!(*payment_preimage, payment_preimage_1);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed).unwrap();
+ let _ = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[0], 1);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+ let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
+ assert_eq!(reestablish_1.len(), 1);
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+ let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
+ assert_eq!(reestablish_2.len(), 1);
+
+ nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]).unwrap();
+ let as_resp = handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
+ nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]).unwrap();
+ let bs_resp = handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
+
+ assert!(as_resp.0.is_none());
+ assert!(bs_resp.0.is_none());
+
+ assert!(bs_resp.1.is_none());
+ assert!(bs_resp.2.is_none());
+
+ assert!(as_resp.3 == RAACommitmentOrder::CommitmentFirst);
+
+ assert_eq!(as_resp.2.as_ref().unwrap().update_add_htlcs.len(), 1);
+ assert!(as_resp.2.as_ref().unwrap().update_fulfill_htlcs.is_empty());
+ assert!(as_resp.2.as_ref().unwrap().update_fail_htlcs.is_empty());
+ assert!(as_resp.2.as_ref().unwrap().update_fail_malformed_htlcs.is_empty());
+ assert!(as_resp.2.as_ref().unwrap().update_fee.is_none());
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &as_resp.2.as_ref().unwrap().update_add_htlcs[0]).unwrap();
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_resp.2.as_ref().unwrap().commitment_signed).unwrap();
+ let bs_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[1], 1);
+
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), as_resp.1.as_ref().unwrap()).unwrap();
+ let bs_second_commitment_signed = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ assert!(bs_second_commitment_signed.update_add_htlcs.is_empty());
+ assert!(bs_second_commitment_signed.update_fulfill_htlcs.is_empty());
+ assert!(bs_second_commitment_signed.update_fail_htlcs.is_empty());
+ assert!(bs_second_commitment_signed.update_fail_malformed_htlcs.is_empty());
+ assert!(bs_second_commitment_signed.update_fee.is_none());
+ check_added_monitors!(nodes[1], 1);
+
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_revoke_and_ack).unwrap();
+ let as_commitment_signed = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+ assert!(as_commitment_signed.update_add_htlcs.is_empty());
+ assert!(as_commitment_signed.update_fulfill_htlcs.is_empty());
+ assert!(as_commitment_signed.update_fail_htlcs.is_empty());
+ assert!(as_commitment_signed.update_fail_malformed_htlcs.is_empty());
+ assert!(as_commitment_signed.update_fee.is_none());
+ check_added_monitors!(nodes[0], 1);
+
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_commitment_signed.commitment_signed).unwrap();
+ let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[0], 1);
+
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_commitment_signed.commitment_signed).unwrap();
+ let bs_second_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[1], 1);
+
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_revoke_and_ack).unwrap();
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[1], 1);
+
+ let events_4 = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events_4.len(), 1);
+ match events_4[0] {
+ Event::PendingHTLCsForwardable { .. } => { },
+ _ => panic!("Unexpected event"),
+ };
+
+ nodes[1].node.channel_state.lock().unwrap().next_forward = Instant::now();
+ nodes[1].node.process_pending_htlc_forwards();
+
+ let events_5 = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events_5.len(), 1);
+ match events_5[0] {
+ Event::PaymentReceived { ref payment_hash, amt: _ } => {
+ assert_eq!(payment_hash_2, *payment_hash);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_revoke_and_ack).unwrap();
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[0], 1);
+
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
+ }
+
+ #[test]
+ fn test_simple_monitor_permanent_update_fail() {
+ // Test that we handle a simple permanent monitor update failure
+ let mut nodes = create_network(2);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ let (_, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::PermanentFailure);
+ if let Err(APIError::ChannelUnavailable {..}) = nodes[0].node.send_payment(route, payment_hash_1) {} else { panic!(); }
+ check_added_monitors!(nodes[0], 1);
+
+ let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_1.len(), 2);
+ match events_1[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ };
+ match events_1[1] {
+ MessageSendEvent::HandleError { node_id, .. } => assert_eq!(node_id, nodes[1].node.get_our_node_id()),
+ _ => panic!("Unexpected event"),
+ };
+
+ // TODO: Once we hit the chain with the failure transaction we should check that we get a
+ // PaymentFailed event
+
+ assert_eq!(nodes[0].node.list_channels().len(), 0);
+ }
+
+ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
+ // Test that we can recover from a simple temporary monitor update failure optionally with
+ // a disconnect in between
+ let mut nodes = create_network(2);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
+ if let Err(APIError::MonitorUpdateFailed) = nodes[0].node.send_payment(route.clone(), payment_hash_1) {} else { panic!(); }
+ check_added_monitors!(nodes[0], 1);
+
+ assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+ assert_eq!(nodes[0].node.list_channels().len(), 1);
+
+ if disconnect {
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+ }
+
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
+ nodes[0].node.test_restore_channel_monitor();
+ check_added_monitors!(nodes[0], 1);
+
+ let mut events_2 = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_2.len(), 1);
+ let payment_event = SendEvent::from_event(events_2.pop().unwrap());
+ assert_eq!(payment_event.node_id, nodes[1].node.get_our_node_id());
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]).unwrap();
+ commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+
+ expect_pending_htlcs_forwardable!(nodes[1]);
+
+ let events_3 = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events_3.len(), 1);
+ match events_3[0] {
+ Event::PaymentReceived { ref payment_hash, amt } => {
+ assert_eq!(payment_hash_1, *payment_hash);
+ assert_eq!(amt, 1000000);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_1);
+
+ // Now set it to failed again...
+ let (_, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
+ if let Err(APIError::MonitorUpdateFailed) = nodes[0].node.send_payment(route, payment_hash_2) {} else { panic!(); }
+ check_added_monitors!(nodes[0], 1);
+
+ assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+ assert_eq!(nodes[0].node.list_channels().len(), 1);
+
+ if disconnect {
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+ }
+
+ // ...and make sure we can force-close a TemporaryFailure channel with a PermanentFailure
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::PermanentFailure);
+ nodes[0].node.test_restore_channel_monitor();
+ check_added_monitors!(nodes[0], 1);
+
+ let events_5 = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_5.len(), 1);
+ match events_5[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+
+ // TODO: Once we hit the chain with the failure transaction we should check that we get a
+ // PaymentFailed event
+
+ assert_eq!(nodes[0].node.list_channels().len(), 0);
+ }
+
+ #[test]
+ fn test_simple_monitor_temporary_update_fail() {
+ do_test_simple_monitor_temporary_update_fail(false);
+ do_test_simple_monitor_temporary_update_fail(true);
+ }
+
+ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
+ let disconnect_flags = 8 | 16;
+
+ // Test that we can recover from a temporary monitor update failure with some in-flight
+ // HTLCs going on at the same time potentially with some disconnection thrown in.
+ // * First we route a payment, then get a temporary monitor update failure when trying to
+ // route a second payment. We then claim the first payment.
+ // * If disconnect_count is set, we will disconnect at this point (which is likely as
+ // TemporaryFailure likely indicates net disconnect which resulted in failing to update
+ // the ChannelMonitor on a watchtower).
+ // * If !(disconnect_count & 16) we deliver a update_fulfill_htlc/CS for the first payment
+ // immediately, otherwise we wait sconnect and deliver them via the reconnect
+ // channel_reestablish processing (ie disconnect_count & 16 makes no sense if
+ // disconnect_count & !disconnect_flags is 0).
+ // * We then update the channel monitor, reconnecting if disconnect_count is set and walk
+ // through message sending, potentially disconnect/reconnecting multiple times based on
+ // disconnect_count, to get the update_fulfill_htlc through.
+ // * We then walk through more message exchanges to get the original update_add_htlc
+ // through, swapping message ordering based on disconnect_count & 8 and optionally
+ // disconnect/reconnecting based on disconnect_count.
+ let mut nodes = create_network(2);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+
+ // Now try to send a second payment which will fail to send
+ let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
+ if let Err(APIError::MonitorUpdateFailed) = nodes[0].node.send_payment(route.clone(), payment_hash_2) {} else { panic!(); }
+ check_added_monitors!(nodes[0], 1);
+
+ assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+ assert_eq!(nodes[0].node.list_channels().len(), 1);
+
+ // Claim the previous payment, which will result in a update_fulfill_htlc/CS from nodes[1]
+ // but nodes[0] won't respond since it is frozen.
+ assert!(nodes[1].node.claim_funds(payment_preimage_1));
+ check_added_monitors!(nodes[1], 1);
+ let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_2.len(), 1);
+ let (bs_initial_fulfill, bs_initial_commitment_signed) = match events_2[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_eq!(*node_id, nodes[0].node.get_our_node_id());
+ 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());
+
+ if (disconnect_count & 16) == 0 {
+ nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_fulfill_htlcs[0]).unwrap();
+ let events_3 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_3.len(), 1);
+ match events_3[0] {
+ Event::PaymentSent { ref payment_preimage } => {
+ assert_eq!(*payment_preimage, payment_preimage_1);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ if let Err(msgs::HandleError{err, action: Some(msgs::ErrorAction::IgnoreError) }) = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed) {
+ assert_eq!(err, "Previous monitor update failure prevented generation of RAA");
+ } else { panic!(); }
+ }
+
+ (update_fulfill_htlcs[0].clone(), commitment_signed.clone())
+ },
+ _ => panic!("Unexpected event"),
+ };
+
+ if disconnect_count & !disconnect_flags > 0 {
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ }
+
+ // Now fix monitor updating...
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
+ nodes[0].node.test_restore_channel_monitor();
+ check_added_monitors!(nodes[0], 1);
+
+ macro_rules! disconnect_reconnect_peers { () => { {
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+ let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
+ assert_eq!(reestablish_1.len(), 1);
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+ let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
+ assert_eq!(reestablish_2.len(), 1);
+
+ nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]).unwrap();
+ let as_resp = handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
+ nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]).unwrap();
+ let bs_resp = handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
+
+ assert!(as_resp.0.is_none());
+ assert!(bs_resp.0.is_none());
+
+ (reestablish_1, reestablish_2, as_resp, bs_resp)
+ } } }
+
+ let (payment_event, initial_revoke_and_ack) = if disconnect_count & !disconnect_flags > 0 {
+ assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+ let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
+ assert_eq!(reestablish_1.len(), 1);
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+ let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
+ assert_eq!(reestablish_2.len(), 1);
+
+ nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]).unwrap();
+ check_added_monitors!(nodes[0], 0);
+ let mut as_resp = handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
+ nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]).unwrap();
+ check_added_monitors!(nodes[1], 0);
+ let mut bs_resp = handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
+
+ assert!(as_resp.0.is_none());
+ assert!(bs_resp.0.is_none());
+
+ assert!(bs_resp.1.is_none());
+ if (disconnect_count & 16) == 0 {
+ assert!(bs_resp.2.is_none());
+
+ assert!(as_resp.1.is_some());
+ assert!(as_resp.2.is_some());
+ assert!(as_resp.3 == RAACommitmentOrder::CommitmentFirst);
+ } else {
+ assert!(bs_resp.2.as_ref().unwrap().update_add_htlcs.is_empty());
+ assert!(bs_resp.2.as_ref().unwrap().update_fail_htlcs.is_empty());
+ assert!(bs_resp.2.as_ref().unwrap().update_fail_malformed_htlcs.is_empty());
+ assert!(bs_resp.2.as_ref().unwrap().update_fee.is_none());
+ assert!(bs_resp.2.as_ref().unwrap().update_fulfill_htlcs == vec![bs_initial_fulfill]);
+ assert!(bs_resp.2.as_ref().unwrap().commitment_signed == bs_initial_commitment_signed);
+
+ assert!(as_resp.1.is_none());
+
+ nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_resp.2.as_ref().unwrap().update_fulfill_htlcs[0]).unwrap();
+ let events_3 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_3.len(), 1);
+ match events_3[0] {
+ Event::PaymentSent { ref payment_preimage } => {
+ assert_eq!(*payment_preimage, payment_preimage_1);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_resp.2.as_ref().unwrap().commitment_signed).unwrap();
+ let as_resp_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[0], 1);
+
+ as_resp.1 = Some(as_resp_raa);
+ bs_resp.2 = None;
+ }
+
+ if disconnect_count & !disconnect_flags > 1 {
+ let (second_reestablish_1, second_reestablish_2, second_as_resp, second_bs_resp) = disconnect_reconnect_peers!();
+
+ if (disconnect_count & 16) == 0 {
+ assert!(reestablish_1 == second_reestablish_1);
+ assert!(reestablish_2 == second_reestablish_2);
+ }
+ assert!(as_resp == second_as_resp);
+ assert!(bs_resp == second_bs_resp);
+ }
+
+ (SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), as_resp.2.unwrap()), as_resp.1.unwrap())
+ } else {
+ let mut events_4 = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_4.len(), 2);
+ (SendEvent::from_event(events_4.remove(0)), match events_4[0] {
+ MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
+ assert_eq!(*node_id, nodes[1].node.get_our_node_id());
+ msg.clone()
+ },
+ _ => panic!("Unexpected event"),
+ })
+ };
+
+ assert_eq!(payment_event.node_id, nodes[1].node.get_our_node_id());
+
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]).unwrap();
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg).unwrap();
+ let bs_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+ // nodes[1] is awaiting an RAA from nodes[0] still so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[1], 1);
+
+ if disconnect_count & !disconnect_flags > 2 {
+ let (_, _, as_resp, bs_resp) = disconnect_reconnect_peers!();
+
+ assert!(as_resp.1.unwrap() == initial_revoke_and_ack);
+ assert!(bs_resp.1.unwrap() == bs_revoke_and_ack);
+
+ assert!(as_resp.2.is_none());
+ assert!(bs_resp.2.is_none());
+ }
+
+ let as_commitment_update;
+ let bs_second_commitment_update;
+
+ macro_rules! handle_bs_raa { () => {
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_revoke_and_ack).unwrap();
+ as_commitment_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
+ assert!(as_commitment_update.update_add_htlcs.is_empty());
+ assert!(as_commitment_update.update_fulfill_htlcs.is_empty());
+ assert!(as_commitment_update.update_fail_htlcs.is_empty());
+ assert!(as_commitment_update.update_fail_malformed_htlcs.is_empty());
+ assert!(as_commitment_update.update_fee.is_none());
+ check_added_monitors!(nodes[0], 1);
+ } }
+
+ macro_rules! handle_initial_raa { () => {
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &initial_revoke_and_ack).unwrap();
+ bs_second_commitment_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ assert!(bs_second_commitment_update.update_add_htlcs.is_empty());
+ assert!(bs_second_commitment_update.update_fulfill_htlcs.is_empty());
+ assert!(bs_second_commitment_update.update_fail_htlcs.is_empty());
+ assert!(bs_second_commitment_update.update_fail_malformed_htlcs.is_empty());
+ assert!(bs_second_commitment_update.update_fee.is_none());
+ check_added_monitors!(nodes[1], 1);
+ } }
+
+ if (disconnect_count & 8) == 0 {
+ handle_bs_raa!();
+
+ if disconnect_count & !disconnect_flags > 3 {
+ let (_, _, as_resp, bs_resp) = disconnect_reconnect_peers!();
+
+ assert!(as_resp.1.unwrap() == initial_revoke_and_ack);
+ assert!(bs_resp.1.is_none());
+
+ assert!(as_resp.2.unwrap() == as_commitment_update);
+ assert!(bs_resp.2.is_none());
+
+ assert!(as_resp.3 == RAACommitmentOrder::RevokeAndACKFirst);
+ }
+
+ handle_initial_raa!();
+
+ if disconnect_count & !disconnect_flags > 4 {
+ let (_, _, as_resp, bs_resp) = disconnect_reconnect_peers!();
+
+ assert!(as_resp.1.is_none());
+ assert!(bs_resp.1.is_none());
+
+ assert!(as_resp.2.unwrap() == as_commitment_update);
+ assert!(bs_resp.2.unwrap() == bs_second_commitment_update);
+ }
+ } else {
+ handle_initial_raa!();
+
+ if disconnect_count & !disconnect_flags > 3 {
+ let (_, _, as_resp, bs_resp) = disconnect_reconnect_peers!();
+
+ assert!(as_resp.1.is_none());
+ assert!(bs_resp.1.unwrap() == bs_revoke_and_ack);
+
+ assert!(as_resp.2.is_none());
+ assert!(bs_resp.2.unwrap() == bs_second_commitment_update);
+
+ assert!(bs_resp.3 == RAACommitmentOrder::RevokeAndACKFirst);
+ }
+
+ handle_bs_raa!();
+
+ if disconnect_count & !disconnect_flags > 4 {
+ let (_, _, as_resp, bs_resp) = disconnect_reconnect_peers!();
+
+ assert!(as_resp.1.is_none());
+ assert!(bs_resp.1.is_none());
+
+ assert!(as_resp.2.unwrap() == as_commitment_update);
+ assert!(bs_resp.2.unwrap() == bs_second_commitment_update);
+ }
+ }
+
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bs_second_commitment_update.commitment_signed).unwrap();
+ let as_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[0], 1);
+
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_commitment_update.commitment_signed).unwrap();
+ let bs_second_revoke_and_ack = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[0].node.get_our_node_id());
+ // No commitment_signed so get_event_msg's assert(len == 1) passes
+ check_added_monitors!(nodes[1], 1);
+
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_revoke_and_ack).unwrap();
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[1], 1);
+
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_second_revoke_and_ack).unwrap();
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[0], 1);
+
+ expect_pending_htlcs_forwardable!(nodes[1]);
+
+ let events_5 = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events_5.len(), 1);
+ match events_5[0] {
+ Event::PaymentReceived { ref payment_hash, amt } => {
+ assert_eq!(payment_hash_2, *payment_hash);
+ assert_eq!(amt, 1000000);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_2);
+ }
+
+ #[test]
+ fn test_monitor_temporary_update_fail_a() {
+ do_test_monitor_temporary_update_fail(0);
+ do_test_monitor_temporary_update_fail(1);
+ do_test_monitor_temporary_update_fail(2);
+ do_test_monitor_temporary_update_fail(3);
+ do_test_monitor_temporary_update_fail(4);
+ do_test_monitor_temporary_update_fail(5);
+ }
+
+ #[test]
+ fn test_monitor_temporary_update_fail_b() {
+ do_test_monitor_temporary_update_fail(2 | 8);
+ do_test_monitor_temporary_update_fail(3 | 8);
+ do_test_monitor_temporary_update_fail(4 | 8);
+ do_test_monitor_temporary_update_fail(5 | 8);
+ }
+
+ #[test]
+ fn test_monitor_temporary_update_fail_c() {
+ do_test_monitor_temporary_update_fail(1 | 16);
+ do_test_monitor_temporary_update_fail(2 | 16);
+ do_test_monitor_temporary_update_fail(3 | 16);
+ do_test_monitor_temporary_update_fail(2 | 8 | 16);
+ do_test_monitor_temporary_update_fail(3 | 8 | 16);
+ }
+
+ #[test]
+ fn test_monitor_update_fail_cs() {
+ // Tests handling of a monitor update failure when processing an incoming commitment_signed
+ let mut nodes = create_network(2);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ let (payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ nodes[0].node.send_payment(route, our_payment_hash).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]).unwrap();
+
+ *nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
+ if let msgs::HandleError { err, action: Some(msgs::ErrorAction::IgnoreError) } = nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &send_event.commitment_msg).unwrap_err() {
+ assert_eq!(err, "Failed to update ChannelMonitor");
+ } else { panic!(); }
+ check_added_monitors!(nodes[1], 1);
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+
+ *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
+ nodes[1].node.test_restore_channel_monitor();
+ check_added_monitors!(nodes[1], 1);
+ let responses = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(responses.len(), 2);
+
+ match responses[0] {
+ MessageSendEvent::SendRevokeAndACK { ref msg, ref node_id } => {
+ assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &msg).unwrap();
+ check_added_monitors!(nodes[0], 1);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ match responses[1] {
+ MessageSendEvent::UpdateHTLCs { ref updates, ref node_id } => {
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert!(updates.update_fail_htlcs.is_empty());
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
+ if let msgs::HandleError { err, action: Some(msgs::ErrorAction::IgnoreError) } = nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &updates.commitment_signed).unwrap_err() {
+ assert_eq!(err, "Failed to update ChannelMonitor");
+ } else { panic!(); }
+ check_added_monitors!(nodes[0], 1);
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
+ nodes[0].node.test_restore_channel_monitor();
+ check_added_monitors!(nodes[0], 1);
+
+ let final_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &final_raa).unwrap();
+ check_added_monitors!(nodes[1], 1);
+
+ let mut events = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PendingHTLCsForwardable { .. } => { },
+ _ => panic!("Unexpected event"),
+ };
+ nodes[1].node.channel_state.lock().unwrap().next_forward = Instant::now();
+ nodes[1].node.process_pending_htlc_forwards();
+
+ events = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PaymentReceived { payment_hash, amt } => {
+ assert_eq!(payment_hash, our_payment_hash);
+ assert_eq!(amt, 1000000);
+ },
+ _ => panic!("Unexpected event"),
+ };
+
+ claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
+ }
+
+ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
+ // Tests handling of a monitor update failure when processing an incoming RAA
+ let mut nodes = create_network(3);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+ create_announced_chan_between_nodes(&nodes, 1, 2);
+
+ // Rebalance a bit so that we can send backwards from 2 to 1.
+ send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 5000000);
+
+ // Route a first payment that we'll fail backwards
+ let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
+
+ // Fail the payment backwards, failing the monitor update on nodes[1]'s receipt of the RAA
+ assert!(nodes[2].node.fail_htlc_backwards(&payment_hash_1, PaymentFailReason::PreimageUnknown));
+ check_added_monitors!(nodes[2], 1);
+
+ let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert_eq!(updates.update_fail_htlcs.len(), 1);
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ nodes[1].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]).unwrap();
+
+ let bs_revoke_and_ack = commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true, false, true);
+ check_added_monitors!(nodes[0], 0);
+
+ // While the second channel is AwaitingRAA, forward a second payment to get it into the
+ // holding cell.
+ let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let route = nodes[0].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ nodes[0].node.send_payment(route, payment_hash_2).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let mut send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]).unwrap();
+ commitment_signed_dance!(nodes[1], nodes[0], send_event.commitment_msg, false);
+
+ let events_1 = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events_1.len(), 1);
+ match events_1[0] {
+ Event::PendingHTLCsForwardable { .. } => { },
+ _ => panic!("Unexpected event"),
+ };
+
+ nodes[1].node.channel_state.lock().unwrap().next_forward = Instant::now();
+ nodes[1].node.process_pending_htlc_forwards();
+ check_added_monitors!(nodes[1], 0);
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+
+ // Now fail monitor updating.
+ *nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
+ if let msgs::HandleError { err, action: Some(msgs::ErrorAction::IgnoreError) } = nodes[1].node.handle_revoke_and_ack(&nodes[2].node.get_our_node_id(), &bs_revoke_and_ack).unwrap_err() {
+ assert_eq!(err, "Failed to update ChannelMonitor");
+ } else { panic!(); }
+ assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ check_added_monitors!(nodes[1], 1);
+
+ // Attempt to forward a third payment but fail due to the second channel being unavailable
+ // for forwarding.
+
+ let (_, payment_hash_3) = get_payment_preimage_hash!(nodes[0]);
+ let route = nodes[0].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ nodes[0].node.send_payment(route, payment_hash_3).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); // We succeed in updating the monitor for the first channel
+ send_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &send_event.msgs[0]).unwrap();
+ commitment_signed_dance!(nodes[1], nodes[0], send_event.commitment_msg, false, true);
+ check_added_monitors!(nodes[1], 0);
+
+ let mut events_2 = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(events_2.len(), 1);
+ match events_2.remove(0) {
+ MessageSendEvent::UpdateHTLCs { node_id, updates } => {
+ assert_eq!(node_id, nodes[0].node.get_our_node_id());
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert_eq!(updates.update_fail_htlcs.len(), 1);
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+
+ nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]).unwrap();
+ commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false);
+
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ if let Event::PaymentFailed { payment_hash, rejected_by_dest } = events[0] {
+ assert_eq!(payment_hash, payment_hash_3);
+ assert!(!rejected_by_dest);
+ } else { panic!("Unexpected event!"); }
+ },
+ _ => panic!("Unexpected event type!"),
+ };
+
+ let (payment_preimage_4, payment_hash_4) = if test_ignore_second_cs {
+ // Try to route another payment backwards from 2 to make sure 1 holds off on responding
+ let (payment_preimage_4, payment_hash_4) = get_payment_preimage_hash!(nodes[0]);
+ let route = nodes[2].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
+ nodes[2].node.send_payment(route, payment_hash_4).unwrap();
+ check_added_monitors!(nodes[2], 1);
+
+ send_event = SendEvent::from_event(nodes[2].node.get_and_clear_pending_msg_events().remove(0));
+ nodes[1].node.handle_update_add_htlc(&nodes[2].node.get_our_node_id(), &send_event.msgs[0]).unwrap();
+ if let Err(msgs::HandleError{err, action: Some(msgs::ErrorAction::IgnoreError) }) = nodes[1].node.handle_commitment_signed(&nodes[2].node.get_our_node_id(), &send_event.commitment_msg) {
+ assert_eq!(err, "Previous monitor update failure prevented generation of RAA");
+ } else { panic!(); }
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
+ (Some(payment_preimage_4), Some(payment_hash_4))
+ } else { (None, None) };
+
+ // Restore monitor updating, ensuring we immediately get a fail-back update and a
+ // update_add update.
+ *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
+ nodes[1].node.test_restore_channel_monitor();
+ check_added_monitors!(nodes[1], 2);
+
+ let mut events_3 = nodes[1].node.get_and_clear_pending_msg_events();
+ if test_ignore_second_cs {
+ assert_eq!(events_3.len(), 3);
+ } else {
+ assert_eq!(events_3.len(), 2);
+ }
+
+ // Note that the ordering of the events for different nodes is non-prescriptive, though the
+ // ordering of the two events that both go to nodes[2] have to stay in the same order.
+ let messages_a = match events_3.pop().unwrap() {
+ MessageSendEvent::UpdateHTLCs { node_id, mut updates } => {
+ assert_eq!(node_id, nodes[0].node.get_our_node_id());
+ assert!(updates.update_fulfill_htlcs.is_empty());
+ assert_eq!(updates.update_fail_htlcs.len(), 1);
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ (updates.update_fail_htlcs.remove(0), updates.commitment_signed)
+ },
+ _ => panic!("Unexpected event type!"),
+ };
+ let raa = if test_ignore_second_cs {
+ match events_3.remove(1) {
+ MessageSendEvent::SendRevokeAndACK { node_id, msg } => {
+ assert_eq!(node_id, nodes[2].node.get_our_node_id());
+ Some(msg.clone())
+ },
+ _ => panic!("Unexpected event"),
+ }
+ } else { None };
+ let send_event_b = SendEvent::from_event(events_3.remove(0));
+ assert_eq!(send_event_b.node_id, nodes[2].node.get_our_node_id());
+
+ // Now deliver the new messages...
+
+ nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &messages_a.0).unwrap();
+ commitment_signed_dance!(nodes[0], nodes[1], messages_a.1, false);
+ let events_4 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_4.len(), 1);
+ if let Event::PaymentFailed { payment_hash, rejected_by_dest } = events_4[0] {
+ assert_eq!(payment_hash, payment_hash_1);
+ assert!(rejected_by_dest);
+ } else { panic!("Unexpected event!"); }
+
+ nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &send_event_b.msgs[0]).unwrap();
+ if test_ignore_second_cs {
+ nodes[2].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &send_event_b.commitment_msg).unwrap();
+ check_added_monitors!(nodes[2], 1);
+ let bs_revoke_and_ack = get_event_msg!(nodes[2], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+ nodes[2].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &raa.unwrap()).unwrap();
+ check_added_monitors!(nodes[2], 1);
+ let bs_cs = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
+ assert!(bs_cs.update_add_htlcs.is_empty());
+ assert!(bs_cs.update_fail_htlcs.is_empty());
+ assert!(bs_cs.update_fail_malformed_htlcs.is_empty());
+ assert!(bs_cs.update_fulfill_htlcs.is_empty());
+ assert!(bs_cs.update_fee.is_none());
+
+ nodes[1].node.handle_revoke_and_ack(&nodes[2].node.get_our_node_id(), &bs_revoke_and_ack).unwrap();
+ check_added_monitors!(nodes[1], 1);
+ let as_cs = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id());
+ assert!(as_cs.update_add_htlcs.is_empty());
+ assert!(as_cs.update_fail_htlcs.is_empty());
+ assert!(as_cs.update_fail_malformed_htlcs.is_empty());
+ assert!(as_cs.update_fulfill_htlcs.is_empty());
+ assert!(as_cs.update_fee.is_none());
+
+ nodes[1].node.handle_commitment_signed(&nodes[2].node.get_our_node_id(), &bs_cs.commitment_signed).unwrap();
+ check_added_monitors!(nodes[1], 1);
+ let as_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, nodes[2].node.get_our_node_id());
+
+ nodes[2].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &as_cs.commitment_signed).unwrap();
+ check_added_monitors!(nodes[2], 1);
+ let bs_second_raa = get_event_msg!(nodes[2], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id());
+
+ nodes[2].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &as_raa).unwrap();
+ check_added_monitors!(nodes[2], 1);
+ assert!(nodes[2].node.get_and_clear_pending_msg_events().is_empty());
+
+ nodes[1].node.handle_revoke_and_ack(&nodes[2].node.get_our_node_id(), &bs_second_raa).unwrap();
+ check_added_monitors!(nodes[1], 1);
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ } else {
+ commitment_signed_dance!(nodes[2], nodes[1], send_event_b.commitment_msg, false);
+ }
+
+ let events_5 = nodes[2].node.get_and_clear_pending_events();
+ assert_eq!(events_5.len(), 1);
+ match events_5[0] {
+ Event::PendingHTLCsForwardable { .. } => { },
+ _ => panic!("Unexpected event"),
+ };
+
+ nodes[2].node.channel_state.lock().unwrap().next_forward = Instant::now();
+ nodes[2].node.process_pending_htlc_forwards();
+
+ let events_6 = nodes[2].node.get_and_clear_pending_events();
+ assert_eq!(events_6.len(), 1);
+ match events_6[0] {
+ Event::PaymentReceived { payment_hash, .. } => { assert_eq!(payment_hash, payment_hash_2); },
+ _ => panic!("Unexpected event"),
+ };
+
+ if test_ignore_second_cs {
+ let events_7 = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events_7.len(), 1);
+ match events_7[0] {
+ Event::PendingHTLCsForwardable { .. } => { },
+ _ => panic!("Unexpected event"),
+ };
+
+ nodes[1].node.channel_state.lock().unwrap().next_forward = Instant::now();
+ nodes[1].node.process_pending_htlc_forwards();
+ check_added_monitors!(nodes[1], 1);
+
+ send_event = SendEvent::from_node(&nodes[1]);
+ assert_eq!(send_event.node_id, nodes[0].node.get_our_node_id());
+ assert_eq!(send_event.msgs.len(), 1);
+ nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &send_event.msgs[0]).unwrap();
+ commitment_signed_dance!(nodes[0], nodes[1], send_event.commitment_msg, false);
+
+ let events_8 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_8.len(), 1);
+ match events_8[0] {
+ Event::PendingHTLCsForwardable { .. } => { },
+ _ => panic!("Unexpected event"),
+ };
+
+ nodes[0].node.channel_state.lock().unwrap().next_forward = Instant::now();
+ nodes[0].node.process_pending_htlc_forwards();
+
+ let events_9 = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events_9.len(), 1);
+ match events_9[0] {
+ Event::PaymentReceived { payment_hash, .. } => assert_eq!(payment_hash, payment_hash_4.unwrap()),
+ _ => panic!("Unexpected event"),
+ };
+ claim_payment(&nodes[2], &[&nodes[1], &nodes[0]], payment_preimage_4.unwrap());
+ }
+
+ claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage_2);
+ }
+
+ #[test]
+ fn test_monitor_update_fail_raa() {
+ do_test_monitor_update_fail_raa(false);
+ do_test_monitor_update_fail_raa(true);
+ }
+
+ #[test]
+ fn test_monitor_update_fail_reestablish() {
+ // Simple test for message retransmission after monitor update failure on
+ // channel_reestablish generating a monitor update (which comes from freeing holding cell
+ // HTLCs).
+ let mut nodes = create_network(3);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+ create_announced_chan_between_nodes(&nodes, 1, 2);
+
+ let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
+
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+
+ assert!(nodes[2].node.claim_funds(our_payment_preimage));
+ check_added_monitors!(nodes[2], 1);
+ let mut updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fail_htlcs.is_empty());
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ assert_eq!(updates.update_fulfill_htlcs.len(), 1);
+ nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]).unwrap();
+ check_added_monitors!(nodes[1], 1);
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
+
+ *nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+
+ let as_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
+ let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+
+ nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish).unwrap();
+
+ if let msgs::HandleError { err, action: Some(msgs::ErrorAction::IgnoreError) } = nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reestablish).unwrap_err() {
+ assert_eq!(err, "Failed to update ChannelMonitor");
+ } else { panic!(); }
+ check_added_monitors!(nodes[1], 1);
+
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+
+ assert!(as_reestablish == get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id()));
+ assert!(bs_reestablish == get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id()));
+
+ nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish).unwrap();
+
+ nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reestablish).unwrap();
+ check_added_monitors!(nodes[1], 0);
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+
+ *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(());
+ nodes[1].node.test_restore_channel_monitor();
+ check_added_monitors!(nodes[1], 1);
+
+ updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ assert!(updates.update_add_htlcs.is_empty());
+ assert!(updates.update_fail_htlcs.is_empty());
+ assert!(updates.update_fail_malformed_htlcs.is_empty());
+ assert!(updates.update_fee.is_none());
+ assert_eq!(updates.update_fulfill_htlcs.len(), 1);
+ nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]).unwrap();
+ commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false);
+
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PaymentSent { payment_preimage, .. } => assert_eq!(payment_preimage, our_payment_preimage),
+ _ => panic!("Unexpected event"),
+ }
+ }
+
+ #[test]
+ fn test_invalid_channel_announcement() {
+ //Test BOLT 7 channel_announcement msg requirement for final node, gather data to build customed channel_announcement msgs
+ let secp_ctx = Secp256k1::new();
+ let nodes = create_network(2);
+
+ let chan_announcement = create_chan_between_nodes(&nodes[0], &nodes[1]);
+
+ let a_channel_lock = nodes[0].node.channel_state.lock().unwrap();
+ let b_channel_lock = nodes[1].node.channel_state.lock().unwrap();
+ let as_chan = a_channel_lock.by_id.get(&chan_announcement.3).unwrap();
+ let bs_chan = b_channel_lock.by_id.get(&chan_announcement.3).unwrap();
+
+ let _ = nodes[0].router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id : as_chan.get_short_channel_id().unwrap(), is_permanent: false } );
+
+ let as_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &as_chan.get_local_keys().funding_key);
+ let bs_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &bs_chan.get_local_keys().funding_key);
+
+ let as_network_key = nodes[0].node.get_our_node_id();
+ let bs_network_key = nodes[1].node.get_our_node_id();
+
+ let were_node_one = as_bitcoin_key.serialize()[..] < bs_bitcoin_key.serialize()[..];
+
+ let mut chan_announcement;
+
+ macro_rules! dummy_unsigned_msg {
+ () => {
+ msgs::UnsignedChannelAnnouncement {
+ features: msgs::GlobalFeatures::new(),
+ chain_hash: genesis_block(Network::Testnet).header.bitcoin_hash(),
+ short_channel_id: as_chan.get_short_channel_id().unwrap(),
+ node_id_1: if were_node_one { as_network_key } else { bs_network_key },
+ node_id_2: if were_node_one { bs_network_key } else { as_network_key },
+ bitcoin_key_1: if were_node_one { as_bitcoin_key } else { bs_bitcoin_key },
+ bitcoin_key_2: if were_node_one { bs_bitcoin_key } else { as_bitcoin_key },
+ excess_data: Vec::new(),
+ };
+ }
+ }
+
+ macro_rules! sign_msg {
+ ($unsigned_msg: expr) => {
+ let msghash = Message::from_slice(&Sha256dHash::from_data(&$unsigned_msg.encode()[..])[..]).unwrap();
+ let as_bitcoin_sig = secp_ctx.sign(&msghash, &as_chan.get_local_keys().funding_key);
+ let bs_bitcoin_sig = secp_ctx.sign(&msghash, &bs_chan.get_local_keys().funding_key);
+ let as_node_sig = secp_ctx.sign(&msghash, &nodes[0].node.our_network_key);
+ let bs_node_sig = secp_ctx.sign(&msghash, &nodes[1].node.our_network_key);
+ chan_announcement = msgs::ChannelAnnouncement {
+ node_signature_1 : if were_node_one { as_node_sig } else { bs_node_sig},
+ node_signature_2 : if were_node_one { bs_node_sig } else { as_node_sig},
+ bitcoin_signature_1: if were_node_one { as_bitcoin_sig } else { bs_bitcoin_sig },
+ bitcoin_signature_2 : if were_node_one { bs_bitcoin_sig } else { as_bitcoin_sig },
+ contents: $unsigned_msg
+ }
+ }
+ }
+
+ let unsigned_msg = dummy_unsigned_msg!();
+ sign_msg!(unsigned_msg);
+ assert_eq!(nodes[0].router.handle_channel_announcement(&chan_announcement).unwrap(), true);
+ let _ = nodes[0].router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id : as_chan.get_short_channel_id().unwrap(), is_permanent: false } );
+
+ // Configured with Network::Testnet
+ let mut unsigned_msg = dummy_unsigned_msg!();
+ unsigned_msg.chain_hash = genesis_block(Network::Bitcoin).header.bitcoin_hash();
+ sign_msg!(unsigned_msg);
+ assert!(nodes[0].router.handle_channel_announcement(&chan_announcement).is_err());
+
+ let mut unsigned_msg = dummy_unsigned_msg!();
+ unsigned_msg.chain_hash = Sha256dHash::from_data(&[1,2,3,4,5,6,7,8,9]);
+ sign_msg!(unsigned_msg);
+ assert!(nodes[0].router.handle_channel_announcement(&chan_announcement).is_err());
+ }
+
+ struct VecWriter(Vec<u8>);
+ impl Writer for VecWriter {
+ fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
+ self.0.extend_from_slice(buf);
+ Ok(())
+ }
+ fn size_hint(&mut self, size: usize) {
+ self.0.reserve_exact(size);
+ }
+ }
+
+ #[test]
+ fn test_no_txn_manager_serialize_deserialize() {
+ let mut nodes = create_network(2);
+
+ let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001);
+
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+ let nodes_0_serialized = nodes[0].node.encode();
+ let mut chan_0_monitor_serialized = VecWriter(Vec::new());
+ nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write_for_disk(&mut chan_0_monitor_serialized).unwrap();
+
+ nodes[0].chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone(), Arc::new(test_utils::TestLogger::new())));
+ let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
+ let (_, chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap();
+ assert!(chan_0_monitor_read.is_empty());
+
+ let mut nodes_0_read = &nodes_0_serialized[..];
+ let config = UserConfig::new();
+ let keys_manager = Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
+ let (_, nodes_0_deserialized) = {
+ let mut channel_monitors = HashMap::new();
+ channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor);
+ <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+ default_config: config,
+ keys_manager,
+ fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
+ monitor: nodes[0].chan_monitor.clone(),
+ chain_monitor: nodes[0].chain_monitor.clone(),
+ tx_broadcaster: nodes[0].tx_broadcaster.clone(),
+ logger: Arc::new(test_utils::TestLogger::new()),
+ channel_monitors: &channel_monitors,
+ }).unwrap()
+ };
+ assert!(nodes_0_read.is_empty());
+
+ assert!(nodes[0].chan_monitor.add_update_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
+ nodes[0].node = Arc::new(nodes_0_deserialized);
+ let nodes_0_as_listener: Arc<ChainListener> = nodes[0].node.clone();
+ nodes[0].chain_monitor.register_listener(Arc::downgrade(&nodes_0_as_listener));
+ assert_eq!(nodes[0].node.list_channels().len(), 1);
+ check_added_monitors!(nodes[0], 1);
+
+ nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+ let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
+ nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+ let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
+
+ nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]).unwrap();
+ assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]).unwrap();
+ assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
+
+ let (funding_locked, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
+ let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_locked);
+ for node in nodes.iter() {
+ assert!(node.router.handle_channel_announcement(&announcement).unwrap());
+ node.router.handle_channel_update(&as_update).unwrap();
+ node.router.handle_channel_update(&bs_update).unwrap();
+ }
+
+ send_payment(&nodes[0], &[&nodes[1]], 1000000);
+ }
+
+ #[test]
+ fn test_simple_manager_serialize_deserialize() {
+ let mut nodes = create_network(2);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+ let (_, our_payment_hash) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+ let nodes_0_serialized = nodes[0].node.encode();
+ let mut chan_0_monitor_serialized = VecWriter(Vec::new());
+ nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write_for_disk(&mut chan_0_monitor_serialized).unwrap();
+
+ nodes[0].chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone(), Arc::new(test_utils::TestLogger::new())));
+ let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
+ let (_, chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap();
+ assert!(chan_0_monitor_read.is_empty());
+
+ let mut nodes_0_read = &nodes_0_serialized[..];
+ let keys_manager = Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
+ let (_, nodes_0_deserialized) = {
+ let mut channel_monitors = HashMap::new();
+ channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor);
+ <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+ default_config: UserConfig::new(),
+ keys_manager,
+ fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
+ monitor: nodes[0].chan_monitor.clone(),
+ chain_monitor: nodes[0].chain_monitor.clone(),
+ tx_broadcaster: nodes[0].tx_broadcaster.clone(),
+ logger: Arc::new(test_utils::TestLogger::new()),
+ channel_monitors: &channel_monitors,
+ }).unwrap()
+ };
+ assert!(nodes_0_read.is_empty());
+
+ assert!(nodes[0].chan_monitor.add_update_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
+ nodes[0].node = Arc::new(nodes_0_deserialized);
+ check_added_monitors!(nodes[0], 1);
+
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ fail_payment(&nodes[0], &[&nodes[1]], our_payment_hash);
+ claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage);
+ }
+
+ #[test]
+ fn test_manager_serialize_deserialize_inconsistent_monitor() {
+ // Test deserializing a ChannelManager with a out-of-date ChannelMonitor
+ let mut nodes = create_network(4);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+ create_announced_chan_between_nodes(&nodes, 2, 0);
+ let (_, _, channel_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 3);
+
+ let (our_payment_preimage, _) = route_payment(&nodes[2], &[&nodes[0], &nodes[1]], 1000000);
+
+ // Serialize the ChannelManager here, but the monitor we keep up-to-date
+ let nodes_0_serialized = nodes[0].node.encode();
+
+ route_payment(&nodes[0], &[&nodes[3]], 1000000);
+ nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ nodes[2].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+ nodes[3].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+ // Now the ChannelMonitor (which is now out-of-sync with ChannelManager for channel w/
+ // nodes[3])
+ let mut node_0_monitors_serialized = Vec::new();
+ for monitor in nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap().iter() {
+ let mut writer = VecWriter(Vec::new());
+ monitor.1.write_for_disk(&mut writer).unwrap();
+ node_0_monitors_serialized.push(writer.0);
+ }
+
+ nodes[0].chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone(), Arc::new(test_utils::TestLogger::new())));
+ let mut node_0_monitors = Vec::new();
+ for serialized in node_0_monitors_serialized.iter() {
+ let mut read = &serialized[..];
+ let (_, monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut read, Arc::new(test_utils::TestLogger::new())).unwrap();
+ assert!(read.is_empty());
+ node_0_monitors.push(monitor);
+ }
+
+ let mut nodes_0_read = &nodes_0_serialized[..];
+ let keys_manager = Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
+ let (_, nodes_0_deserialized) = <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+ default_config: UserConfig::new(),
+ keys_manager,
+ fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
+ monitor: nodes[0].chan_monitor.clone(),
+ chain_monitor: nodes[0].chain_monitor.clone(),
+ tx_broadcaster: nodes[0].tx_broadcaster.clone(),
+ logger: Arc::new(test_utils::TestLogger::new()),
+ channel_monitors: &node_0_monitors.iter().map(|monitor| { (monitor.get_funding_txo().unwrap(), monitor) }).collect(),
+ }).unwrap();
+ assert!(nodes_0_read.is_empty());
+
+ { // Channel close should result in a commitment tx and an HTLC tx
+ let txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(txn.len(), 2);
+ assert_eq!(txn[0].input[0].previous_output.txid, funding_tx.txid());
+ assert_eq!(txn[1].input[0].previous_output.txid, txn[0].txid());
+ }
+
+ for monitor in node_0_monitors.drain(..) {
+ assert!(nodes[0].chan_monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor).is_ok());
+ check_added_monitors!(nodes[0], 1);
+ }
+ nodes[0].node = Arc::new(nodes_0_deserialized);
+
+ // nodes[1] and nodes[2] have no lost state with nodes[0]...
+ reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+ reconnect_nodes(&nodes[0], &nodes[2], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+ //... and we can even still claim the payment!
+ claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage);
+
+ nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id());
+ let reestablish = get_event_msg!(nodes[3], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
+ nodes[0].node.peer_connected(&nodes[3].node.get_our_node_id());
+ if let Err(msgs::HandleError { action: Some(msgs::ErrorAction::SendErrorMessage { msg }), .. }) = nodes[0].node.handle_channel_reestablish(&nodes[3].node.get_our_node_id(), &reestablish) {
+ assert_eq!(msg.channel_id, channel_id);
+ } else { panic!("Unexpected result"); }
+ }
+
+ macro_rules! check_spendable_outputs {
+ ($node: expr, $der_idx: expr) => {
+ {
+ let events = $node.chan_monitor.simple_monitor.get_and_clear_pending_events();
+ let mut txn = Vec::new();
+ for event in events {
+ match event {
+ Event::SpendableOutputs { ref outputs } => {
+ for outp in outputs {
+ match *outp {
+ SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
+ let input = TxIn {
+ previous_output: outpoint.clone(),
+ script_sig: Script::new(),
+ sequence: 0,
+ witness: Vec::new(),
+ };
+ let outp = TxOut {
+ script_pubkey: Builder::new().push_opcode(opcodes::All::OP_RETURN).into_script(),
+ value: output.value,
+ };
+ let mut spend_tx = Transaction {
+ version: 2,
+ lock_time: 0,
+ input: vec![input],
+ output: vec![outp],
+ };
+ let secp_ctx = Secp256k1::new();
+ let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &key);
+ let witness_script = Address::p2pkh(&remotepubkey, Network::Testnet).script_pubkey();
+ let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap();
+ let remotesig = secp_ctx.sign(&sighash, key);
+ spend_tx.input[0].witness.push(remotesig.serialize_der(&secp_ctx).to_vec());
+ spend_tx.input[0].witness[0].push(SigHashType::All as u8);
+ spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
+ txn.push(spend_tx);
+ },
+ SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref key, ref witness_script, ref to_self_delay, ref output } => {
+ let input = TxIn {
+ previous_output: outpoint.clone(),
+ script_sig: Script::new(),
+ sequence: *to_self_delay as u32,
+ witness: Vec::new(),
+ };
+ let outp = TxOut {
+ script_pubkey: Builder::new().push_opcode(opcodes::All::OP_RETURN).into_script(),
+ value: output.value,
+ };
+ let mut spend_tx = Transaction {
+ version: 2,
+ lock_time: 0,
+ input: vec![input],
+ output: vec![outp],
+ };
+ let secp_ctx = Secp256k1::new();
+ let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], witness_script, output.value)[..]).unwrap();
+ let local_delaysig = secp_ctx.sign(&sighash, key);
+ spend_tx.input[0].witness.push(local_delaysig.serialize_der(&secp_ctx).to_vec());
+ spend_tx.input[0].witness[0].push(SigHashType::All as u8);
+ spend_tx.input[0].witness.push(vec!(0));
+ spend_tx.input[0].witness.push(witness_script.clone().into_bytes());
+ txn.push(spend_tx);
+ },
+ SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output } => {
+ let secp_ctx = Secp256k1::new();
+ let input = TxIn {
+ previous_output: outpoint.clone(),
+ script_sig: Script::new(),
+ sequence: 0,
+ witness: Vec::new(),
+ };
+ let outp = TxOut {
+ script_pubkey: Builder::new().push_opcode(opcodes::All::OP_RETURN).into_script(),
+ value: output.value,
+ };
+ let mut spend_tx = Transaction {
+ version: 2,
+ lock_time: 0,
+ input: vec![input],
+ output: vec![outp.clone()],
+ };
+ let secret = {
+ match ExtendedPrivKey::new_master(&secp_ctx, Network::Testnet, &$node.node_seed) {
+ Ok(master_key) => {
+ match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx($der_idx)) {
+ Ok(key) => key,
+ Err(_) => panic!("Your RNG is busted"),
+ }
+ }
+ Err(_) => panic!("Your rng is busted"),
+ }
+ };
+ let pubkey = ExtendedPubKey::from_private(&secp_ctx, &secret).public_key;
+ let witness_script = Address::p2pkh(&pubkey, Network::Testnet).script_pubkey();
+ let sighash = Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx.input[0], &witness_script, output.value)[..]).unwrap();
+ let sig = secp_ctx.sign(&sighash, &secret.secret_key);
+ spend_tx.input[0].witness.push(sig.serialize_der(&secp_ctx).to_vec());
+ spend_tx.input[0].witness[0].push(SigHashType::All as u8);
+ spend_tx.input[0].witness.push(pubkey.serialize().to_vec());
+ txn.push(spend_tx);
+ },
+ }
+ }
+ },
+ _ => panic!("Unexpected event"),
+ };
+ }
+ txn
+ }
+ }
+ }
+
+ #[test]
+ fn test_claim_sizeable_push_msat() {
+ // Incidentally test SpendableOutput event generation due to detection of to_local output on commitment tx
+ let nodes = create_network(2);
+
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000);
+ nodes[1].node.force_close_channel(&chan.2);
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(node_txn.len(), 1);
+ check_spends!(node_txn[0], chan.3.clone());
+ assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening
+
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
+ let spend_txn = check_spendable_outputs!(nodes[1], 1);
+ assert_eq!(spend_txn.len(), 1);
+ check_spends!(spend_txn[0], node_txn[0].clone());
+ }
+
+ #[test]
+ fn test_claim_on_remote_sizeable_push_msat() {
+ // Same test as previous, just test on remote commitment tx, as per_commitment_point registration changes following you're funder/fundee and
+ // to_remote output is encumbered by a P2WPKH
+
+ let nodes = create_network(2);
+
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000);
+ nodes[0].node.force_close_channel(&chan.2);
+ let events = nodes[0].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(node_txn.len(), 1);
+ check_spends!(node_txn[0], chan.3.clone());
+ assert_eq!(node_txn[0].output.len(), 2); // We can't force trimming of to_remote output as channel_reserve_satoshis block us to do so at channel opening
+
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 0);
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ let spend_txn = check_spendable_outputs!(nodes[1], 1);
+ assert_eq!(spend_txn.len(), 2);
+ assert_eq!(spend_txn[0], spend_txn[1]);
+ check_spends!(spend_txn[0], node_txn[0].clone());
+ }
+
+ #[test]
+ fn test_claim_on_remote_revoked_sizeable_push_msat() {
+ // Same test as previous, just test on remote revoked commitment tx, as per_commitment_point registration changes following you're funder/fundee and
+ // to_remote output is encumbered by a P2WPKH
+
+ let nodes = create_network(2);
+
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 59000000);
+ let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
+ assert_eq!(revoked_local_txn[0].input.len(), 1);
+ assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
+
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ let spend_txn = check_spendable_outputs!(nodes[1], 1);
+ assert_eq!(spend_txn.len(), 4);
+ assert_eq!(spend_txn[0], spend_txn[2]); // to_remote output on revoked remote commitment_tx
+ check_spends!(spend_txn[0], revoked_local_txn[0].clone());
+ assert_eq!(spend_txn[1], spend_txn[3]); // to_local output on local commitment tx
+ check_spends!(spend_txn[1], node_txn[0].clone());
+ }
+
+ #[test]
+ fn test_static_spendable_outputs_preimage_tx() {
+ let nodes = create_network(2);
+
+ // Create some initial channels
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
+
+ let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
+ assert_eq!(commitment_tx[0].input.len(), 1);
+ assert_eq!(commitment_tx[0].input[0].previous_output.txid, chan_1.3.txid());
+
+ // Settle A's commitment tx on B's chain
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ assert!(nodes[1].node.claim_funds(payment_preimage));
+ check_added_monitors!(nodes[1], 1);
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()] }, 1);
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::UpdateHTLCs { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ match events[1] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexepected event"),
+ }
+
+ // Check B's monitor was able to send back output descriptor event for preimage tx on A's commitment tx
+ let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); // ChannelManager : 1 (local commitment tx), ChannelMonitor: 2 (1 preimage tx) * 2 (block-rescan)
+ check_spends!(node_txn[0], commitment_tx[0].clone());
+ assert_eq!(node_txn[0], node_txn[2]);
+ assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), 133);
+ check_spends!(node_txn[1], chan_1.3.clone());
+
+ let spend_txn = check_spendable_outputs!(nodes[1], 1); // , 0, 0, 1, 1);
+ assert_eq!(spend_txn.len(), 2);
+ assert_eq!(spend_txn[0], spend_txn[1]);
+ check_spends!(spend_txn[0], node_txn[0].clone());
+ }
+
+ #[test]
+ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
+ let nodes = create_network(2);
+
+ // Create some initial channels
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.last_local_commitment_txn.clone();
+ assert_eq!(revoked_local_txn[0].input.len(), 1);
+ assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
+
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
+
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(node_txn.len(), 3);
+ assert_eq!(node_txn.pop().unwrap(), node_txn[0]);
+ assert_eq!(node_txn[0].input.len(), 2);
+ check_spends!(node_txn[0], revoked_local_txn[0].clone());
+
+ let spend_txn = check_spendable_outputs!(nodes[1], 1);
+ assert_eq!(spend_txn.len(), 2);
+ assert_eq!(spend_txn[0], spend_txn[1]);
+ check_spends!(spend_txn[0], node_txn[0].clone());
+ }
+
+ #[test]
+ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
+ let nodes = create_network(2);
+
+ // Create some initial channels
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
+ assert_eq!(revoked_local_txn[0].input.len(), 1);
+ assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
+
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
+
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ // A will generate HTLC-Timeout from revoked commitment tx
+ nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+ let events = nodes[0].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ let revoked_htlc_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(revoked_htlc_txn.len(), 3);
+ assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[2]);
+ assert_eq!(revoked_htlc_txn[0].input.len(), 1);
+ assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), 133);
+ check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone());
+ check_spends!(revoked_htlc_txn[1], chan_1.3.clone());
+
+ // B will generate justice tx from A's revoked commitment/HTLC tx
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1);
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+
+ let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(node_txn.len(), 4);
+ assert_eq!(node_txn[3].input.len(), 1);
+ check_spends!(node_txn[3], revoked_htlc_txn[0].clone());
+
+ // Check B's ChannelMonitor was able to generate the right spendable output descriptor
+ let spend_txn = check_spendable_outputs!(nodes[1], 1);
+ assert_eq!(spend_txn.len(), 3);
+ assert_eq!(spend_txn[0], spend_txn[1]);
+ check_spends!(spend_txn[0], node_txn[0].clone());
+ check_spends!(spend_txn[2], node_txn[3].clone());
+ }
+
+ #[test]
+ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
+ let nodes = create_network(2);
+
+ // Create some initial channels
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
+ let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
+ assert_eq!(revoked_local_txn[0].input.len(), 1);
+ assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
+
+ claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage);
+
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ // B will generate HTLC-Success from revoked commitment tx
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ let revoked_htlc_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
+
+ assert_eq!(revoked_htlc_txn.len(), 3);
+ assert_eq!(revoked_htlc_txn[0], revoked_htlc_txn[2]);
+ assert_eq!(revoked_htlc_txn[0].input.len(), 1);
+ assert_eq!(revoked_htlc_txn[0].input[0].witness.last().unwrap().len(), 138);
+ check_spends!(revoked_htlc_txn[0], revoked_local_txn[0].clone());
+
+ // A will generate justice tx from B's revoked commitment/HTLC tx
+ nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone(), revoked_htlc_txn[0].clone()] }, 1);
+ let events = nodes[0].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+
+ let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(node_txn.len(), 4);
+ assert_eq!(node_txn[3].input.len(), 1);
+ check_spends!(node_txn[3], revoked_htlc_txn[0].clone());
+
+ // Check A's ChannelMonitor was able to generate the right spendable output descriptor
+ let spend_txn = check_spendable_outputs!(nodes[0], 1);
+ assert_eq!(spend_txn.len(), 5);
+ assert_eq!(spend_txn[0], spend_txn[2]);
+ assert_eq!(spend_txn[1], spend_txn[3]);
+ check_spends!(spend_txn[0], revoked_local_txn[0].clone()); // spending to_remote output from revoked local tx
+ check_spends!(spend_txn[1], node_txn[2].clone()); // spending justice tx output from revoked local tx htlc received output
+ check_spends!(spend_txn[4], node_txn[3].clone()); // spending justice tx output on htlc success tx
+ }
+
+ #[test]
+ fn test_dynamic_spendable_outputs_local_htlc_success_tx() {
+ let nodes = create_network(2);
+
+ // Create some initial channels
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000).0;
+ let local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
+ assert_eq!(local_txn[0].input.len(), 1);
+ check_spends!(local_txn[0], chan_1.3.clone());
+
+ // Give B knowledge of preimage to be able to generate a local HTLC-Success Tx
+ nodes[1].node.claim_funds(payment_preimage);
+ check_added_monitors!(nodes[1], 1);
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![local_txn[0].clone()] }, 1);
+ let events = nodes[1].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::UpdateHTLCs { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ match events[1] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexepected event"),
+ }
+ let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(node_txn[0].input.len(), 1);
+ assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), 138);
+ check_spends!(node_txn[0], local_txn[0].clone());
+
+ // Verify that B is able to spend its own HTLC-Success tx thanks to spendable output event given back by its ChannelMonitor
+ let spend_txn = check_spendable_outputs!(nodes[1], 1);
+ assert_eq!(spend_txn.len(), 2);
+ check_spends!(spend_txn[0], node_txn[0].clone());
+ check_spends!(spend_txn[1], node_txn[2].clone());
+ }
+
+ #[test]
+ fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() {
+ let nodes = create_network(2);
+
+ // Create some initial channels
+ let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000).0;
+ let local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
+ assert_eq!(local_txn[0].input.len(), 1);
+ check_spends!(local_txn[0], chan_1.3.clone());
+
+ // Timeout HTLC on A's chain and so it can generate a HTLC-Timeout tx
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![local_txn[0].clone()] }, 200);
+ let events = nodes[0].node.get_and_clear_pending_msg_events();
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+ _ => panic!("Unexepected event"),
+ }
+ let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
+ assert_eq!(node_txn[0].input.len(), 1);
+ assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), 133);
+ check_spends!(node_txn[0], local_txn[0].clone());
+
+ // Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor
+ let spend_txn = check_spendable_outputs!(nodes[0], 1);
+ assert_eq!(spend_txn.len(), 8);
+ assert_eq!(spend_txn[0], spend_txn[2]);
+ assert_eq!(spend_txn[0], spend_txn[4]);
+ assert_eq!(spend_txn[0], spend_txn[6]);
+ assert_eq!(spend_txn[1], spend_txn[3]);
+ assert_eq!(spend_txn[1], spend_txn[5]);
+ assert_eq!(spend_txn[1], spend_txn[7]);
+ check_spends!(spend_txn[0], local_txn[0].clone());
+ check_spends!(spend_txn[1], node_txn[0].clone());
+ }
+
+ #[test]
+ fn test_static_output_closing_tx() {
+ let nodes = create_network(2);
+
+ let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
+
+ send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
+ let closing_tx = close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true).2;
+
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![closing_tx.clone()] }, 1);
+ let spend_txn = check_spendable_outputs!(nodes[0], 2);
+ assert_eq!(spend_txn.len(), 1);
+ check_spends!(spend_txn[0], closing_tx.clone());
+
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![closing_tx.clone()] }, 1);
+ let spend_txn = check_spendable_outputs!(nodes[1], 2);
+ assert_eq!(spend_txn.len(), 1);
+ check_spends!(spend_txn[0], closing_tx);
+ }