- if let Some((monitor_update, further_update_exists)) = chan.unblock_next_blocked_monitor_update() {
- log_debug!(self.logger, "Unlocking monitor updating for channel {} and updating monitor",
- channel_funding_outpoint.to_channel_id());
- handle_new_monitor_update!(self, channel_funding_outpoint, monitor_update,
- peer_state_lck, peer_state, per_peer_state, chan);
- if further_update_exists {
- // If there are more `ChannelMonitorUpdate`s to process, restart at the
- // top of the loop.
- continue;
- }
- } else {
- log_trace!(self.logger, "Unlocked monitor updating for channel {} without monitors to update",
- channel_funding_outpoint.to_channel_id());
- }
- }
- }
- } else {
- log_debug!(self.logger,
- "Got a release post-RAA monitor update for peer {} but the channel is gone",
- log_pubkey!(counterparty_node_id));
- }
- break;
- }
- }
-
- fn handle_post_event_actions(&self, actions: Vec<EventCompletionAction>) {
- for action in actions {
- match action {
- EventCompletionAction::ReleaseRAAChannelMonitorUpdate {
- channel_funding_outpoint, counterparty_node_id
- } => {
- self.handle_monitor_update_release(counterparty_node_id, channel_funding_outpoint, None);
- }
- }
- }
- }
-
- /// Processes any events asynchronously in the order they were generated since the last call
- /// using the given event handler.
- ///
- /// See the trait-level documentation of [`EventsProvider`] for requirements.
- pub async fn process_pending_events_async<Future: core::future::Future, H: Fn(Event) -> Future>(
- &self, handler: H
- ) {
- let mut ev;
- process_events_body!(self, ev, { handler(ev).await });
- }
-}
-
-fn create_fwd_pending_htlc_info(
- msg: &msgs::UpdateAddHTLC, hop_data: msgs::InboundOnionPayload, hop_hmac: [u8; 32],
- new_packet_bytes: [u8; onion_utils::ONION_DATA_LEN], shared_secret: [u8; 32],
- next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
-) -> Result<PendingHTLCInfo, InboundOnionErr> {
- debug_assert!(next_packet_pubkey_opt.is_some());
- let outgoing_packet = msgs::OnionPacket {
- version: 0,
- public_key: next_packet_pubkey_opt.unwrap_or(Err(secp256k1::Error::InvalidPublicKey)),
- hop_data: new_packet_bytes,
- hmac: hop_hmac,
- };
-
- let (short_channel_id, amt_to_forward, outgoing_cltv_value) = match hop_data {
- msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } =>
- (short_channel_id, amt_to_forward, outgoing_cltv_value),
- msgs::InboundOnionPayload::Receive { .. } | msgs::InboundOnionPayload::BlindedReceive { .. } =>
- return Err(InboundOnionErr {
- msg: "Final Node OnionHopData provided for us as an intermediary node",
- err_code: 0x4000 | 22,
- err_data: Vec::new(),
- }),
- };
-
- Ok(PendingHTLCInfo {
- routing: PendingHTLCRouting::Forward {
- onion_packet: outgoing_packet,
- short_channel_id,
- },
- payment_hash: msg.payment_hash,
- incoming_shared_secret: shared_secret,
- incoming_amt_msat: Some(msg.amount_msat),
- outgoing_amt_msat: amt_to_forward,
- outgoing_cltv_value,
- skimmed_fee_msat: None,
- })
-}
-
-fn create_recv_pending_htlc_info(
- hop_data: msgs::InboundOnionPayload, shared_secret: [u8; 32], payment_hash: PaymentHash,
- amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool,
- counterparty_skimmed_fee_msat: Option<u64>, current_height: u32, accept_mpp_keysend: bool,
-) -> Result<PendingHTLCInfo, InboundOnionErr> {
- let (payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, outgoing_cltv_value, payment_metadata) = match hop_data {
- msgs::InboundOnionPayload::Receive {
- payment_data, keysend_preimage, custom_tlvs, amt_msat, outgoing_cltv_value, payment_metadata, ..
- } =>
- (payment_data, keysend_preimage, custom_tlvs, amt_msat, outgoing_cltv_value, payment_metadata),
- msgs::InboundOnionPayload::BlindedReceive {
- amt_msat, total_msat, outgoing_cltv_value, payment_secret, ..
- } => {
- let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
- (Some(payment_data), None, Vec::new(), amt_msat, outgoing_cltv_value, None)
- }
- msgs::InboundOnionPayload::Forward { .. } => {
- return Err(InboundOnionErr {
- err_code: 0x4000|22,
- err_data: Vec::new(),
- msg: "Got non final data with an HMAC of 0",
- })
- },
- };
- // final_incorrect_cltv_expiry
- if outgoing_cltv_value > cltv_expiry {
- return Err(InboundOnionErr {
- msg: "Upstream node set CLTV to less than the CLTV set by the sender",
- err_code: 18,
- err_data: cltv_expiry.to_be_bytes().to_vec()
- })
- }
- // final_expiry_too_soon
- // We have to have some headroom to broadcast on chain if we have the preimage, so make sure
- // we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
- //
- // Also, ensure that, in the case of an unknown preimage for the received payment hash, our
- // payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
- // channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
- if cltv_expiry <= current_height + HTLC_FAIL_BACK_BUFFER + 1 {
- let mut err_data = Vec::with_capacity(12);
- err_data.extend_from_slice(&amt_msat.to_be_bytes());
- err_data.extend_from_slice(¤t_height.to_be_bytes());
- return Err(InboundOnionErr {
- err_code: 0x4000 | 15, err_data,
- msg: "The final CLTV expiry is too soon to handle",
- });
- }
- if (!allow_underpay && onion_amt_msat > amt_msat) ||
- (allow_underpay && onion_amt_msat >
- amt_msat.saturating_add(counterparty_skimmed_fee_msat.unwrap_or(0)))
- {
- return Err(InboundOnionErr {
- err_code: 19,
- err_data: amt_msat.to_be_bytes().to_vec(),
- msg: "Upstream node sent less than we were supposed to receive in payment",
- });
- }
-
- let routing = if let Some(payment_preimage) = keysend_preimage {
- // We need to check that the sender knows the keysend preimage before processing this
- // payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
- // could discover the final destination of X, by probing the adjacent nodes on the route
- // with a keysend payment of identical payment hash to X and observing the processing
- // time discrepancies due to a hash collision with X.
- let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
- if hashed_preimage != payment_hash {
- return Err(InboundOnionErr {
- err_code: 0x4000|22,
- err_data: Vec::new(),
- msg: "Payment preimage didn't match payment hash",
- });
- }
- if !accept_mpp_keysend && payment_data.is_some() {
- return Err(InboundOnionErr {
- err_code: 0x4000|22,
- err_data: Vec::new(),
- msg: "We don't support MPP keysend payments",
- });
- }
- PendingHTLCRouting::ReceiveKeysend {
- payment_data,
- payment_preimage,
- payment_metadata,
- incoming_cltv_expiry: outgoing_cltv_value,
- custom_tlvs,
- }
- } else if let Some(data) = payment_data {
- PendingHTLCRouting::Receive {
- payment_data: data,
- payment_metadata,
- incoming_cltv_expiry: outgoing_cltv_value,
- phantom_shared_secret,
- custom_tlvs,
- }
- } else {
- return Err(InboundOnionErr {
- err_code: 0x4000|0x2000|3,
- err_data: Vec::new(),
- msg: "We require payment_secrets",
- });
- };
- Ok(PendingHTLCInfo {
- routing,
- payment_hash,
- incoming_shared_secret: shared_secret,
- incoming_amt_msat: Some(amt_msat),
- outgoing_amt_msat: onion_amt_msat,
- outgoing_cltv_value,
- skimmed_fee_msat: counterparty_skimmed_fee_msat,
- })
-}
-
-/// Peel one layer off an incoming onion, returning [`PendingHTLCInfo`] (either Forward or Receive).
-/// This does all the relevant context-free checks that LDK requires for payment relay or
-/// acceptance. If the payment is to be received, and the amount matches the expected amount for
-/// a given invoice, this indicates the [`msgs::UpdateAddHTLC`], once fully committed in the
-/// channel, will generate an [`Event::PaymentClaimable`].
-pub fn peel_payment_onion<NS: Deref, L: Deref, T: secp256k1::Verification>(
- msg: &msgs::UpdateAddHTLC, node_signer: &NS, logger: &L, secp_ctx: &Secp256k1<T>,
- cur_height: u32, accept_mpp_keysend: bool,
-) -> Result<PendingHTLCInfo, InboundOnionErr>
-where
- NS::Target: NodeSigner,
- L::Target: Logger,
-{
- let (hop, shared_secret, next_packet_details_opt) =
- decode_incoming_update_add_htlc_onion(msg, node_signer, logger, secp_ctx
- ).map_err(|e| {
- let (err_code, err_data) = match e {
- HTLCFailureMsg::Malformed(m) => (m.failure_code, Vec::new()),
- HTLCFailureMsg::Relay(r) => (0x4000 | 22, r.reason.data),
- };
- let msg = "Failed to decode update add htlc onion";
- InboundOnionErr { msg, err_code, err_data }
- })?;
- Ok(match hop {
- onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
- let NextPacketDetails {
- next_packet_pubkey, outgoing_amt_msat: _, outgoing_scid: _, outgoing_cltv_value
- } = match next_packet_details_opt {
- Some(next_packet_details) => next_packet_details,
- // Forward should always include the next hop details
- None => return Err(InboundOnionErr {
- msg: "Failed to decode update add htlc onion",
- err_code: 0x4000 | 22,
- err_data: Vec::new(),
- }),
- };
-
- if let Err((err_msg, code)) = check_incoming_htlc_cltv(
- cur_height, outgoing_cltv_value, msg.cltv_expiry
- ) {
- return Err(InboundOnionErr {
- msg: err_msg,
- err_code: code,
- err_data: Vec::new(),
- });
- }
- create_fwd_pending_htlc_info(
- msg, next_hop_data, next_hop_hmac, new_packet_bytes, shared_secret,
- Some(next_packet_pubkey)
- )?
- },
- onion_utils::Hop::Receive(received_data) => {
- create_recv_pending_htlc_info(
- received_data, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry,
- None, false, msg.skimmed_fee_msat, cur_height, accept_mpp_keysend,
- )?
- }
- })
-}
-
-struct NextPacketDetails {
- next_packet_pubkey: Result<PublicKey, secp256k1::Error>,
- outgoing_scid: u64,
- outgoing_amt_msat: u64,
- outgoing_cltv_value: u32,
-}
-
-fn decode_incoming_update_add_htlc_onion<NS: Deref, L: Deref, T: secp256k1::Verification>(
- msg: &msgs::UpdateAddHTLC, node_signer: &NS, logger: &L, secp_ctx: &Secp256k1<T>,
-) -> Result<(onion_utils::Hop, [u8; 32], Option<NextPacketDetails>), HTLCFailureMsg>
-where
- NS::Target: NodeSigner,
- L::Target: Logger,
-{
- macro_rules! return_malformed_err {
- ($msg: expr, $err_code: expr) => {
- {
- log_info!(logger, "Failed to accept/forward incoming HTLC: {}", $msg);
- return Err(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
- channel_id: msg.channel_id,
- htlc_id: msg.htlc_id,
- sha256_of_onion: Sha256::hash(&msg.onion_routing_packet.hop_data).into_inner(),
- failure_code: $err_code,
- }));