/// Route hints used in constructing invoices for [phantom node payents].
///
/// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
+#[derive(Clone)]
pub struct PhantomRouteHints {
/// The list of channels to be included in the invoice route hints.
pub channels: Vec<ChannelDetails>,
let mut channel_state = self.channel_state.lock().unwrap();
match channel_state.by_id.entry(temporary_channel_id) {
hash_map::Entry::Occupied(_) => {
- if cfg!(feature = "fuzztarget") {
+ if cfg!(fuzzing) {
return Err(APIError::APIMisuseError { err: "Fuzzy bad RNG".to_owned() });
} else {
panic!("RNG is bad???");
// the channel is now on chain and our counterparty is
// trying to broadcast the HTLC-Timeout, but that's their
// problem, not ours.
- //
- // `fail_htlc_backwards_internal` is never called for
- // phantom payments, so this is unreachable for them.
}
}
}
macro_rules! check_total_value {
($payment_data_total_msat: expr, $payment_secret: expr, $payment_preimage: expr) => {{
- let mut total_value = 0;
let mut payment_received_generated = false;
let htlcs = channel_state.claimable_htlcs.entry(payment_hash)
.or_insert(Vec::new());
continue
}
}
- htlcs.push(claimable_htlc);
+ let mut total_value = claimable_htlc.value;
for htlc in htlcs.iter() {
total_value += htlc.value;
match &htlc.onion_payload {
if total_value >= msgs::MAX_VALUE_MSAT || total_value > $payment_data_total_msat {
log_trace!(self.logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)",
log_bytes!(payment_hash.0), total_value, $payment_data_total_msat);
- for htlc in htlcs.iter() {
- fail_htlc!(htlc);
- }
+ fail_htlc!(claimable_htlc);
} else if total_value == $payment_data_total_msat {
+ htlcs.push(claimable_htlc);
new_events.push(events::Event::PaymentReceived {
payment_hash,
purpose: events::PaymentPurpose::InvoicePayment {
// Nothing to do - we haven't reached the total
// payment value yet, wait until we receive more
// MPP parts.
+ htlcs.push(claimable_htlc);
}
payment_received_generated
}}
pending_events.push(path_failure);
if let Some(ev) = full_failure_ev { pending_events.push(ev); }
},
- HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id, htlc_id, incoming_packet_shared_secret, .. }) => {
+ HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id, htlc_id, incoming_packet_shared_secret, phantom_shared_secret, .. }) => {
let err_packet = match onion_error {
HTLCFailReason::Reason { failure_code, data } => {
log_trace!(self.logger, "Failing HTLC with payment_hash {} backwards from us with code {}", log_bytes!(payment_hash.0), failure_code);
- let packet = onion_utils::build_failure_packet(&incoming_packet_shared_secret, failure_code, &data[..]).encode();
- onion_utils::encrypt_failure_packet(&incoming_packet_shared_secret, &packet)
+ if let Some(phantom_ss) = phantom_shared_secret {
+ let phantom_packet = onion_utils::build_failure_packet(&phantom_ss, failure_code, &data[..]).encode();
+ let encrypted_phantom_packet = onion_utils::encrypt_failure_packet(&phantom_ss, &phantom_packet);
+ onion_utils::encrypt_failure_packet(&incoming_packet_shared_secret, &encrypted_phantom_packet.data[..])
+ } else {
+ let packet = onion_utils::build_failure_packet(&incoming_packet_shared_secret, failure_code, &data[..]).encode();
+ onion_utils::encrypt_failure_packet(&incoming_packet_shared_secret, &packet)
+ }
},
HTLCFailReason::LightningError { err } => {
log_trace!(self.logger, "Failing HTLC with payment_hash {} backwards with pre-built LightningError", log_bytes!(payment_hash.0));
onion_utils::build_first_hop_failure_packet(incoming_shared_secret, error_code, &{
let mut res = Vec::with_capacity(8 + 128);
// TODO: underspecified, follow https://github.com/lightningnetwork/lightning-rfc/issues/791
- res.extend_from_slice(&byte_utils::be16_to_array(0));
+ if error_code == 0x1000 | 20 {
+ res.extend_from_slice(&byte_utils::be16_to_array(0));
+ }
res.extend_from_slice(&upd.encode_with_len()[..]);
res
}[..])
/// In chanmon_consistency_target, we'd like to be able to restore monitor updating without
/// handling all pending events (i.e. not PendingHTLCsForwardable). Thus, we expose monitor
/// update events as a separate process method here.
- #[cfg(feature = "fuzztarget")]
+ #[cfg(fuzzing)]
pub fn process_monitor_events(&self) {
self.process_pending_monitor_events();
}
}
}
- #[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))]
+ #[cfg(any(test, fuzzing, feature = "_test_utils"))]
pub fn get_and_clear_pending_events(&self) -> Vec<events::Event> {
let events = core::cell::RefCell::new(Vec::new());
let event_handler = |event: &events::Event| events.borrow_mut().push(event.clone());