Skip to content

Commit 063b758

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 6dd1ec1 commit 063b758

File tree

1 file changed

+55
-47
lines changed

1 file changed

+55
-47
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2913,6 +2913,59 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
29132913
}
29142914
}
29152915

2916+
macro_rules! check_total_value {
2917+
($payment_data_total_msat: expr, $payment_secret: expr, $payment_preimage: expr) => {{
2918+
let mut total_value = 0;
2919+
let mut payment_received_generated = false;
2920+
let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
2921+
.or_insert(Vec::new());
2922+
if htlcs.len() == 1 {
2923+
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
2924+
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));
2925+
fail_htlc!(claimable_htlc);
2926+
continue
2927+
}
2928+
}
2929+
htlcs.push(claimable_htlc);
2930+
for htlc in htlcs.iter() {
2931+
total_value += htlc.value;
2932+
match &htlc.onion_payload {
2933+
OnionPayload::Invoice(htlc_payment_data) => {
2934+
if htlc_payment_data.total_msat != $payment_data_total_msat {
2935+
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
2936+
log_bytes!(payment_hash.0), $payment_data_total_msat, htlc_payment_data.total_msat);
2937+
total_value = msgs::MAX_VALUE_MSAT;
2938+
}
2939+
if total_value >= msgs::MAX_VALUE_MSAT { break; }
2940+
},
2941+
_ => unreachable!(),
2942+
}
2943+
}
2944+
if total_value >= msgs::MAX_VALUE_MSAT || total_value > $payment_data_total_msat {
2945+
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)",
2946+
log_bytes!(payment_hash.0), total_value, $payment_data_total_msat);
2947+
for htlc in htlcs.iter() {
2948+
fail_htlc!(htlc);
2949+
}
2950+
} else if total_value == $payment_data_total_msat {
2951+
new_events.push(events::Event::PaymentReceived {
2952+
payment_hash,
2953+
purpose: events::PaymentPurpose::InvoicePayment {
2954+
payment_preimage: $payment_preimage,
2955+
payment_secret: $payment_secret,
2956+
},
2957+
amt: total_value,
2958+
});
2959+
payment_received_generated = true;
2960+
} else {
2961+
// Nothing to do - we haven't reached the total
2962+
// payment value yet, wait until we receive more
2963+
// MPP parts.
2964+
}
2965+
payment_received_generated
2966+
}}
2967+
}
2968+
29162969
// Check that the payment hash and secret are known. Note that we
29172970
// MUST take care to handle the "unknown payment hash" and
29182971
// "incorrect payment secret" cases here identically or we'd expose
@@ -2962,54 +3015,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
29623015
log_bytes!(payment_hash.0), payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap());
29633016
fail_htlc!(claimable_htlc);
29643017
} else {
2965-
let mut total_value = 0;
2966-
let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
2967-
.or_insert(Vec::new());
2968-
if htlcs.len() == 1 {
2969-
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
2970-
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));
2971-
fail_htlc!(claimable_htlc);
2972-
continue
2973-
}
2974-
}
2975-
htlcs.push(claimable_htlc);
2976-
for htlc in htlcs.iter() {
2977-
total_value += htlc.value;
2978-
match &htlc.onion_payload {
2979-
OnionPayload::Invoice(htlc_payment_data) => {
2980-
if htlc_payment_data.total_msat != payment_data.total_msat {
2981-
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})",
2982-
log_bytes!(payment_hash.0), payment_data.total_msat, htlc_payment_data.total_msat);
2983-
total_value = msgs::MAX_VALUE_MSAT;
2984-
}
2985-
if total_value >= msgs::MAX_VALUE_MSAT { break; }
2986-
},
2987-
_ => unreachable!(),
2988-
}
2989-
}
2990-
if total_value >= msgs::MAX_VALUE_MSAT || total_value > payment_data.total_msat {
2991-
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)",
2992-
log_bytes!(payment_hash.0), total_value, payment_data.total_msat);
2993-
for htlc in htlcs.iter() {
2994-
fail_htlc!(htlc);
2995-
}
2996-
} else if total_value == payment_data.total_msat {
2997-
new_events.push(events::Event::PaymentReceived {
2998-
payment_hash,
2999-
purpose: events::PaymentPurpose::InvoicePayment {
3000-
payment_preimage: inbound_payment.get().payment_preimage,
3001-
payment_secret: payment_data.payment_secret,
3002-
},
3003-
amt: total_value,
3004-
});
3005-
// Only ever generate at most one PaymentReceived
3006-
// per registered payment_hash, even if it isn't
3007-
// claimed.
3018+
let payment_received_generated = check_total_value!(payment_data.total_msat, payment_data.payment_secret, inbound_payment.get().payment_preimage);
3019+
if payment_received_generated {
30083020
inbound_payment.remove_entry();
3009-
} else {
3010-
// Nothing to do - we haven't reached the total
3011-
// payment value yet, wait until we receive more
3012-
// MPP parts.
30133021
}
30143022
}
30153023
},

0 commit comments

Comments
 (0)