Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

greenlight: wait for channel reestablished #1093

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions libs/sdk-core/src/greenlight/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use serde_json::{json, Map, Value};
use strum_macros::{Display, EnumString};
use tokio::join;
use tokio::sync::{mpsc, watch, Mutex};
use tokio::time::{sleep, MissedTickBehavior};
use tokio::time::{sleep, Instant, MissedTickBehavior};
use tokio_stream::StreamExt;
use tonic::Streaming;

Expand Down Expand Up @@ -888,6 +888,67 @@ impl Greenlight {
let outbound_payments = update_payment_expirations(outbound_payments, htlc_list)?;
Ok((outbound_payments, new_state))
}

async fn wait_channel_reestablished(&self, path: &PaymentPath) -> NodeResult<()> {
let deadline =
Instant::now()
.checked_add(Duration::from_secs(20))
.ok_or(NodeError::generic(
"Failed to set channel establishment deadline",
))?;

while Instant::now().le(&deadline) && !self.poll_channel_reestablished(path).await? {
tokio::time::sleep(Duration::from_millis(50)).await
}

Ok(())
JssDWt marked this conversation as resolved.
Show resolved Hide resolved
}

async fn poll_channel_reestablished(&self, path: &PaymentPath) -> NodeResult<bool> {
let edge = match path.edges.first() {
Some(edge) => edge,
None => return Err(NodeError::generic("Channel not found")),
};
let mut client = self.get_node_client().await?;
let res = client
.list_peer_channels(cln::ListpeerchannelsRequest {
id: Some(edge.node_id.clone()),
})
.await?
.into_inner();
let channel = match res.channels.iter().find(|c| {
match (
c.alias.as_ref().and_then(|a| a.local.as_ref()),
c.short_channel_id.as_ref(),
) {
(Some(alias), Some(short_channel_id)) => {
*alias == edge.short_channel_id || *short_channel_id == edge.short_channel_id
}
(Some(alias), None) => *alias == edge.short_channel_id,
(None, Some(short_channel_id)) => *short_channel_id == edge.short_channel_id,
(None, None) => false,
}
}) {
Some(channel) => channel,
None => return Err(NodeError::generic("Channel not found")),
};

if let Some(peer_connected) = channel.peer_connected {
if !peer_connected {
return Ok(false);
}
}

if !channel
.status
JssDWt marked this conversation as resolved.
Show resolved Hide resolved
.iter()
.any(|s| s.contains("Channel ready") || s.contains("Reconnected, and reestablished"))
{
return Ok(false);
}

Ok(true)
}
}

fn add_amount_sent(
Expand Down Expand Up @@ -1205,7 +1266,7 @@ impl NodeAPI for Greenlight {
"send_pay route to pay: {:?}, received_amount = {}",
route, to_pay_msat
);

self.wait_channel_reestablished(&max.path).await?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know greenlight has a mechanism to wait for channel re-establishment before attempting to pay, what is the benefit of adding such mechanism on the client too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or perhaps this mechanism doesn't exist in send_pay and that's why it is added here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or perhaps this mechanism doesn't exist in send_pay and that's why it is added here?

exactly: Blockstream/greenlight#522

// We send the part using the node API
client
.send_pay(SendpayRequest {
Expand Down
Loading