Skip to content

Commit 9c5acf1

Browse files
Move pending forward htlc construction into method
In upcoming blinded paths work, this method will grow to handle blinded forwards.
1 parent df237ba commit 9c5acf1

File tree

1 file changed

+55
-39
lines changed

1 file changed

+55
-39
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl HTLCSource {
341341
}
342342
}
343343

344-
struct ReceiveError {
344+
struct InboundOnionErr {
345345
err_code: u16,
346346
err_data: Vec<u8>,
347347
msg: &'static str,
@@ -2616,14 +2616,52 @@ where
26162616
}
26172617
}
26182618

2619+
fn construct_fwd_pending_htlc_info(
2620+
&self, msg: &msgs::UpdateAddHTLC, hop_data: msgs::OnionHopData, hop_hmac: [u8; 32],
2621+
new_packet_bytes: [u8; onion_utils::ONION_DATA_LEN], shared_secret: [u8; 32],
2622+
next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
2623+
) -> Result<PendingHTLCInfo, InboundOnionErr> {
2624+
debug_assert!(next_packet_pubkey_opt.is_some());
2625+
let outgoing_packet = msgs::OnionPacket {
2626+
version: 0,
2627+
public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
2628+
hop_data: new_packet_bytes,
2629+
hmac: hop_hmac.clone(),
2630+
};
2631+
2632+
let short_channel_id = match hop_data.format {
2633+
msgs::OnionHopDataFormat::NonFinalNode { short_channel_id } => short_channel_id,
2634+
msgs::OnionHopDataFormat::FinalNode { .. } => {
2635+
return Err(InboundOnionErr {
2636+
msg: "Final Node OnionHopData provided for us as an intermediary node",
2637+
err_code: 0x4000 | 22,
2638+
err_data: Vec::new(),
2639+
})
2640+
},
2641+
};
2642+
2643+
Ok(PendingHTLCInfo {
2644+
routing: PendingHTLCRouting::Forward {
2645+
onion_packet: outgoing_packet,
2646+
short_channel_id,
2647+
},
2648+
payment_hash: msg.payment_hash.clone(),
2649+
incoming_shared_secret: shared_secret,
2650+
incoming_amt_msat: Some(msg.amount_msat),
2651+
outgoing_amt_msat: hop_data.amt_to_forward,
2652+
outgoing_cltv_value: hop_data.outgoing_cltv_value,
2653+
skimmed_fee_msat: None,
2654+
})
2655+
}
2656+
26192657
fn construct_recv_pending_htlc_info(
26202658
&self, hop_data: msgs::OnionHopData, shared_secret: [u8; 32], payment_hash: PaymentHash,
26212659
amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool,
26222660
counterparty_skimmed_fee_msat: Option<u64>,
2623-
) -> Result<PendingHTLCInfo, ReceiveError> {
2661+
) -> Result<PendingHTLCInfo, InboundOnionErr> {
26242662
// final_incorrect_cltv_expiry
26252663
if hop_data.outgoing_cltv_value > cltv_expiry {
2626-
return Err(ReceiveError {
2664+
return Err(InboundOnionErr {
26272665
msg: "Upstream node set CLTV to less than the CLTV set by the sender",
26282666
err_code: 18,
26292667
err_data: cltv_expiry.to_be_bytes().to_vec()
@@ -2641,7 +2679,7 @@ where
26412679
let mut err_data = Vec::with_capacity(12);
26422680
err_data.extend_from_slice(&amt_msat.to_be_bytes());
26432681
err_data.extend_from_slice(&current_height.to_be_bytes());
2644-
return Err(ReceiveError {
2682+
return Err(InboundOnionErr {
26452683
err_code: 0x4000 | 15, err_data,
26462684
msg: "The final CLTV expiry is too soon to handle",
26472685
});
@@ -2650,7 +2688,7 @@ where
26502688
(allow_underpay && hop_data.amt_to_forward >
26512689
amt_msat.saturating_add(counterparty_skimmed_fee_msat.unwrap_or(0)))
26522690
{
2653-
return Err(ReceiveError {
2691+
return Err(InboundOnionErr {
26542692
err_code: 19,
26552693
err_data: amt_msat.to_be_bytes().to_vec(),
26562694
msg: "Upstream node sent less than we were supposed to receive in payment",
@@ -2659,7 +2697,7 @@ where
26592697

26602698
let routing = match hop_data.format {
26612699
msgs::OnionHopDataFormat::NonFinalNode { .. } => {
2662-
return Err(ReceiveError {
2700+
return Err(InboundOnionErr {
26632701
err_code: 0x4000|22,
26642702
err_data: Vec::new(),
26652703
msg: "Got non final data with an HMAC of 0",
@@ -2674,14 +2712,14 @@ where
26742712
// time discrepancies due to a hash collision with X.
26752713
let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
26762714
if hashed_preimage != payment_hash {
2677-
return Err(ReceiveError {
2715+
return Err(InboundOnionErr {
26782716
err_code: 0x4000|22,
26792717
err_data: Vec::new(),
26802718
msg: "Payment preimage didn't match payment hash",
26812719
});
26822720
}
26832721
if !self.default_configuration.accept_mpp_keysend && payment_data.is_some() {
2684-
return Err(ReceiveError {
2722+
return Err(InboundOnionErr {
26852723
err_code: 0x4000|22,
26862724
err_data: Vec::new(),
26872725
msg: "We don't support MPP keysend payments",
@@ -2701,7 +2739,7 @@ where
27012739
phantom_shared_secret,
27022740
}
27032741
} else {
2704-
return Err(ReceiveError {
2742+
return Err(InboundOnionErr {
27052743
err_code: 0x4000|0x2000|3,
27062744
err_data: Vec::new(),
27072745
msg: "We require payment_secrets",
@@ -2964,37 +3002,15 @@ where
29643002
// delay) once they've send us a commitment_signed!
29653003
PendingHTLCStatus::Forward(info)
29663004
},
2967-
Err(ReceiveError { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
3005+
Err(InboundOnionErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
29683006
}
29693007
},
29703008
onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
2971-
debug_assert!(next_packet_pubkey_opt.is_some());
2972-
let outgoing_packet = msgs::OnionPacket {
2973-
version: 0,
2974-
public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
2975-
hop_data: new_packet_bytes,
2976-
hmac: next_hop_hmac.clone(),
2977-
};
2978-
2979-
let short_channel_id = match next_hop_data.format {
2980-
msgs::OnionHopDataFormat::NonFinalNode { short_channel_id } => short_channel_id,
2981-
msgs::OnionHopDataFormat::FinalNode { .. } => {
2982-
return_err!("Final Node OnionHopData provided for us as an intermediary node", 0x4000 | 22, &[0;0]);
2983-
},
2984-
};
2985-
2986-
PendingHTLCStatus::Forward(PendingHTLCInfo {
2987-
routing: PendingHTLCRouting::Forward {
2988-
onion_packet: outgoing_packet,
2989-
short_channel_id,
2990-
},
2991-
payment_hash: msg.payment_hash.clone(),
2992-
incoming_shared_secret: shared_secret,
2993-
incoming_amt_msat: Some(msg.amount_msat),
2994-
outgoing_amt_msat: next_hop_data.amt_to_forward,
2995-
outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
2996-
skimmed_fee_msat: None,
2997-
})
3009+
match self.construct_fwd_pending_htlc_info(msg, next_hop_data, next_hop_hmac,
3010+
new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
3011+
Ok(info) => PendingHTLCStatus::Forward(info),
3012+
Err(InboundOnionErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
3013+
}
29983014
}
29993015
}
30003016
}
@@ -3777,7 +3793,7 @@ where
37773793
outgoing_cltv_value, Some(phantom_shared_secret), false, None)
37783794
{
37793795
Ok(info) => phantom_receives.push((prev_short_channel_id, prev_funding_outpoint, prev_user_channel_id, vec![(info, prev_htlc_id)])),
3780-
Err(ReceiveError { err_code, err_data, msg }) => failed_payment!(msg, err_code, err_data, Some(phantom_shared_secret))
3796+
Err(InboundOnionErr { err_code, err_data, msg }) => failed_payment!(msg, err_code, err_data, Some(phantom_shared_secret))
37813797
}
37823798
},
37833799
_ => panic!(),
@@ -10018,7 +10034,7 @@ mod tests {
1001810034
};
1001910035
// Check that if the amount we received + the penultimate hop extra fee is less than the sender
1002010036
// intended amount, we fail the payment.
10021-
if let Err(crate::ln::channelmanager::ReceiveError { err_code, .. }) =
10037+
if let Err(crate::ln::channelmanager::InboundOnionErr { err_code, .. }) =
1002210038
node[0].node.construct_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]),
1002310039
sender_intended_amt_msat - extra_fee_msat - 1, 42, None, true, Some(extra_fee_msat))
1002410040
{

0 commit comments

Comments
 (0)