Skip to content

Commit 02b6f29

Browse files
committed
WIP: splice in
1 parent 5915a3d commit 02b6f29

9 files changed

Lines changed: 312 additions & 23 deletions

File tree

examples/cli/src/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ impl WalletState {
192192
fee_msat
193193
);
194194
},
195+
Event::SplicePending { new_funding_txo, .. } => {
196+
println!(
197+
"{} Splice pending: {}",
198+
"🔄".bright_yellow(),
199+
new_funding_txo
200+
);
201+
},
195202
}
196203

197204
w.event_handled().unwrap();

graduated-rebalancer/src/lib.rs

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ pub trait LightningWallet: Send + Sync {
108108
&self, payment_hash: [u8; 32],
109109
) -> Pin<Box<dyn Future<Output = Option<ReceivedLightningPayment>> + Send + '_>>;
110110

111+
/// Check if we already have a channel with the LSP
112+
fn has_channel_with_lsp(&self) -> bool;
113+
111114
/// Open a channel with the LSP using on-chain funds
112115
fn open_channel_with_lsp(
113116
&self, amt: Amount,
@@ -117,6 +120,16 @@ pub trait LightningWallet: Send + Sync {
117120
fn await_channel_pending(
118121
&self, channel_id: u128,
119122
) -> Pin<Box<dyn Future<Output = OutPoint> + Send + '_>>;
123+
124+
/// Splice funds from on-chain to an existing channel with the LSP
125+
fn splice_to_lsp_channel(
126+
&self, amt: Amount,
127+
) -> Pin<Box<dyn Future<Output = Result<u128, Self::Error>> + Send + '_>>;
128+
129+
/// Wait for a splice pending notification, returns the splice outpoint
130+
fn await_splice_pending(
131+
&self, channel_id: u128,
132+
) -> Pin<Box<dyn Future<Output = OutPoint> + Send + '_>>;
120133
}
121134

122135
/// Represents a payment from the lightning wallet
@@ -313,32 +326,51 @@ where
313326
}
314327
}
315328

316-
/// Perform on-chain to lightning rebalance by opening a channel
329+
/// Perform on-chain to lightning rebalance by opening a channel or splicing into an existing one
317330
async fn do_onchain_rebalance(&self, params: TriggerParams) {
318-
// This should open a channel with the LSP using available on-chain funds
319-
320331
let _ = self.balance_mutex.lock().await;
321332

322-
log_info!(self.logger, "Opening channel with LSP with on-chain funds");
333+
let (channel_outpoint, user_channel_id) = if self.ln_wallet.has_channel_with_lsp() {
334+
log_info!(self.logger, "Splicing into channel with LSP with on-chain funds");
323335

324-
// todo for now we can only open a channel, eventually move to splicing
325-
let user_chan_id = match self.ln_wallet.open_channel_with_lsp(params.amount).await {
326-
Ok(chan_id) => chan_id,
327-
Err(e) => {
328-
log_error!(self.logger, "Failed to open channel with LSP: {e:?}");
329-
return;
330-
},
331-
};
336+
let user_chan_id = match self.ln_wallet.splice_to_lsp_channel(params.amount).await {
337+
Ok(chan_id) => chan_id,
338+
Err(e) => {
339+
log_error!(self.logger, "Failed to open channel with LSP: {e:?}");
340+
return;
341+
},
342+
};
343+
344+
log_info!(self.logger, "Initiated splice opened with LSP");
345+
346+
let channel_outpoint = self.ln_wallet.await_splice_pending(user_chan_id).await;
347+
348+
log_info!(self.logger, "Splice initiated at: {channel_outpoint}");
349+
350+
(channel_outpoint, user_chan_id)
351+
} else {
352+
log_info!(self.logger, "Opening channel with LSP with on-chain funds");
332353

333-
log_info!(self.logger, "Initiated channel opened with LSP");
354+
let user_chan_id = match self.ln_wallet.open_channel_with_lsp(params.amount).await {
355+
Ok(chan_id) => chan_id,
356+
Err(e) => {
357+
log_error!(self.logger, "Failed to open channel with LSP: {e:?}");
358+
return;
359+
},
360+
};
361+
362+
log_info!(self.logger, "Initiated channel opened with LSP");
334363

335-
let channel_outpoint = self.ln_wallet.await_channel_pending(user_chan_id).await;
364+
let channel_outpoint = self.ln_wallet.await_channel_pending(user_chan_id).await;
336365

337-
log_info!(self.logger, "Channel open succeeded at: {channel_outpoint}",);
366+
log_info!(self.logger, "Channel open succeeded at: {channel_outpoint}");
367+
368+
(channel_outpoint, user_chan_id)
369+
};
338370

339371
self.event_handler.handle_event(RebalancerEvent::OnChainRebalanceInitiated {
340372
trigger_id: params.id,
341-
user_channel_id: user_chan_id,
373+
user_channel_id,
342374
channel_outpoint,
343375
});
344376
}

