Skip to content

Commit 5471a66

Browse files
Add test that a remote add that violates the remote's fee spike buffer will result in the HTLC's status to be Pending::Failed
1 parent 9924863 commit 5471a66

File tree

1 file changed

+99
-2
lines changed

1 file changed

+99
-2
lines changed

lightning/src/ln/channel.rs

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4435,7 +4435,7 @@ mod tests {
44354435
use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys};
44364436
use ln::channel::MAX_FUNDING_SATOSHIS;
44374437
use ln::features::{InitFeatures, NodeFeatures};
4438-
use ln::msgs::{OptionalField, DataLossProtect, UpdateAddHTLC};
4438+
use ln::msgs::{OptionalField, DataLossProtect, UpdateAddHTLC, OnionErrorPacket};
44394439
use ln::{chan_utils, onion_utils};
44404440
use ln::chan_utils::{LocalCommitmentTransaction, ChannelPublicKeys};
44414441
use ln::features::ChannelFeatures;
@@ -4605,7 +4605,104 @@ mod tests {
46054605
}
46064606

46074607
#[test]
4608-
#[should_panic]
4608+
fn test_fee_spike_buffer_violation_inbound_htlc_inbound_chan() {
4609+
let chan_cfgs = create_chan_cfgs(2);
4610+
let mut chans = create_channels(&chan_cfgs, 100000, 95000000);
4611+
4612+
// Construct an update_add_htlc message to test that chans[1] will
4613+
// change a pending HTLC's status to failure upon receipt of a fee spike
4614+
// buffer violating HTLC offer.
4615+
let route_hop = RouteHop {
4616+
pubkey: chans[0].their_node_id,
4617+
node_features: NodeFeatures::known(),
4618+
short_channel_id: chans[0].short_channel_id.unwrap(),
4619+
channel_features: ChannelFeatures::known(),
4620+
fee_msat: 0,
4621+
cltv_expiry_delta: 0,
4622+
};
4623+
let route = vec![route_hop];
4624+
4625+
let secp_ctx = Secp256k1::new();
4626+
let mut session_priv_raw;
4627+
let session_priv = SecretKey::from_slice(&{
4628+
session_priv_raw = [0; 32];
4629+
let mut rng = thread_rng();
4630+
rng.fill_bytes(&mut session_priv_raw);
4631+
session_priv_raw
4632+
}).expect("RNG is bad!");
4633+
4634+
let payment_preimage = PaymentPreimage([0; 32]);
4635+
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
4636+
4637+
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
4638+
let onion_keys_2 = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
4639+
let onion_keys_3 = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
4640+
let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route, 1, &None, 0).unwrap();
4641+
let (onion_payloads_2, _, _) = onion_utils::build_onion_payloads(&route, 1, &None, 0).unwrap();
4642+
let (onion_payloads_3, _, _) = onion_utils::build_onion_payloads(&route, 1, &None, 0).unwrap();
4643+
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
4644+
let onion_packet_2 = onion_utils::construct_onion_packet(onion_payloads_2, onion_keys_2, [0; 32], &payment_hash);
4645+
let onion_packet_3 = onion_utils::construct_onion_packet(onion_payloads_3, onion_keys_3, [0; 32], &payment_hash);
4646+
4647+
// The max nodes[1] can receive is its nodes[0]'s outbound liquidity
4648+
// minus the commit tx fees, nodes[0]'s channel reserve, and the fee
4649+
// spike buffer.
4650+
let max_can_recv = 5000000 - chans[0].local_channel_reserve_satoshis * 1000 - 2*chans[1].next_remote_commit_tx_fee_msat(1 + 1);
4651+
4652+
// Manually construct the update_add_htlc message to bypass checks in send_htlc.
4653+
let mut msg = UpdateAddHTLC {
4654+
channel_id: chans[0].channel_id,
4655+
htlc_id: 0,
4656+
amount_msat: max_can_recv + 1,
4657+
payment_hash,
4658+
cltv_expiry: htlc_cltv,
4659+
onion_routing_packet: onion_packet,
4660+
};
4661+
let pending_forward_state = PendingHTLCStatus::Forward(PendingHTLCInfo{
4662+
routing: PendingHTLCRouting::Forward{ onion_packet: onion_packet_2, short_channel_id: chans[0].short_channel_id.unwrap() },
4663+
incoming_shared_secret: session_priv_raw,
4664+
payment_hash,
4665+
amt_to_forward: max_can_recv + 1,
4666+
outgoing_cltv_value: htlc_cltv
4667+
});
4668+
let create_onion_closure = |_chan: &Channel<EnforcingChannelKeys>, _pending_forward_info: &PendingHTLCStatus| {
4669+
Some(OnionErrorPacket{ data: vec![] })
4670+
};
4671+
4672+
// Assert that the HTLC was successfully added.
4673+
assert!(chans[1].update_add_htlc(&msg, pending_forward_state, create_onion_closure).is_ok());
4674+
4675+
// Check that the HTLC's pending status is failed.
4676+
match &chans[1].pending_inbound_htlcs[0].state {
4677+
&InboundHTLCState::RemoteAnnounced(ref state) => {
4678+
if let &PendingHTLCStatus::Fail(_) = state { } else { panic!() }
4679+
},
4680+
_ => panic!(),
4681+
}
4682+
4683+
// Check that adding an HTLC worth 1 msat less will succeed.
4684+
let create_onion_closure = |_chan: &Channel<EnforcingChannelKeys>, _pending_forward_info: &PendingHTLCStatus| {
4685+
Some(OnionErrorPacket{ data: vec![] })
4686+
};
4687+
chans[1].pending_inbound_htlcs = vec![];
4688+
let pending_forward_state = PendingHTLCStatus::Forward(PendingHTLCInfo{
4689+
routing: PendingHTLCRouting::Forward{ onion_packet: onion_packet_3, short_channel_id: chans[0].short_channel_id.unwrap() },
4690+
incoming_shared_secret: session_priv_raw,
4691+
payment_hash,
4692+
amt_to_forward: max_can_recv + 1,
4693+
outgoing_cltv_value: htlc_cltv
4694+
});
4695+
msg.htlc_id = 1;
4696+
msg.amount_msat = max_can_recv;
4697+
assert!(chans[1].update_add_htlc(&msg, pending_forward_state, create_onion_closure).is_ok());
4698+
match &chans[1].pending_inbound_htlcs[0].state {
4699+
&InboundHTLCState::RemoteAnnounced(ref state) => {
4700+
if let &PendingHTLCStatus::Forward(_) = state { } else { panic!() }
4701+
},
4702+
_ => panic!(),
4703+
}
4704+
}
4705+
46094706
#[test]
46104707
fn test_chan_reserve_violation_inbound_htlc_outbound_chan() {
46114708
let chan_cfgs = create_chan_cfgs(2);

0 commit comments

Comments
 (0)