Skip to content

Commit 10ceda5

Browse files
Macro-ize checking that the total value of an MPP's parts is sane
This DRY-ed code will be used in upcoming commits when we stop storing inbound payment data
1 parent 1df58c8 commit 10ceda5

File tree

1 file changed

+51
-49
lines changed

1 file changed

+51
-49
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,6 +2804,56 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28042804
}
28052805
}
28062806

2807+
macro_rules! check_total_value {
2808+
($payment_data_total_msat: expr, $payment_secret: expr, $payment_preimage: expr) => {
2809+
let mut total_value = 0;
2810+
let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
2811+
.or_insert(Vec::new());
2812+
if htlcs.len() == 1 {
2813+
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
2814+
log_trace!(self.logger, "Failing new HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash", log_bytes!(payment_hash.0));
2815+
fail_htlc!(claimable_htlc);
2816+
continue
2817+
}
2818+
}
2819+
htlcs.push(claimable_htlc);
2820+
for htlc in htlcs.iter() {
2821+
total_value += htlc.value;
2822+
match &htlc.onion_payload {
2823+
OnionPayload::Invoice(htlc_payment_data) => {
2824+
if htlc_payment_data.total_msat != $payment_data_total_msat {
2825+
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
2826+
log_bytes!(payment_hash.0), $payment_data_total_msat, htlc_payment_data.total_msat);
2827+
total_value = msgs::MAX_VALUE_MSAT;
2828+
}
2829+
if total_value >= msgs::MAX_VALUE_MSAT { break; }
2830+
},
2831+
_ => unreachable!(),
2832+
}
2833+
}
2834+
if total_value >= msgs::MAX_VALUE_MSAT || total_value > $payment_data_total_msat {
2835+
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)",
2836+
log_bytes!(payment_hash.0), total_value, $payment_data_total_msat);
2837+
for htlc in htlcs.iter() {
2838+
fail_htlc!(htlc);
2839+
}
2840+
} else if total_value == $payment_data_total_msat {
2841+
new_events.push(events::Event::PaymentReceived {
2842+
payment_hash,
2843+
purpose: events::PaymentPurpose::InvoicePayment {
2844+
payment_preimage: $payment_preimage,
2845+
payment_secret: $payment_secret,
2846+
},
2847+
amt: total_value,
2848+
});
2849+
} else {
2850+
// Nothing to do - we haven't reached the total
2851+
// payment value yet, wait until we receive more
2852+
// MPP parts.
2853+
}
2854+
}
2855+
}
2856+
28072857
// Check that the payment hash and secret are known. Note that we
28082858
// MUST take care to handle the "unknown payment hash" and
28092859
// "incorrect payment secret" cases here identically or we'd expose
@@ -2853,55 +2903,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
28532903
log_bytes!(payment_hash.0), payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap());
28542904
fail_htlc!(claimable_htlc);
28552905
} else {
2856-
let mut total_value = 0;
2857-
let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
2858-
.or_insert(Vec::new());
2859-
if htlcs.len() == 1 {
2860-
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
2861-
log_trace!(self.logger, "Failing new HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash", log_bytes!(payment_hash.0));
2862-
fail_htlc!(claimable_htlc);
2863-
continue
2864-
}
2865-
}
2866-
htlcs.push(claimable_htlc);
2867-
for htlc in htlcs.iter() {
2868-
total_value += htlc.value;
2869-
match &htlc.onion_payload {
2870-
OnionPayload::Invoice(htlc_payment_data) => {
2871-
if htlc_payment_data.total_msat != payment_data.total_msat {
2872-
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
2873-
log_bytes!(payment_hash.0), payment_data.total_msat, htlc_payment_data.total_msat);
2874-
total_value = msgs::MAX_VALUE_MSAT;
2875-
}
2876-
if total_value >= msgs::MAX_VALUE_MSAT { break; }
2877-
},
2878-
_ => unreachable!(),
2879-
}
2880-
}
2881-
if total_value >= msgs::MAX_VALUE_MSAT || total_value > payment_data.total_msat {
2882-
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)",
2883-
log_bytes!(payment_hash.0), total_value, payment_data.total_msat);
2884-
for htlc in htlcs.iter() {
2885-
fail_htlc!(htlc);
2886-
}
2887-
} else if total_value == payment_data.total_msat {
2888-
new_events.push(events::Event::PaymentReceived {
2889-
payment_hash,
2890-
purpose: events::PaymentPurpose::InvoicePayment {
2891-
payment_preimage: inbound_payment.get().payment_preimage,
2892-
payment_secret: payment_data.payment_secret,
2893-
},
2894-
amt: total_value,
2895-
});
2896-
// Only ever generate at most one PaymentReceived
2897-
// per registered payment_hash, even if it isn't
2898-
// claimed.
2899-
inbound_payment.remove_entry();
2900-
} else {
2901-
// Nothing to do - we haven't reached the total
2902-
// payment value yet, wait until we receive more
2903-
// MPP parts.
2904-
}
2906+
check_total_value!(payment_data.total_msat, payment_data.payment_secret, inbound_payment.get().payment_preimage);
29052907
}
29062908
},
29072909
};

0 commit comments

Comments
 (0)