orange-sdk/src/event.rs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ pub enum Event {
131131
/// The fee paid, in msats, for the rebalance payment.
132132
fee_msat: u64,
133133
},
134+
/// We have initiated a splice and are waiting for it to confirm.
135+
SplicePending {
136+
/// The `channel_id` of the channel.
137+
channel_id: ChannelId,
138+
/// The `user_channel_id` of the channel.
139+
user_channel_id: UserChannelId,
140+
/// The `node_id` of the channel counterparty.
141+
counterparty_node_id: PublicKey,
142+
/// The outpoint of the channel's splice funding transaction.
143+
new_funding_txo: OutPoint,
144+
},
134145
}
135146

136147
impl_writeable_tlv_based_enum!(Event,
@@ -182,6 +193,12 @@ impl_writeable_tlv_based_enum!(Event,
182193
(6, amount_msat, required),
183194
(8, fee_msat, required),
184195
},
196+
(8, SplicePending) => {
197+
(1, channel_id, required),
198+
(3, counterparty_node_id, required),
199+
(5, user_channel_id, required),
200+
(7, new_funding_txo, required),
201+
},
185202
);
186203

187204
/// A queue for events emitted by the [`Wallet`].
@@ -301,6 +318,7 @@ pub(crate) struct LdkEventHandler {
301318
pub(crate) tx_metadata: store::TxMetadataStore,
302319
pub(crate) payment_receipt_sender: watch::Sender<()>,
303320
pub(crate) channel_pending_sender: watch::Sender<u128>,
321+
pub(crate) splice_pending_sender: watch::Sender<u128>,
304322
pub(crate) logger: Arc<Logger>,
305323
}
306324

@@ -415,11 +433,28 @@ impl LdkEventHandler {
415433
return;
416434
}
417435
},
418-
ldk_node::Event::SplicePending { .. } => {
419-
log_debug!(self.logger, "Received SplicePending event");
436+
ldk_node::Event::SplicePending {
437+
channel_id,
438+
user_channel_id,
439+
counterparty_node_id,
440+
new_funding_txo,
441+
} => {
442+
log_debug!(self.logger, "Received SplicePending event {event:?}");
443+
let _ = self.splice_pending_sender.send(user_channel_id.0);
444+
445+
if let Err(e) = self.event_queue.add_event(Event::SplicePending {
446+
channel_id,
447+
user_channel_id,
448+
counterparty_node_id,
449+
new_funding_txo,
450+
}) {
451+
log_error!(self.logger, "Failed to add SplicePending event: {e:?}");
452+
return;
453+
}
420454
},
421455
ldk_node::Event::SpliceFailed { .. } => {
422-
log_debug!(self.logger, "Received SpliceFailed event");
456+
println!("===========splice failed============");
457+
log_warn!(self.logger, "Received SpliceFailed event: {event:?}");
423458
},
424459
}
425460

