+ run_onion_failure_test("final_expiry_too_soon", 1, &nodes, &route, &payment_hash, |msg| {
+ let height = msg.cltv_expiry - CLTV_CLAIM_BUFFER - LATENCY_GRACE_PERIOD_BLOCKS + 1;
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+
+ nodes[2].block_notifier.block_connected_checked(&header, height, &[], &[]);
+ }, || {}, true, Some(17), None);
+
+ run_onion_failure_test("final_incorrect_cltv_expiry", 1, &nodes, &route, &payment_hash, |_| {}, || {
+ for (_, pending_forwards) in nodes[1].node.channel_state.lock().unwrap().forward_htlcs.iter_mut() {
+ for f in pending_forwards.iter_mut() {
+ match f {
+ &mut HTLCForwardInfo::AddHTLC { ref mut forward_info, .. } =>
+ forward_info.outgoing_cltv_value += 1,
+ _ => {},
+ }
+ }
+ }
+ }, true, Some(18), None);
+
+ run_onion_failure_test("final_incorrect_htlc_amount", 1, &nodes, &route, &payment_hash, |_| {}, || {
+ // violate amt_to_forward > msg.amount_msat
+ for (_, pending_forwards) in nodes[1].node.channel_state.lock().unwrap().forward_htlcs.iter_mut() {
+ for f in pending_forwards.iter_mut() {
+ match f {
+ &mut HTLCForwardInfo::AddHTLC { ref mut forward_info, .. } =>
+ forward_info.amt_to_forward -= 1,
+ _ => {},
+ }
+ }
+ }
+ }, true, Some(19), None);
+
+ run_onion_failure_test("channel_disabled", 0, &nodes, &route, &payment_hash, |_| {}, || {
+ // disconnect event to the channel between nodes[1] ~ nodes[2]
+ nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), false);
+ nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+ }, true, Some(UPDATE|20), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
+ reconnect_nodes(&nodes[1], &nodes[2], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
+
+ run_onion_failure_test("expiry_too_far", 0, &nodes, &route, &payment_hash, |msg| {
+ let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
+ let mut route = route.clone();
+ let height = 1;
+ route.paths[0][1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.paths[0][0].cltv_expiry_delta + 1;
+ let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
+ let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, height).unwrap();
+ let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
+ msg.cltv_expiry = htlc_cltv;
+ msg.onion_routing_packet = onion_packet;
+ }, ||{}, true, Some(21), None);
+}
+
+#[test]
+#[should_panic]
+fn bolt2_open_channel_sending_node_checks_part1() { //This test needs to be on its own as we are catching a panic
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+ //Force duplicate channel ids
+ for node in nodes.iter() {
+ *node.keys_manager.override_channel_id_priv.lock().unwrap() = Some([0; 32]);
+ }
+
+ // BOLT #2 spec: Sending node must ensure temporary_channel_id is unique from any other channel ID with the same peer.
+ let channel_value_satoshis=10000;
+ let push_msat=10001;
+ nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None).unwrap();
+ let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
+ nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &node0_to_1_send_open_channel);
+
+ //Create a second channel with a channel_id collision
+ assert!(nodes[0].node.create_channel(nodes[0].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None).is_err());
+}
+
+#[test]
+fn bolt2_open_channel_sending_node_checks_part2() {
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+ // BOLT #2 spec: Sending node must set funding_satoshis to less than 2^24 satoshis
+ let channel_value_satoshis=2^24;
+ let push_msat=10001;
+ assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None).is_err());
+
+ // BOLT #2 spec: Sending node must set push_msat to equal or less than 1000 * funding_satoshis
+ let channel_value_satoshis=10000;
+ // Test when push_msat is equal to 1000 * funding_satoshis.
+ let push_msat=1000*channel_value_satoshis+1;
+ assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None).is_err());
+
+ // BOLT #2 spec: Sending node must set set channel_reserve_satoshis greater than or equal to dust_limit_satoshis
+ let channel_value_satoshis=10000;
+ let push_msat=10001;
+ assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None).is_ok()); //Create a valid channel
+ let node0_to_1_send_open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
+ assert!(node0_to_1_send_open_channel.channel_reserve_satoshis>=node0_to_1_send_open_channel.dust_limit_satoshis);
+
+ // BOLT #2 spec: Sending node must set undefined bits in channel_flags to 0
+ // Only the least-significant bit of channel_flags is currently defined resulting in channel_flags only having one of two possible states 0 or 1
+ assert!(node0_to_1_send_open_channel.channel_flags<=1);
+
+ // BOLT #2 spec: Sending node should set to_self_delay sufficient to ensure the sender can irreversibly spend a commitment transaction output, in case of misbehaviour by the receiver.
+ assert!(BREAKDOWN_TIMEOUT>0);
+ assert!(node0_to_1_send_open_channel.to_self_delay==BREAKDOWN_TIMEOUT);
+
+ // BOLT #2 spec: Sending node must ensure the chain_hash value identifies the chain it wishes to open the channel within.
+ let chain_hash=genesis_block(Network::Testnet).header.bitcoin_hash();
+ assert_eq!(node0_to_1_send_open_channel.chain_hash,chain_hash);
+
+ // BOLT #2 spec: Sending node must set funding_pubkey, revocation_basepoint, htlc_basepoint, payment_basepoint, and delayed_payment_basepoint to valid DER-encoded, compressed, secp256k1 pubkeys.
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.funding_pubkey.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.revocation_basepoint.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.htlc_basepoint.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.payment_point.serialize()).is_ok());
+ assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.delayed_payment_basepoint.serialize()).is_ok());
+}
+
+// Test that if we fail to send an HTLC that is being freed from the holding cell, and the HTLC
+// originated from our node, its failure is surfaced to the user. We trigger this failure to
+// free the HTLC by increasing our fee while the HTLC is in the holding cell such that the HTLC
+// is no longer affordable once it's freed.
+#[test]
+fn test_fail_holding_cell_htlc_upon_free() {
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let logger = test_utils::TestLogger::new();
+
+ // First nodes[0] generates an update_fee, setting the channel's
+ // pending_update_fee.
+ nodes[0].node.update_fee(chan.2, get_feerate!(nodes[0], chan.2) + 20).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let events = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 1);
+ let (update_msg, commitment_signed) = match events[0] {
+ MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => {
+ (update_fee.as_ref(), commitment_signed)
+ },
+ _ => panic!("Unexpected event"),
+ };
+
+ nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msg.unwrap());
+
+ let mut chan_stat = get_channel_value_stat!(nodes[0], chan.2);
+ let channel_reserve = chan_stat.channel_reserve_msat;
+ let feerate = get_feerate!(nodes[0], chan.2);
+
+ // 2* and +1 HTLCs on the commit tx fee calculation for the fee spike reserve.
+ let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
+ let max_can_send = 5000000 - channel_reserve - 2*commit_tx_fee_msat(feerate, 1 + 1);
+ let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+ let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, &[], max_can_send, TEST_FINAL_CLTV, &logger).unwrap();
+
+ // Send a payment which passes reserve checks but gets stuck in the holding cell.
+ nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
+ chan_stat = get_channel_value_stat!(nodes[0], chan.2);
+ assert_eq!(chan_stat.holding_cell_outbound_amount_msat, max_can_send);
+
+ // Flush the pending fee update.
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), commitment_signed);
+ let (as_revoke_and_ack, _) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ check_added_monitors!(nodes[1], 1);
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &as_revoke_and_ack);
+ check_added_monitors!(nodes[0], 1);
+
+ // Upon receipt of the RAA, there will be an attempt to resend the holding cell
+ // HTLC, but now that the fee has been raised the payment will now fail, causing
+ // us to surface its failure to the user.
+ chan_stat = get_channel_value_stat!(nodes[0], chan.2);
+ assert_eq!(chan_stat.holding_cell_outbound_amount_msat, 0);
+ nodes[0].logger.assert_log("lightning::ln::channel".to_string(), "Freeing holding cell with 1 HTLC updates".to_string(), 1);
+ let failure_log = format!("Failed to send HTLC with payment_hash {} due to Cannot send value that would put us under local channel reserve value ({})", log_bytes!(our_payment_hash.0), chan_stat.channel_reserve_msat);
+ nodes[0].logger.assert_log("lightning::ln::channel".to_string(), failure_log.to_string(), 1);
+
+ // Check that the payment failed to be sent out.
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match &events[0] {
+ &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref error_code, ref error_data } => {
+ assert_eq!(our_payment_hash.clone(), *payment_hash);
+ assert_eq!(*rejected_by_dest, false);
+ assert_eq!(*error_code, None);
+ assert_eq!(*error_data, None);
+ },
+ _ => panic!("Unexpected event"),
+ }
+}
+
+// Test that if multiple HTLCs are released from the holding cell and one is
+// valid but the other is no longer valid upon release, the valid HTLC can be
+// successfully completed while the other one fails as expected.
+#[test]
+fn test_free_and_fail_holding_cell_htlcs() {
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+ let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let logger = test_utils::TestLogger::new();
+
+ // First nodes[0] generates an update_fee, setting the channel's
+ // pending_update_fee.
+ nodes[0].node.update_fee(chan.2, get_feerate!(nodes[0], chan.2) + 200).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let events = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 1);
+ let (update_msg, commitment_signed) = match events[0] {
+ MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => {
+ (update_fee.as_ref(), commitment_signed)
+ },
+ _ => panic!("Unexpected event"),
+ };
+
+ nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msg.unwrap());
+
+ let mut chan_stat = get_channel_value_stat!(nodes[0], chan.2);
+ let channel_reserve = chan_stat.channel_reserve_msat;
+ let feerate = get_feerate!(nodes[0], chan.2);
+
+ // 2* and +1 HTLCs on the commit tx fee calculation for the fee spike reserve.
+ let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
+ let amt_1 = 20000;
+ let (_, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
+ let amt_2 = 5000000 - channel_reserve - 2*commit_tx_fee_msat(feerate, 2 + 1) - amt_1;
+ let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
+ let route_1 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, &[], amt_1, TEST_FINAL_CLTV, &logger).unwrap();
+ let route_2 = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), None, &[], amt_2, TEST_FINAL_CLTV, &logger).unwrap();
+
+ // Send 2 payments which pass reserve checks but get stuck in the holding cell.
+ nodes[0].node.send_payment(&route_1, payment_hash_1, &None).unwrap();
+ chan_stat = get_channel_value_stat!(nodes[0], chan.2);
+ assert_eq!(chan_stat.holding_cell_outbound_amount_msat, amt_1);
+ nodes[0].node.send_payment(&route_2, payment_hash_2, &None).unwrap();
+ chan_stat = get_channel_value_stat!(nodes[0], chan.2);
+ assert_eq!(chan_stat.holding_cell_outbound_amount_msat, amt_1 + amt_2);
+
+ // Flush the pending fee update.
+ nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), commitment_signed);
+ let (revoke_and_ack, commitment_signed) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ check_added_monitors!(nodes[1], 1);
+ nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &revoke_and_ack);
+ nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &commitment_signed);
+ check_added_monitors!(nodes[0], 2);
+
+ // Upon receipt of the RAA, there will be an attempt to resend the holding cell HTLCs,
+ // but now that the fee has been raised the second payment will now fail, causing us
+ // to surface its failure to the user. The first payment should succeed.
+ chan_stat = get_channel_value_stat!(nodes[0], chan.2);
+ assert_eq!(chan_stat.holding_cell_outbound_amount_msat, 0);
+ nodes[0].logger.assert_log("lightning::ln::channel".to_string(), "Freeing holding cell with 2 HTLC updates".to_string(), 1);
+ let failure_log = format!("Failed to send HTLC with payment_hash {} due to Cannot send value that would put us under local channel reserve value ({})", log_bytes!(payment_hash_2.0), chan_stat.channel_reserve_msat);
+ nodes[0].logger.assert_log("lightning::ln::channel".to_string(), failure_log.to_string(), 1);
+
+ // Check that the second payment failed to be sent out.
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match &events[0] {
+ &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref error_code, ref error_data } => {
+ assert_eq!(payment_hash_2.clone(), *payment_hash);
+ assert_eq!(*rejected_by_dest, false);
+ assert_eq!(*error_code, None);
+ assert_eq!(*error_data, None);
+ },
+ _ => panic!("Unexpected event"),
+ }
+
+ // Complete the first payment and the RAA from the fee update.
+ let (payment_event, send_raa_event) = {
+ let mut msgs = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(msgs.len(), 2);
+ (SendEvent::from_event(msgs.remove(0)), msgs.remove(0))
+ };
+ let raa = match send_raa_event {
+ MessageSendEvent::SendRevokeAndACK { msg, .. } => msg,
+ _ => panic!("Unexpected event"),
+ };
+ nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &raa);
+ check_added_monitors!(nodes[1], 1);
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+ commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+ let 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.process_pending_htlc_forwards();
+ let events = nodes[1].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PaymentReceived { .. } => {},
+ _ => panic!("Unexpected event"),
+ }
+ nodes[1].node.claim_funds(payment_preimage_1, &None, amt_1);
+ check_added_monitors!(nodes[1], 1);
+ let update_msgs = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
+ nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &update_msgs.update_fulfill_htlcs[0]);
+ commitment_signed_dance!(nodes[0], nodes[1], update_msgs.commitment_signed, false, true);
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PaymentSent { ref payment_preimage } => {
+ assert_eq!(*payment_preimage, payment_preimage_1);
+ }
+ _ => panic!("Unexpected event"),
+ }
+}
+
+// Test that if we fail to forward an HTLC that is being freed from the holding cell that the
+// HTLC is failed backwards. We trigger this failure to forward the freed HTLC by increasing
+// our fee while the HTLC is in the holding cell such that the HTLC is no longer affordable
+// once it's freed.
+#[test]
+fn test_fail_holding_cell_htlc_upon_free_multihop() {
+ let chanmon_cfgs = create_chanmon_cfgs(3);
+ let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+ let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+ let chan_0_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let chan_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000, InitFeatures::known(), InitFeatures::known());
+ let logger = test_utils::TestLogger::new();
+
+ // First nodes[1] generates an update_fee, setting the channel's
+ // pending_update_fee.
+ nodes[1].node.update_fee(chan_1_2.2, get_feerate!(nodes[1], chan_1_2.2) + 20).unwrap();
+ check_added_monitors!(nodes[1], 1);