Skip to content

Commit a346206

Browse files
authored
Merge pull request #58 from lightningdevkit/splice-all
Splice and open channels with all on-chain funds
2 parents 1a62c46 + 124178e commit a346206

6 files changed

Lines changed: 154 additions & 63 deletions

File tree

.github/workflows/tests.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ concurrency:
1111
group: ${{ github.workflow }}-${{ github.ref }}
1212
cancel-in-progress: true
1313

14+
env:
15+
RUST_BACKTRACE: 1
16+
RUST_LOG: orange_sdk=debug,graduated_rebalancer=debug,ldk_node=info,integration_tests=info,test_utils=info
17+
1418
jobs:
1519
rust_tests:
1620
name: Rust Checks
@@ -40,7 +44,7 @@ jobs:
4044
run: cargo check -p orange-cli
4145

4246
- name: Run tests
43-
run: cargo test --features _test-utils -- --test-threads=2
47+
run: cargo test --features _test-utils -- --test-threads=2 --nocapture
4448

4549
cashu_tests:
4650
name: Cashu Tests
@@ -59,4 +63,4 @@ jobs:
5963
- uses: Swatinem/rust-cache@v2.7.8
6064

6165
- name: Run cashu tests
62-
run: cargo test --features _cashu-tests -- --test-threads=2
66+
run: cargo test --features _cashu-tests -- --test-threads=2 --nocapture