orange-sdk/src/ffi/orange/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,17 @@ pub enum Event {
262262
/// The fee paid, in msats, for the rebalance payment.
263263
fee_msat: u64,
264264
},
265+
/// We have initiated a splice and are waiting for it to confirm.
266+
SplicePending {
267+
/// The `channel_id` of the channel.
268+
channel_id: Vec<u8>,
269+
/// The `user_channel_id` of the channel.
270+
user_channel_id: Vec<u8>,
271+
/// The `node_id` of the channel counterparty.
272+
counterparty_node_id: Vec<u8>,
273+
/// The outpoint of the channel's splice funding transaction.
274+
new_funding_txo: String,
275+
},
265276
}
266277

267278
impl From<OrangeEvent> for Event {
@@ -349,6 +360,17 @@ impl From<OrangeEvent> for Event {
349360
amount_msat,
350361
fee_msat,
351362
},
363+
OrangeEvent::SplicePending {
364+
channel_id,
365+
user_channel_id,
366+
counterparty_node_id,
367+
new_funding_txo,
368+
} => Event::SplicePending {
369+
channel_id: channel_id.0.to_vec(),
370+
user_channel_id: user_channel_id.0.to_be_bytes().to_vec(),
371+
counterparty_node_id: counterparty_node_id.serialize().to_vec(),
372+
new_funding_txo: new_funding_txo.to_string(),
373+
},
352374
}
353375
}
354376
}

orange-sdk/src/lib.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![deny(missing_docs)]
1+
#![deny(missing_docs)]
22

33
//! A library implementing the full backend for a modern, highly usable, Bitcoin wallet focusing on
44
//! maximizing security and self-custody without trading off user experience.
@@ -665,11 +665,14 @@ impl Wallet {
665665
/// Lists the transactions which have been made.
666666
pub async fn list_transactions(&self) -> Result<Vec<Transaction>, WalletError> {
667667
let trusted_payments = self.inner.trusted.list_payments().await?;
668-
let lightning_payments = self.inner.ln_wallet.list_payments();
668+
let mut lightning_payments = self.inner.ln_wallet.list_payments();
669+
lightning_payments.sort_by_key(|l| l.latest_update_timestamp);
669670

670671
let mut res = Vec::with_capacity(trusted_payments.len() + lightning_payments.len());
671672
let tx_metadata = self.inner.tx_metadata.read();
672673

674+
println!("\n\n=======================");
675+
673676
let mut internal_transfers = HashMap::new();
674677
#[derive(Debug, Default)]
675678
struct InternalTransfer {
@@ -773,6 +776,7 @@ impl Wallet {
773776
});
774777
}
775778
}
779+
println!("ln payments: {:#?}", lightning_payments);
776780
for payment in lightning_payments {
777781
use ldk_node::payment::PaymentDirection;
778782
let lightning_receive_fee = match payment.kind {
@@ -792,6 +796,10 @@ impl Wallet {
792796
),
793797
};
794798
if let Some(tx_metadata) = tx_metadata.get(&PaymentId::SelfCustodial(payment.id.0)) {
799+
println!(
800+
"Found metadata for lightning payment {} got {:?}",
801+
payment.id, tx_metadata.ty
802+
);
795803
match &tx_metadata.ty {
796804
TxType::TrustedToLightning {
797805
trusted_payment: _,
@@ -814,6 +822,7 @@ impl Wallet {
814822
.or_insert(InternalTransfer::default());
815823
if &payment.id.0 == channel_txid.as_byte_array() {
816824
debug_assert!(entry.send_fee.is_none());
825+
println!("onchain to ln fee: {:?}", payment.fee_paid_msat);
817826
entry.send_fee = payment
818827
.fee_paid_msat
819828
.map(|fee| Amount::from_milli_sats(fee).expect("Must be valid"));
@@ -831,6 +840,8 @@ impl Wallet {
831840
});
832841
debug_assert!(entry.transaction.is_none());
833842

843+
println!("trigger: {:?}", payment.fee_paid_msat);
844+
834845
entry.transaction = Some(Transaction {
835846
id: PaymentId::SelfCustodial(payment.id.0),
836847
status: payment.status.into(),

0 commit comments

Comments
 (0)