Skip to content

Commit

Permalink
ability to signal channel open failure
Browse files Browse the repository at this point in the history
  • Loading branch information
johncantrell97 committed May 17, 2024
1 parent 30e80d4 commit 494a03c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 8 deletions.
17 changes: 10 additions & 7 deletions src/lsps2/payment_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ impl PaymentQueue {
position.map(|position| self.payments.remove(position))
}

pub(crate) fn clear(&mut self) -> Vec<InterceptedHTLC> {
self.payments.drain(..).map(|(_k, v)| v).flatten().collect()
pub(crate) fn clear(&mut self) -> Vec<(PaymentHash, Vec<InterceptedHTLC>)> {
self.payments.drain(..).collect()
}
}

Expand Down Expand Up @@ -109,11 +109,14 @@ mod tests {
);
assert_eq!(
payment_queue.clear(),
vec![InterceptedHTLC {
intercept_id: InterceptId([1; 32]),
expected_outbound_amount_msat: 300_000_000,
payment_hash: PaymentHash([101; 32]),
}]
vec![(
PaymentHash([101; 32]),
vec![InterceptedHTLC {
intercept_id: InterceptId([1; 32]),
expected_outbound_amount_msat: 300_000_000,
payment_hash: PaymentHash([101; 32]),
}]
)]
);
}
}
69 changes: 68 additions & 1 deletion src/lsps2/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,13 @@ impl OutboundJITChannelState {
let mut payment_queue_lock = payment_queue.lock().unwrap();
let payment_forwarded =
OutboundJITChannelState::PaymentForwarded { channel_id: *channel_id };
let forward_htlcs = ForwardHTLCsAction(*channel_id, payment_queue_lock.clear());
let htlcs = payment_queue_lock
.clear()
.into_iter()
.map(|(_, htlcs)| htlcs)
.flatten()
.collect();
let forward_htlcs = ForwardHTLCsAction(*channel_id, htlcs);
Ok((payment_forwarded, Some(forward_htlcs)))
},
OutboundJITChannelState::PaymentForwarded { channel_id } => {
Expand Down Expand Up @@ -898,6 +904,67 @@ where
Ok(())
}

/// Used by LSP to fail intercepted htlcs backwards when the channel open fails for any reason.
///
/// Should be called in response to receiving a [`LSPS2ServiceEvent::OpenChannel`] event.
///
/// The JIT channel state is reset such that the payer can attempt payment again.
/// [`LSPS2ServiceEvent::OpenChannel`]: crate::lsps2::event::LSPS2ServiceEvent::OpenChannel
pub fn channel_open_failed(
&self, counterparty_node_id: &PublicKey, intercept_scid: u64,
) -> Result<(), APIError> {
let outer_state_lock = self.per_peer_state.read().unwrap();
match outer_state_lock.get(counterparty_node_id) {
Some(inner_state_lock) => {
let mut peer_state = inner_state_lock.lock().unwrap();

if let Some(jit_channel) =
peer_state.outbound_channels_by_intercept_scid.get_mut(&intercept_scid)
{
let new_state = if let OutboundJITChannelState::PendingChannelOpen {
payment_queue,
..
} = &jit_channel.state
{
let mut queue = payment_queue.lock().unwrap();
let payment_hashes = queue
.clear()
.into_iter()
.map(|(payment_hash, _)| payment_hash)
.collect::<Vec<_>>();
for payment_hash in payment_hashes {
self.channel_manager.get_cm().fail_htlc_backwards_with_reason(
&payment_hash,
FailureCode::TemporaryNodeFailure,
);
}
OutboundJITChannelState::PendingInitialPayment {
payment_queue: payment_queue.clone(),
}
} else {
return Err(APIError::APIMisuseError {
err: format!("Channel is not in the PendingChannelOpen state.",),
});
};
jit_channel.state = new_state;
} else {
return Err(APIError::APIMisuseError {
err: format!(
"Could not find a channel with intercept_scid {}",
intercept_scid
),
});
}
},
None => {
return Err(APIError::APIMisuseError {
err: format!("No counterparty state for: {}", counterparty_node_id),
});
},
}
Ok(())
}

/// Forward [`Event::ChannelReady`] event parameters into this function.
///
/// Will forward the intercepted HTLC if it matches a channel
Expand Down

0 comments on commit 494a03c

Please sign in to comment.