graduated-rebalancer/src/lib.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,21 @@ pub trait LightningWallet: Send + Sync {
110110
/// Check if we already have a channel with the LSP
111111
fn has_channel_with_lsp(&self) -> bool;
112112

113-
/// Open a channel with the LSP using on-chain funds
113+
/// Open a channel with the LSP using all available on-chain funds
114+
/// (minus fees and anchor reserves).
114115
fn open_channel_with_lsp(
115-
&self, amt: Amount,
116+
&self,
116117
) -> Pin<Box<dyn Future<Output = Result<u128, Self::Error>> + Send + '_>>;
117118

118119
/// Wait for a channel pending notification, returns the new channel's outpoint
119120
fn await_channel_pending(
120121
&self, channel_id: u128,
121122
) -> Pin<Box<dyn Future<Output = OutPoint> + Send + '_>>;
122123

123-
/// Splice funds from on-chain to an existing channel with the LSP
124+
/// Splice all available on-chain funds (minus fees and anchor reserves) into
125+
/// an existing channel with the LSP.
124126
fn splice_to_lsp_channel(
125-
&self, amt: Amount,
127+
&self,
126128
) -> Pin<Box<dyn Future<Output = Result<u128, Self::Error>> + Send + '_>>;
127129

128130
/// Wait for a splice pending notification, returns the splice outpoint
@@ -344,7 +346,7 @@ where
344346
let (channel_outpoint, user_channel_id) = if self.ln_wallet.has_channel_with_lsp() {
345347
log_info!(self.logger, "Splicing into channel with LSP with on-chain funds");
346348

347-
let user_chan_id = match self.ln_wallet.splice_to_lsp_channel(params.amount).await {
349+
let user_chan_id = match self.ln_wallet.splice_to_lsp_channel().await {
348350
Ok(chan_id) => chan_id,
349351
Err(e) => {
350352
log_error!(self.logger, "Failed to open channel with LSP: {e:?}");
@@ -362,7 +364,7 @@ where
362364
} else {
363365
log_info!(self.logger, "Opening channel with LSP with on-chain funds");
364366

365-
let user_chan_id = match self.ln_wallet.open_channel_with_lsp(params.amount).await {
367+
let user_chan_id = match self.ln_wallet.open_channel_with_lsp().await {
366368
Ok(chan_id) => chan_id,
367369
Err(e) => {
368370
log_error!(self.logger, "Failed to open channel with LSP: {e:?}");

orange-sdk/src/lightning_wallet.rs

Lines changed: 9 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -400,20 +400,16 @@ impl LightningWallet {
400400
}
401401
}
402402

403-
pub(crate) async fn splice_balance_into_channel(
404-
&self, amount: Amount,
405-
) -> Result<UserChannelId, NodeError> {
403+
pub(crate) async fn splice_all_into_channel(&self) -> Result<UserChannelId, NodeError> {
406404
// find existing channel to splice into
407405
let channels = self.inner.ldk_node.list_channels();
408406
let channel = channels.iter().find(|c| c.counterparty_node_id == self.inner.lsp_node_id);
409407

410408
match channel {
411409
Some(chan) => {
412-
self.inner.ldk_node.splice_in(
413-
&chan.user_channel_id,
414-
chan.counterparty_node_id,
415-
amount.sats_rounding_up(),
416-
)?;
410+
self.inner
411+
.ldk_node
412+
.splice_in_with_all(&chan.user_channel_id, chan.counterparty_node_id)?;
417413
Ok(chan.user_channel_id)
418414
},
419415
None => {
@@ -424,23 +420,9 @@ impl LightningWallet {
424420
}
425421

426422
pub(crate) async fn open_channel_with_lsp(&self) -> Result<UserChannelId, NodeError> {
427-
let bal = self.inner.ldk_node.list_balances().spendable_onchain_balance_sats;
428-
429-
// need a dummy p2wsh address to estimate the fee, p2wsh is used for LN channels
430-
// let fake_addr = Address::p2wsh(Script::new(), self.inner.ldk_node.config().network);
431-
//
432-
// let fee = self
433-
// .inner
434-
// .ldk_node
435-
// .onchain_payment()
436-
// .estimate_send_all_to_address(&fake_addr, true, None)?;
437-
// todo get real fee
438-
let fee = 1000;
439-
440-
let id = self.inner.ldk_node.open_channel(
423+
let id = self.inner.ldk_node.open_channel_with_all(
441424
self.inner.lsp_node_id,
442425
self.inner.lsp_socket_addr.clone(),
443-
bal - fee,
444426
None,
445427
None,
446428
)?;
@@ -541,12 +523,9 @@ impl graduated_rebalancer::LightningWallet for LightningWallet {
541523
}
542524

543525
fn open_channel_with_lsp(
544-
&self, _amt: Amount,
526+
&self,
545527
) -> Pin<Box<dyn Future<Output = Result<u128, Self::Error>> + Send + '_>> {
546-
Box::pin(async move {
547-
// we don't use the amount and just use our full spendable balance in open_channel_with_lsp
548-
self.open_channel_with_lsp().await.map(|c| c.0)
549-
})
528+
Box::pin(async move { self.open_channel_with_lsp().await.map(|c| c.0) })
550529
}
551530

552531
fn await_channel_pending(
@@ -570,21 +549,9 @@ impl graduated_rebalancer::LightningWallet for LightningWallet {
570549
}
571550

572551
fn splice_to_lsp_channel(
573-
&self, amt: Amount,
552+
&self,
574553
) -> Pin<Box<dyn Future<Output = Result<u128, Self::Error>> + Send + '_>> {
575-
let bal = self.inner.ldk_node.list_balances();
576-
// if we don't have enough onchain balance, return error
577-
// if we are within 1,000 sats of the amount, reduce the amount to account for fees
578-
if bal.spendable_onchain_balance_sats < amt.sats_rounding_up() {
579-
return Box::pin(async move { Err(NodeError::InsufficientFunds) });
580-
} else if bal.spendable_onchain_balance_sats < amt.sats_rounding_up() + 1_000 {
581-
let reduced_amt = amt.saturating_sub(Amount::from_sats(1_000).expect("valid amount"));
582-
return Box::pin(async move {
583-
self.splice_balance_into_channel(reduced_amt).await.map(|c| c.0)
584-
});
585-
}
586-
587-
Box::pin(async move { self.splice_balance_into_channel(amt).await.map(|c| c.0) })
554+
Box::pin(async move { self.splice_all_into_channel().await.map(|c| c.0) })
588555
}
589556

590557
fn await_splice_pending(

orange-sdk/src/trusted_wallet/dummy.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ impl DummyTrustedWallet {
166166
.await
167167
.unwrap();
168168
}
169+
170+
let _ = payment_success_sender.send(());
169171
},
170172
Event::PaymentReceived { payment_id, amount_msat, payment_hash, .. } => {
171173
// convert id
@@ -258,10 +260,8 @@ impl DummyTrustedWallet {
258260
DummyTrustedWallet { current_bal_msats, payments, ldk_node, payment_success_flag }
259261
}
260262

261-
pub(crate) async fn await_payment_success(&self) {
262-
let mut flag = self.payment_success_flag.clone();
263-
flag.mark_unchanged();
264-
let _ = flag.changed().await;
263+
fn payment_wait_timeout() -> Duration {
264+
if std::env::var("CI").is_ok() { Duration::from_secs(120) } else { Duration::from_secs(20) }
265265
}
266266
}
267267

@@ -384,6 +384,8 @@ impl TrustedWalletInterface for DummyTrustedWallet {
384384
) -> Pin<Box<dyn Future<Output = Option<ReceivedLightningPayment>> + Send + '_>> {
385385
Box::pin(async move {
386386
let id = channelmanager::PaymentId(payment_hash);
387+
let mut flag = self.payment_success_flag.clone();
388+
flag.mark_unchanged();
387389
loop {
388390
if let Some(payment) = self.ldk_node.payment(&id) {
389391
let counterparty_skimmed_fee_msat = match payment.kind {
@@ -408,7 +410,12 @@ impl TrustedWalletInterface for DummyTrustedWallet {
408410
PaymentStatus::Failed => return None,
409411
}
410412
}
411-
self.await_payment_success().await;
413+
if !matches!(
414+
tokio::time::timeout(Self::payment_wait_timeout(), flag.changed()).await,
415+
Ok(Ok(()))
416+
) {
417+
return None;
418+
}
412419
}
413420
})
414421
}

0 commit comments

Comments
 (0)