+ let inbound_pmt_key_material = args.keys_manager.get_inbound_payment_key_material();
+ let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material);
+
+ let mut claimable_htlcs = HashMap::with_capacity(claimable_htlcs_list.len());
+ if let Some(mut purposes) = claimable_htlc_purposes {
+ if purposes.len() != claimable_htlcs_list.len() {
+ return Err(DecodeError::InvalidValue);
+ }
+ for (purpose, (payment_hash, previous_hops)) in purposes.drain(..).zip(claimable_htlcs_list.drain(..)) {
+ claimable_htlcs.insert(payment_hash, (purpose, previous_hops));
+ }
+ } else {
+ // LDK versions prior to 0.0.107 did not write a `pending_htlc_purposes`, but do
+ // include a `_legacy_hop_data` in the `OnionPayload`.
+ for (payment_hash, previous_hops) in claimable_htlcs_list.drain(..) {
+ if previous_hops.is_empty() {
+ return Err(DecodeError::InvalidValue);
+ }
+ let purpose = match &previous_hops[0].onion_payload {
+ OnionPayload::Invoice { _legacy_hop_data } => {
+ if let Some(hop_data) = _legacy_hop_data {
+ events::PaymentPurpose::InvoicePayment {
+ payment_preimage: match pending_inbound_payments.get(&payment_hash) {
+ Some(inbound_payment) => inbound_payment.payment_preimage,
+ None => match inbound_payment::verify(payment_hash, &hop_data, 0, &expanded_inbound_key, &args.logger) {
+ Ok(payment_preimage) => payment_preimage,
+ Err(()) => {
+ log_error!(args.logger, "Failed to read claimable payment data for HTLC with payment hash {} - was not a pending inbound payment and didn't match our payment key", log_bytes!(payment_hash.0));
+ return Err(DecodeError::InvalidValue);
+ }
+ }
+ },
+ payment_secret: hop_data.payment_secret,
+ }
+ } else { return Err(DecodeError::InvalidValue); }
+ },
+ OnionPayload::Spontaneous(payment_preimage) =>
+ events::PaymentPurpose::SpontaneousPayment(*payment_preimage),
+ };
+ claimable_htlcs.insert(payment_hash, (purpose, previous_hops));
+ }
+ }
+