From 8ba98356268f7dbf28397d14eb5e1b1d501399dc Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Tue, 2 Jan 2024 16:07:42 +0100 Subject: [PATCH 01/15] chore: write out log level to make log messages more readable Signed-off-by: Philipp Hoenisch --- mobile/lib/logger/simple_utc_printer.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mobile/lib/logger/simple_utc_printer.dart b/mobile/lib/logger/simple_utc_printer.dart index dc5baba54..7ce3f8e3b 100644 --- a/mobile/lib/logger/simple_utc_printer.dart +++ b/mobile/lib/logger/simple_utc_printer.dart @@ -8,11 +8,11 @@ import 'package:logger/logger.dart'; /// ``` class SimpleUTCPrinter extends LogPrinter { static final levelPrefixes = { - Level.trace: '[T]', - Level.debug: '[D]', - Level.info: '[I]', - Level.warning: '[W]', - Level.error: '[E]', + Level.trace: '[TRACE]', + Level.debug: '[DEBUG]', + Level.info: '[INFO]', + Level.warning: '[WARN]', + Level.error: '[ERROR]', Level.fatal: '[FATAL]', }; From eb803d291be5fcf44b3400c921c1fb99c0090c0a Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Tue, 2 Jan 2024 09:31:58 +0100 Subject: [PATCH 02/15] chore: rename old function Signed-off-by: Philipp Hoenisch --- coordinator/src/node.rs | 2 +- coordinator/src/node/resize.rs | 2 +- crates/ln-dlc-node/src/node/mod.rs | 10 +++++----- .../src/node/{dlc_channel.rs => sub_channel.rs} | 2 +- crates/ln-dlc-node/src/tests/dlc/create.rs | 2 +- .../src/tests/dlc/dlc_setup_with_reconnects.rs | 6 +++--- .../src/tests/dlc/non_collaborative_settlement.rs | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) rename crates/ln-dlc-node/src/node/{dlc_channel.rs => sub_channel.rs} (99%) diff --git a/coordinator/src/node.rs b/coordinator/src/node.rs index cede8dcbe..a54693a78 100644 --- a/coordinator/src/node.rs +++ b/coordinator/src/node.rs @@ -327,7 +327,7 @@ impl Node { let channel_details = self.get_counterparty_channel(trade_params.pubkey)?; self.inner - .propose_dlc_channel(channel_details.clone(), contract_input) + .propose_sub_channel(channel_details.clone(), contract_input) .await .context("Could not propose dlc channel")?; diff --git a/coordinator/src/node/resize.rs b/coordinator/src/node/resize.rs index 6352a5cdf..503e9f444 100644 --- a/coordinator/src/node/resize.rs +++ b/coordinator/src/node/resize.rs @@ -298,7 +298,7 @@ impl Node { let node = self.inner.clone(); async move { if let Err(e) = node - .propose_dlc_channel(channel_details.clone(), contract_input) + .propose_sub_channel(channel_details.clone(), contract_input) .await { tracing::error!( diff --git a/crates/ln-dlc-node/src/node/mod.rs b/crates/ln-dlc-node/src/node/mod.rs index e015549b5..7c6ea8b36 100644 --- a/crates/ln-dlc-node/src/node/mod.rs +++ b/crates/ln-dlc-node/src/node/mod.rs @@ -6,9 +6,9 @@ use crate::ln::GossipSource; use crate::ln::Probes; use crate::ln::TracingLogger; use crate::ln_dlc_wallet::LnDlcWallet; -use crate::node::dlc_channel::sub_channel_manager_periodic_check; use crate::node::peer_manager::alias_as_bytes; use crate::node::peer_manager::broadcast_node_announcement; +use crate::node::sub_channel::sub_channel_manager_periodic_check; use crate::on_chain_wallet::OnChainWallet; use crate::seed::Bip39Seed; use crate::shadow::Shadow; @@ -77,8 +77,8 @@ mod storage; mod sub_channel_manager; mod wallet; -pub(crate) mod dlc_channel; pub(crate) mod invoice; +pub(crate) mod sub_channel; pub mod peer_manager; @@ -87,9 +87,6 @@ pub use crate::node::dlc_manager::DlcManager; pub use crate::node::oracle::OracleInfo; pub use ::dlc_manager as rust_dlc_manager; pub use channel_manager::ChannelManager; -pub use dlc_channel::dlc_message_name; -pub use dlc_channel::send_dlc_message; -pub use dlc_channel::sub_channel_message_name; pub use invoice::HTLCStatus; use lightning::ln::msgs::SocketAddress; use lightning::util::persist::KVStore; @@ -99,6 +96,9 @@ use lightning::util::persist::NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE; use lightning::util::ser::ReadableArgs; pub use storage::InMemoryStore; pub use storage::Storage; +pub use sub_channel::dlc_message_name; +pub use sub_channel::send_dlc_message; +pub use sub_channel::sub_channel_message_name; pub use sub_channel_manager::SubChannelManager; pub use wallet::PaymentDetails; diff --git a/crates/ln-dlc-node/src/node/dlc_channel.rs b/crates/ln-dlc-node/src/node/sub_channel.rs similarity index 99% rename from crates/ln-dlc-node/src/node/dlc_channel.rs rename to crates/ln-dlc-node/src/node/sub_channel.rs index 99d0d645a..f6192acf7 100644 --- a/crates/ln-dlc-node/src/node/dlc_channel.rs +++ b/crates/ln-dlc-node/src/node/sub_channel.rs @@ -33,7 +33,7 @@ use time::OffsetDateTime; use tokio::task::spawn_blocking; impl Node { - pub async fn propose_dlc_channel( + pub async fn propose_sub_channel( &self, channel_details: ChannelDetails, contract_input: ContractInput, diff --git a/crates/ln-dlc-node/src/tests/dlc/create.rs b/crates/ln-dlc-node/src/tests/dlc/create.rs index 7bf04cd09..740ef011f 100644 --- a/crates/ln-dlc-node/src/tests/dlc/create.rs +++ b/crates/ln-dlc-node/src/tests/dlc/create.rs @@ -75,7 +75,7 @@ pub async fn create_dlc_channel( .clone(); offer_node - .propose_dlc_channel(channel_details.clone(), contract_input) + .propose_sub_channel(channel_details.clone(), contract_input) .await?; // Process the app's `Offer` diff --git a/crates/ln-dlc-node/src/tests/dlc/dlc_setup_with_reconnects.rs b/crates/ln-dlc-node/src/tests/dlc/dlc_setup_with_reconnects.rs index 5b573d30e..a51e0e255 100644 --- a/crates/ln-dlc-node/src/tests/dlc/dlc_setup_with_reconnects.rs +++ b/crates/ln-dlc-node/src/tests/dlc/dlc_setup_with_reconnects.rs @@ -1,4 +1,4 @@ -use crate::node::dlc_channel::sub_channel_manager_periodic_check; +use crate::node::sub_channel::sub_channel_manager_periodic_check; use crate::node::Node; use crate::tests::dlc::create::create_dlc_channel; use crate::tests::dummy_contract_input; @@ -52,7 +52,7 @@ async fn reconnecting_during_dlc_channel_setup() { let oracle_pk = *app.oracle_pk().first().unwrap(); let contract_input = dummy_contract_input(20_000, 20_000, oracle_pk); - app.propose_dlc_channel(channel_details.clone(), contract_input) + app.propose_sub_channel(channel_details.clone(), contract_input) .await .unwrap(); @@ -417,7 +417,7 @@ async fn can_lose_connection_before_processing_subchannel_accept() { .clone(); coordinator - .propose_dlc_channel(channel_details.clone(), contract_input) + .propose_sub_channel(channel_details.clone(), contract_input) .await .unwrap(); diff --git a/crates/ln-dlc-node/src/tests/dlc/non_collaborative_settlement.rs b/crates/ln-dlc-node/src/tests/dlc/non_collaborative_settlement.rs index b14aaa19e..4491194d7 100644 --- a/crates/ln-dlc-node/src/tests/dlc/non_collaborative_settlement.rs +++ b/crates/ln-dlc-node/src/tests/dlc/non_collaborative_settlement.rs @@ -1,4 +1,4 @@ -use crate::node::dlc_channel::sub_channel_manager_periodic_check; +use crate::node::sub_channel::sub_channel_manager_periodic_check; use crate::node::Node; use crate::tests::bitcoind::mine; use crate::tests::dlc::create::create_dlc_channel; From 9c3c3870cd875449e4434b54a46847dff4dacd34 Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Tue, 2 Jan 2024 09:45:41 +0100 Subject: [PATCH 03/15] chore: more renaming --- coordinator/src/node.rs | 8 +-- coordinator/src/node/resize.rs | 2 +- coordinator/src/node/rollover.rs | 2 +- crates/ln-dlc-node/src/node/dlc_manager.rs | 4 +- crates/ln-dlc-node/src/node/mod.rs | 2 +- crates/ln-dlc-node/src/node/sub_channel.rs | 49 ++++++++++--------- .../src/tests/dlc/collaborative_settlement.rs | 4 +- crates/ln-dlc-node/src/tests/dlc/create.rs | 2 +- .../tests/dlc/dlc_setup_with_reconnects.rs | 18 +++---- crates/ln-dlc-node/src/tests/load.rs | 4 +- mobile/native/src/ln_dlc/node.rs | 6 +-- 11 files changed, 52 insertions(+), 49 deletions(-) diff --git a/coordinator/src/node.rs b/coordinator/src/node.rs index a54693a78..ec7249490 100644 --- a/coordinator/src/node.rs +++ b/coordinator/src/node.rs @@ -38,7 +38,7 @@ use lightning::ln::ChannelId; use lightning::util::config::UserConfig; use ln_dlc_node::node; use ln_dlc_node::node::dlc_message_name; -use ln_dlc_node::node::send_dlc_message; +use ln_dlc_node::node::send_sub_channel_message; use ln_dlc_node::node::sub_channel_message_name; use ln_dlc_node::node::RunningNode; use ln_dlc_node::WalletSettings; @@ -426,7 +426,7 @@ impl Node { ); self.inner - .propose_dlc_channel_collaborative_settlement(channel_id, accept_settlement_amount) + .propose_sub_channel_collaborative_settlement(channel_id, accept_settlement_amount) .await?; db::trades::insert( @@ -525,7 +525,7 @@ impl Node { ) -> Result { let trader_peer_id = trade_params.pubkey; - let subchannel = match self.inner.get_dlc_channel_signed(&trader_peer_id)? { + let subchannel = match self.inner.get_sub_channel_signed(&trader_peer_id)? { None => return Ok(TradeAction::Open), Some(subchannel) => subchannel, }; @@ -723,7 +723,7 @@ impl Node { "Sending message" ); - send_dlc_message( + send_sub_channel_message( &self.inner.dlc_message_handler, &self.inner.peer_manager, node_id, diff --git a/coordinator/src/node/resize.rs b/coordinator/src/node/resize.rs index 503e9f444..1abc79bd5 100644 --- a/coordinator/src/node/resize.rs +++ b/coordinator/src/node/resize.rs @@ -151,7 +151,7 @@ impl Node { position.calculate_accept_settlement_amount_partial_close(trade_params)?; self.inner - .propose_dlc_channel_collaborative_settlement( + .propose_sub_channel_collaborative_settlement( channel_id, accept_settlement_amount.to_sat(), ) diff --git a/coordinator/src/node/rollover.rs b/coordinator/src/node/rollover.rs index 15d1d0030..410ccef8c 100644 --- a/coordinator/src/node/rollover.rs +++ b/coordinator/src/node/rollover.rs @@ -229,7 +229,7 @@ impl Node { // As the average entry price does not change with a rollover, we can simply use the traders // margin as payout here. The funding rate should be considered here once https://github.com/get10101/10101/issues/1069 gets implemented. self.inner - .propose_dlc_channel_update(dlc_channel_id, rollover.margin_trader, contract_input) + .propose_sub_channel_update(dlc_channel_id, rollover.margin_trader, contract_input) .await?; // Sets the position state to rollover indicating that a rollover is in progress. diff --git a/crates/ln-dlc-node/src/node/dlc_manager.rs b/crates/ln-dlc-node/src/node/dlc_manager.rs index 96615b4ba..a504370bc 100644 --- a/crates/ln-dlc-node/src/node/dlc_manager.rs +++ b/crates/ln-dlc-node/src/node/dlc_manager.rs @@ -85,14 +85,14 @@ pub fn signed_channel_state_name(signed_channel: &SignedChannel) -> String { impl Node { pub fn get_signed_channel_by_trader_id(&self, trader_id: PublicKey) -> Result { let channel = self - .get_dlc_channel_signed(&trader_id)? + .get_sub_channel_signed(&trader_id)? .with_context(|| format!("Could not find signed DLC channel. trader_id={trader_id}"))?; let dlc_channel_id = channel .get_dlc_channel_id(0) .expect("Expect to get dlc_channel id"); - let channel = self.get_dlc_channel_by_id(&dlc_channel_id)?; + let channel = self.get_sub_channel_by_id(&dlc_channel_id)?; let signed_channel = match channel { Channel::Signed(signed_channel) => signed_channel, _ => bail!("Couldn't find signed channel for trader_id={trader_id}"), diff --git a/crates/ln-dlc-node/src/node/mod.rs b/crates/ln-dlc-node/src/node/mod.rs index 7c6ea8b36..05c60cd13 100644 --- a/crates/ln-dlc-node/src/node/mod.rs +++ b/crates/ln-dlc-node/src/node/mod.rs @@ -97,7 +97,7 @@ use lightning::util::ser::ReadableArgs; pub use storage::InMemoryStore; pub use storage::Storage; pub use sub_channel::dlc_message_name; -pub use sub_channel::send_dlc_message; +pub use sub_channel::send_sub_channel_message; pub use sub_channel::sub_channel_message_name; pub use sub_channel_manager::SubChannelManager; pub use wallet::PaymentDetails; diff --git a/crates/ln-dlc-node/src/node/sub_channel.rs b/crates/ln-dlc-node/src/node/sub_channel.rs index f6192acf7..0d319e0c2 100644 --- a/crates/ln-dlc-node/src/node/sub_channel.rs +++ b/crates/ln-dlc-node/src/node/sub_channel.rs @@ -69,7 +69,7 @@ impl Nod &[announcements], )?; - send_dlc_message( + send_sub_channel_message( &dlc_message_handler, &peer_manager, channel_details.counterparty.node_id, @@ -84,7 +84,7 @@ impl Nod /// Proposes and update to the DLC channel based on the provided [`ContractInput`]. A /// [`RenewOffer`] is sent to the counterparty, kickstarting the renew protocol. - pub async fn propose_dlc_channel_update( + pub async fn propose_sub_channel_update( &self, dlc_channel_id: &DlcChannelId, payout_amount: u64, @@ -100,7 +100,7 @@ impl Nod let (renew_offer, counterparty_pubkey) = dlc_manager.renew_offer(&dlc_channel_id, payout_amount, &contract_input)?; - send_dlc_message( + send_sub_channel_message( &dlc_message_handler, &peer_manager, counterparty_pubkey, @@ -113,7 +113,7 @@ impl Nod .map_err(|e| anyhow!("{e:#}"))? } - pub fn reject_dlc_channel_offer(&self, channel_id: &ChannelId) -> Result<()> { + pub fn reject_sub_channel_offer(&self, channel_id: &ChannelId) -> Result<()> { let channel_id_hex = hex::encode(channel_id.0); tracing::info!(channel_id = %channel_id_hex, "Rejecting DLC channel offer"); @@ -122,7 +122,7 @@ impl Nod .sub_channel_manager .reject_sub_channel_offer(*channel_id)?; - send_dlc_message( + send_sub_channel_message( &self.dlc_message_handler, &self.peer_manager, node_id, @@ -132,7 +132,7 @@ impl Nod Ok(()) } - pub fn accept_dlc_channel_offer(&self, channel_id: &ChannelId) -> Result<()> { + pub fn accept_sub_channel_offer(&self, channel_id: &ChannelId) -> Result<()> { let channel_id_hex = hex::encode(channel_id.0); tracing::info!(channel_id = %channel_id_hex, "Accepting DLC channel offer"); @@ -140,7 +140,7 @@ impl Nod let (node_id, accept_sub_channel) = self.sub_channel_manager.accept_sub_channel(channel_id)?; - send_dlc_message( + send_sub_channel_message( &self.dlc_message_handler, &self.peer_manager, node_id, @@ -150,7 +150,7 @@ impl Nod Ok(()) } - pub async fn propose_dlc_channel_collaborative_settlement( + pub async fn propose_sub_channel_collaborative_settlement( &self, channel_id: ChannelId, accept_settlement_amount: u64, @@ -171,7 +171,7 @@ impl Nod let (sub_channel_close_offer, counterparty_pk) = sub_channel_manager .offer_subchannel_close(&channel_id, accept_settlement_amount)?; - send_dlc_message( + send_sub_channel_message( &dlc_message_handler, &peer_manager, counterparty_pk, @@ -184,7 +184,7 @@ impl Nod .await? } - pub fn accept_dlc_channel_collaborative_settlement( + pub fn accept_sub_channel_collaborative_settlement( &self, channel_id: &ChannelId, ) -> Result<()> { @@ -196,7 +196,7 @@ impl Nod .sub_channel_manager .accept_subchannel_close_offer(channel_id)?; - send_dlc_message( + send_sub_channel_message( &self.dlc_message_handler, &self.peer_manager, counterparty_pk, @@ -206,7 +206,7 @@ impl Nod Ok(()) } - pub fn get_dlc_channel_offer(&self, pubkey: &PublicKey) -> Result> { + pub fn get_sub_channel_offer(&self, pubkey: &PublicKey) -> Result> { let dlc_channel = self .dlc_manager .get_store() @@ -273,21 +273,21 @@ impl Nod Ok(contract) } - pub fn get_dlc_channel_signed(&self, pubkey: &PublicKey) -> Result> { + pub fn get_sub_channel_signed(&self, pubkey: &PublicKey) -> Result> { let matcher = |dlc_channel: &&SubChannel| { dlc_channel.counter_party == *pubkey && matches!(&dlc_channel.state, SubChannelState::Signed(_)) }; - let dlc_channel = self.get_dlc_channel(&matcher)?; + let dlc_channel = self.get_sub_channel(&matcher)?; Ok(dlc_channel) } - pub fn get_dlc_channel_close_offer(&self, pubkey: &PublicKey) -> Result> { + pub fn get_sub_channel_close_offer(&self, pubkey: &PublicKey) -> Result> { let matcher = |dlc_channel: &&SubChannel| { dlc_channel.counter_party == *pubkey && matches!(&dlc_channel.state, SubChannelState::CloseOffered(_)) }; - let dlc_channel = self.get_dlc_channel(&matcher)?; + let dlc_channel = self.get_sub_channel(&matcher)?; Ok(dlc_channel) } @@ -388,7 +388,7 @@ impl Nod } } - fn get_dlc_channel( + fn get_sub_channel( &self, matcher: impl FnMut(&&SubChannel) -> bool, ) -> Result> { @@ -418,7 +418,7 @@ impl Nod } /// Gets the dlc channel by the dlc channel id - pub fn get_dlc_channel_by_id(&self, dlc_channel_id: &DlcChannelId) -> Result { + pub fn get_sub_channel_by_id(&self, dlc_channel_id: &DlcChannelId) -> Result { self.dlc_manager .get_store() .get_channel(dlc_channel_id) @@ -436,7 +436,7 @@ impl Nod &self, dlc_channel_id: &DlcChannelId, ) -> Result { - let channel = self.get_dlc_channel_by_id(dlc_channel_id)?; + let channel = self.get_sub_channel_by_id(dlc_channel_id)?; let contract_id = channel .get_contract_id() .context("Could not find contract id")?; @@ -470,7 +470,7 @@ impl Nod if let Some(msg) = resp { tracing::debug!(to = %node_id, "Sending DLC-manager message"); - send_dlc_message(dlc_message_handler, peer_manager, node_id, msg); + send_sub_channel_message(dlc_message_handler, peer_manager, node_id, msg); } } Message::SubChannel(msg) => { @@ -487,7 +487,7 @@ impl Nod msg = %sub_channel_message_name(&msg), "Sending DLC channel message" ); - send_dlc_message( + send_sub_channel_message( dlc_message_handler, peer_manager, node_id, @@ -507,7 +507,10 @@ impl Nod /// Use this instead of [`MessageHandler`]'s `send_message` which only enqueues the message. /// /// [`MessageHandler`]: dlc_messages::message_handler::MessageHandler -pub fn send_dlc_message( +pub fn send_sub_channel_message< + S: TenTenOneStorage + 'static, + N: LnDlcStorage + Sync + Send + 'static, +>( dlc_message_handler: &DlcMessageHandler, peer_manager: &PeerManager, node_id: PublicKey, @@ -542,7 +545,7 @@ pub(crate) async fn sub_channel_manager_periodic_check< "Queuing up DLC channel message tied to pending action" ); - send_dlc_message(dlc_message_handler, peer_manager, node_id, msg); + send_sub_channel_message(dlc_message_handler, peer_manager, node_id, msg); } Ok(()) diff --git a/crates/ln-dlc-node/src/tests/dlc/collaborative_settlement.rs b/crates/ln-dlc-node/src/tests/dlc/collaborative_settlement.rs index ab7a969b3..3eb5dd1f3 100644 --- a/crates/ln-dlc-node/src/tests/dlc/collaborative_settlement.rs +++ b/crates/ln-dlc-node/src/tests/dlc/collaborative_settlement.rs @@ -150,7 +150,7 @@ async fn dlc_collaborative_settlement( .context("Could not find usable channel with peer")? .clone(); - app.propose_dlc_channel_collaborative_settlement( + app.propose_sub_channel_collaborative_settlement( channel_details.channel_id, coordinator_settlement_amount, ) @@ -165,7 +165,7 @@ async fn dlc_collaborative_settlement( ) .await?; - coordinator.accept_dlc_channel_collaborative_settlement(&sub_channel.channel_id)?; + coordinator.accept_sub_channel_collaborative_settlement(&sub_channel.channel_id)?; // Process the coordinator's `CloseAccept` and send `CloseConfirm` wait_until_dlc_channel_state( diff --git a/crates/ln-dlc-node/src/tests/dlc/create.rs b/crates/ln-dlc-node/src/tests/dlc/create.rs index 740ef011f..8a1d4b324 100644 --- a/crates/ln-dlc-node/src/tests/dlc/create.rs +++ b/crates/ln-dlc-node/src/tests/dlc/create.rs @@ -87,7 +87,7 @@ pub async fn create_dlc_channel( ) .await?; - accept_node.accept_dlc_channel_offer(&sub_channel.channel_id)?; + accept_node.accept_sub_channel_offer(&sub_channel.channel_id)?; // Process the coordinator's `Accept` and send `Confirm` wait_until_dlc_channel_state( diff --git a/crates/ln-dlc-node/src/tests/dlc/dlc_setup_with_reconnects.rs b/crates/ln-dlc-node/src/tests/dlc/dlc_setup_with_reconnects.rs index a51e0e255..eab19f954 100644 --- a/crates/ln-dlc-node/src/tests/dlc/dlc_setup_with_reconnects.rs +++ b/crates/ln-dlc-node/src/tests/dlc/dlc_setup_with_reconnects.rs @@ -78,13 +78,13 @@ async fn reconnecting_during_dlc_channel_setup() { // Assert that `accept_dlc_channel_offer` fails if the peer is disconnected (do not panic as in // https://github.com/get10101/10101/issues/760). assert!(coordinator - .accept_dlc_channel_offer(&sub_channel.channel_id) + .accept_sub_channel_offer(&sub_channel.channel_id) .is_err()); app.connect(coordinator.info).await.unwrap(); coordinator - .accept_dlc_channel_offer(&sub_channel.channel_id) + .accept_sub_channel_offer(&sub_channel.channel_id) .unwrap(); // Process the coordinator's `Accept` and send `Confirm` @@ -165,7 +165,7 @@ async fn reconnecting_during_dlc_channel_setup() { .unwrap(); let coordinator_settlement_amount = 12_500; - app.propose_dlc_channel_collaborative_settlement( + app.propose_sub_channel_collaborative_settlement( channel_details.channel_id, coordinator_settlement_amount, ) @@ -183,7 +183,7 @@ async fn reconnecting_during_dlc_channel_setup() { .unwrap(); coordinator - .accept_dlc_channel_collaborative_settlement(&sub_channel.channel_id) + .accept_sub_channel_collaborative_settlement(&sub_channel.channel_id) .unwrap(); // Process the coordinator's `CloseAccept` and send `CloseConfirm`. @@ -302,7 +302,7 @@ async fn can_lose_connection_before_processing_subchannel_close_finalize() { .clone(); coordinator - .propose_dlc_channel_collaborative_settlement( + .propose_sub_channel_collaborative_settlement( channel_details.channel_id, app_dlc_collateral / 2, ) @@ -319,7 +319,7 @@ async fn can_lose_connection_before_processing_subchannel_close_finalize() { .await .unwrap(); - app.accept_dlc_channel_collaborative_settlement(&sub_channel.channel_id) + app.accept_sub_channel_collaborative_settlement(&sub_channel.channel_id) .unwrap(); // Process `CloseAccept` and send `CloseConfirm` @@ -431,7 +431,7 @@ async fn can_lose_connection_before_processing_subchannel_accept() { .await .unwrap(); - app.accept_dlc_channel_offer(&sub_channel.channel_id) + app.accept_sub_channel_offer(&sub_channel.channel_id) .unwrap(); // Give time to deliver the `Accept` message to the coordinator. @@ -550,7 +550,7 @@ async fn can_lose_connection_before_processing_subchannel_close_accept() { .clone(); coordinator - .propose_dlc_channel_collaborative_settlement( + .propose_sub_channel_collaborative_settlement( channel_details.channel_id, app_dlc_collateral / 2, ) @@ -567,7 +567,7 @@ async fn can_lose_connection_before_processing_subchannel_close_accept() { .await .unwrap(); - app.accept_dlc_channel_collaborative_settlement(&sub_channel.channel_id) + app.accept_sub_channel_collaborative_settlement(&sub_channel.channel_id) .unwrap(); // Give time to deliver the `CloseAccept` message to the coordinator. diff --git a/crates/ln-dlc-node/src/tests/load.rs b/crates/ln-dlc-node/src/tests/load.rs index c901b76e2..c1797540f 100644 --- a/crates/ln-dlc-node/src/tests/load.rs +++ b/crates/ln-dlc-node/src/tests/load.rs @@ -110,7 +110,7 @@ async fn open_position( ) .await?; - app.accept_dlc_channel_offer(&dlc_channel.channel_id)?; + app.accept_sub_channel_offer(&dlc_channel.channel_id)?; wait_until_dlc_channel_state( Duration::from_secs(60), @@ -158,7 +158,7 @@ async fn close_position( ) .await?; - app.accept_dlc_channel_collaborative_settlement(&dlc_channel.channel_id) + app.accept_sub_channel_collaborative_settlement(&dlc_channel.channel_id) .unwrap(); wait_until_dlc_channel_state( diff --git a/mobile/native/src/ln_dlc/node.rs b/mobile/native/src/ln_dlc/node.rs index b8dc2b4ee..9b6f710b7 100644 --- a/mobile/native/src/ln_dlc/node.rs +++ b/mobile/native/src/ln_dlc/node.rs @@ -192,7 +192,7 @@ impl Node { // TODO: We should probably verify that: (1) the counterparty is the // coordinator and (2) the DLC channel close offer is expected and correct. self.inner - .accept_dlc_channel_collaborative_settlement(&channel_id) + .accept_sub_channel_collaborative_settlement(&channel_id) .with_context(|| { format!( "Failed to accept DLC channel close offer for channel {}", @@ -303,7 +303,7 @@ impl Node { SubchannelOfferAction::Accept => { if let Err(error) = self .inner - .accept_dlc_channel_offer(&channel_id) + .accept_sub_channel_offer(&channel_id) .with_context(|| { format!( "Failed to accept DLC channel offer for channel {}", @@ -329,7 +329,7 @@ impl Node { (InvalidSubchannelOffer::Unacceptable, invalid_offer_msg) }; self.inner - .reject_dlc_channel_offer(&channel_id) + .reject_sub_channel_offer(&channel_id) .with_context(|| { format!( "Failed to reject DLC channel offer for channel {}", From 4c85b7046022ac357cfd5ce647702bac3b63afc1 Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Tue, 2 Jan 2024 16:07:15 +0100 Subject: [PATCH 04/15] chore: replace fund with ln faucet with on-chain faucet Signed-off-by: Philipp Hoenisch --- .../wallet/application/faucet_service.dart | 51 ++++++++++-- .../wallet/domain/share_payment_request.dart | 1 + .../wallet/onboarding/fund_wallet_modal.dart | 22 +---- .../lib/features/wallet/receive_screen.dart | 82 +++---------------- mobile/lib/features/wallet/wallet_screen.dart | 5 +- mobile/native/src/api.rs | 17 ++-- 6 files changed, 70 insertions(+), 108 deletions(-) diff --git a/mobile/lib/features/wallet/application/faucet_service.dart b/mobile/lib/features/wallet/application/faucet_service.dart index 108f901e2..174a020f4 100644 --- a/mobile/lib/features/wallet/application/faucet_service.dart +++ b/mobile/lib/features/wallet/application/faucet_service.dart @@ -1,30 +1,65 @@ import 'dart:convert'; +import 'package:get_10101/common/domain/model.dart'; import 'package:get_10101/logger/logger.dart'; import 'package:http/http.dart' as http; class FaucetService { - /// Pay the provided invoice with lnd faucet - Future payInvoiceWithLndFaucet(String invoice) async { + /// Pay the provided invoice with our faucet + Future payInvoiceWithFaucet(String bip21Uri, Amount? invoiceAmount) async { + final split = bip21Uri.split(":"); + final addressAndMaybeAmount = split[1].split("?"); + logger.i("Funding $addressAndMaybeAmount"); + final address = addressAndMaybeAmount[0]; + final amount = invoiceAmount?.btc ?? 1.0; + + logger.i("Funding $address with $amount"); // Default to the faucet on the 10101 server, but allow to override it // locally if needed for dev testing // It's not populated in Config struct, as it's not used in production String faucet = const String.fromEnvironment("REGTEST_FAUCET", defaultValue: "http://34.32.0.52:8080"); - final data = {'payment_request': invoice}; + final data = { + 'jsonrpc': '1.0', + 'method': 'sendtoaddress', + 'params': [address, "$amount"], + }; final encodedData = json.encode(data); final response = await http.post( - Uri.parse('$faucet/lnd/v1/channels/transactions'), - headers: {'Content-Type': 'application/json'}, + Uri.parse('$faucet/bitcoin'), + headers: {'Content-Type': 'text/plain'}, body: encodedData, ); - if (response.statusCode != 200 || !response.body.contains('"payment_error":""')) { - throw Exception("Payment failed: Received ${response.statusCode} ${response.body}"); + if (response.statusCode != 200 || !response.body.contains('"error":null')) { + throw Exception("Funding failed: Received ${response.statusCode} ${response.body}"); } else { - logger.i("Paying invoice succeeded: ${response.body}"); + logger.i("Funding succeeded: ${response.body}"); + } + + { + final data = { + 'jsonrpc': '1.0', + 'method': 'generatetoaddress', + // a random address + 'params': [7, "bcrt1qlzarjr7s5fs983q7hcfuhnensrp9cs0n8gkacz"], + }; + + final encodedData = json.encode(data); + + final response = await http.post( + Uri.parse('$faucet/bitcoin'), + headers: {'Content-Type': 'text/plain'}, + body: encodedData, + ); + + if (response.statusCode != 200 || !response.body.contains('"error":null')) { + throw Exception("Mining blocks failed: received ${response.statusCode} ${response.body}"); + } else { + logger.i("Mining blocks succeeded: ${response.body}"); + } } } diff --git a/mobile/lib/features/wallet/domain/share_payment_request.dart b/mobile/lib/features/wallet/domain/share_payment_request.dart index 52e0ea686..e66766a98 100644 --- a/mobile/lib/features/wallet/domain/share_payment_request.dart +++ b/mobile/lib/features/wallet/domain/share_payment_request.dart @@ -1,6 +1,7 @@ import 'package:get_10101/common/domain/model.dart'; class SharePaymentRequest { + // TODO(bonomat): this should be removed final String lightningInvoice; final String bip21Uri; final Amount? amount; diff --git a/mobile/lib/features/wallet/onboarding/fund_wallet_modal.dart b/mobile/lib/features/wallet/onboarding/fund_wallet_modal.dart index 63d1a501b..44258f15a 100644 --- a/mobile/lib/features/wallet/onboarding/fund_wallet_modal.dart +++ b/mobile/lib/features/wallet/onboarding/fund_wallet_modal.dart @@ -130,7 +130,7 @@ class _FundWalletModalState extends State { setState(() => _isPayInvoiceButtonDisabled = true); final faucetService = context.read(); faucetService - .payInvoiceWithLndFaucet(widget.invoice) + .payInvoiceWithFaucet(widget.invoice, widget.amount) .catchError((error) { setState(() => _isPayInvoiceButtonDisabled = false); showSnackBar( @@ -143,26 +143,6 @@ class _FundWalletModalState extends State { ), child: const Text("Pay the invoice with 10101 faucet"), ), - OutlinedButton( - onPressed: _isPayInvoiceButtonDisabled - ? null - : () async { - setState(() => _isPayInvoiceButtonDisabled = true); - final faucetService = context.read(); - faucetService - .payInvoiceWithMakerFaucet(widget.invoice) - .catchError((error) { - setState(() => _isPayInvoiceButtonDisabled = false); - showSnackBar( - ScaffoldMessenger.of(context), error.toString()); - }); - }, - style: ElevatedButton.styleFrom( - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(5.0))), - ), - child: const Text("Pay the invoice with 10101 maker"), - ), ], ) : QrImageView( diff --git a/mobile/lib/features/wallet/receive_screen.dart b/mobile/lib/features/wallet/receive_screen.dart index 46a4bac82..a38604221 100644 --- a/mobile/lib/features/wallet/receive_screen.dart +++ b/mobile/lib/features/wallet/receive_screen.dart @@ -46,10 +46,8 @@ class _ReceiveScreenState extends State { String? description; bool _isPayInvoiceButtonDisabled = false; - late bool _isLightning; SharePaymentRequest? _paymentRequest; bool _faucet = false; - bool _receiveUsdp = false; @override void initState() { @@ -57,15 +55,14 @@ class _ReceiveScreenState extends State { context.read().waitForPayment(); _createPaymentRequest(amount, false, description) .then((paymentRequest) => setState(() => _paymentRequest = paymentRequest)); - _isLightning = widget.walletType == WalletType.lightning; } String rawInvoice() { - return _isLightning ? _paymentRequest!.lightningInvoice : _paymentRequest!.bip21Uri; + return _paymentRequest!.bip21Uri; } String requestTypeName() { - return _isLightning ? "Invoice" : "BIP21 payment URI"; + return "BIP21 payment URI"; } @override @@ -108,11 +105,10 @@ class _ReceiveScreenState extends State { Container( margin: const EdgeInsets.fromLTRB(0, 10, 0, 0), child: GestureDetector( - onDoubleTap: config.network == "regtest" && _isLightning - ? () => setState(() => _faucet = !_faucet) - : null, + onDoubleTap: + config.network == "regtest" ? () => setState(() => _faucet = !_faucet) : null, child: Center( - child: _faucet && _isLightning + child: _faucet ? Column( children: [ const SizedBox(height: 125), @@ -123,11 +119,11 @@ class _ReceiveScreenState extends State { setState(() => _isPayInvoiceButtonDisabled = true); final faucetService = context.read(); faucetService - .payInvoiceWithLndFaucet(rawInvoice()) + .payInvoiceWithFaucet(rawInvoice(), amount) .catchError((error) { setState(() => _isPayInvoiceButtonDisabled = false); showSnackBar(ScaffoldMessenger.of(context), error.toString()); - }); + }).then((value) => context.go(WalletScreen.route)); }, style: ElevatedButton.styleFrom( shape: const RoundedRectangleBorder( @@ -135,25 +131,6 @@ class _ReceiveScreenState extends State { ), child: const Text("Pay the invoice with 10101 faucet"), ), - OutlinedButton( - onPressed: _isPayInvoiceButtonDisabled - ? null - : () async { - setState(() => _isPayInvoiceButtonDisabled = true); - final faucetService = context.read(); - faucetService - .payInvoiceWithMakerFaucet(rawInvoice()) - .catchError((error) { - setState(() => _isPayInvoiceButtonDisabled = false); - showSnackBar(ScaffoldMessenger.of(context), error.toString()); - }); - }, - style: ElevatedButton.styleFrom( - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(5.0))), - ), - child: const Text("Pay the invoice with 10101 maker"), - ), const SizedBox(height: 125), ], ) @@ -205,10 +182,10 @@ class _ReceiveScreenState extends State { child: Padding( padding: const EdgeInsets.all(20), child: InvoiceDrawerScreen( - isInUsd: _receiveUsdp, - amount: _receiveUsdp ? usdAmount?.usd : amount?.sats, + isInUsd: false, + amount: amount?.sats, description: description, - isLightning: _isLightning, + isLightning: false, onConfirm: (amt, descr, isUsd) { logger.i("Confirming amount $amt $isUsd"); final satsAmount = @@ -255,42 +232,9 @@ class _ReceiveScreenState extends State { ], ), ), - Visibility( - visible: _isLightning, - replacement: BitcoinAddress( - address: _paymentRequest == null ? "" : _paymentRequest!.bip21Uri, - ), - child: LightningUsdpToggle( - updateReceiveUsdp: (state) { - setState(() { - _receiveUsdp = state; - _createPaymentRequest(amount, _receiveUsdp, description) - .then((paymentRequest) => setState(() => _paymentRequest = paymentRequest)); - }); - }, - receiveUsdp: _receiveUsdp, - satsAmount: amount, - usdAmount: usdAmount, - )), - const Spacer(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - DualButtonSelector( - onLightningButtonClick: () { - setState(() { - _isLightning = true; - }); - }, - onOnChainButtonClick: () { - setState(() { - _isLightning = false; - }); - }, - isLightning: _isLightning, - ), - ], - ) + BitcoinAddress( + address: _paymentRequest == null ? "" : _paymentRequest!.bip21Uri, + ), ]), ))); } diff --git a/mobile/lib/features/wallet/wallet_screen.dart b/mobile/lib/features/wallet/wallet_screen.dart index 6fbf76ed7..b27ec187b 100644 --- a/mobile/lib/features/wallet/wallet_screen.dart +++ b/mobile/lib/features/wallet/wallet_screen.dart @@ -6,7 +6,6 @@ import 'package:get_10101/common/secondary_action_button.dart'; import 'package:get_10101/features/swap/swap_screen.dart'; import 'package:get_10101/features/wallet/balance.dart'; import 'package:get_10101/features/wallet/receive_screen.dart'; -import 'package:get_10101/features/wallet/onboarding/onboarding_screen.dart'; import 'package:get_10101/features/wallet/scanner_screen.dart'; import 'package:get_10101/features/wallet/wallet_change_notifier.dart'; import 'package:go_router/go_router.dart'; @@ -46,7 +45,9 @@ class WalletScreen extends StatelessWidget { onPressed: () { context.go((hasChannel || walletChangeNotifier.lightning().sats > 0) ? ReceiveScreen.route - : OnboardingScreen.route); + : + // TODO: we should have a dedicated on-boarding screen for on-boarding with on-chain funds + ReceiveScreen.route); }, icon: FontAwesomeIcons.arrowDown, title: 'Receive', diff --git a/mobile/native/src/api.rs b/mobile/native/src/api.rs index 5c7d414eb..3fb0ddd9d 100644 --- a/mobile/native/src/api.rs +++ b/mobile/native/src/api.rs @@ -463,23 +463,24 @@ pub struct PaymentRequest { pub fn create_payment_request( amount_sats: Option, - is_usdp: bool, - description: String, + _is_usdp: bool, + _description: String, ) -> Result { let amount_query = amount_sats .map(|amt| format!("?amount={}", Amount::from_sat(amt).to_btc())) .unwrap_or_default(); let addr = ln_dlc::get_unused_address(); - let ln_invoice = if is_usdp { - ln_dlc::create_usdp_invoice(amount_sats, description)? - } else { - ln_dlc::create_invoice(amount_sats, description)? - }; + // TODO(bonomat): this can be removed as we don't support LN for now + // let ln_invoice = if is_usdp { + // ln_dlc::create_usdp_invoice(amount_sats, description)? + // } else { + // ln_dlc::create_invoice(amount_sats, description)? + // }; Ok(PaymentRequest { bip21: format!("bitcoin:{addr}{amount_query}"), - lightning: ln_invoice.to_string(), + lightning: "TODO: remove this part".to_string(), }) } From 05e8dc893c046532bee10083d1c7c56038f374a6 Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Tue, 2 Jan 2024 16:35:34 +0100 Subject: [PATCH 05/15] chore: ignor all the validations to get to trade Signed-off-by: Philipp Hoenisch --- .../trade/trade_bottom_sheet_tab.dart | 83 ++++++++++--------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/mobile/lib/features/trade/trade_bottom_sheet_tab.dart b/mobile/lib/features/trade/trade_bottom_sheet_tab.dart index ce8fa7411..90af168ba 100644 --- a/mobile/lib/features/trade/trade_bottom_sheet_tab.dart +++ b/mobile/lib/features/trade/trade_bottom_sheet_tab.dart @@ -321,47 +321,48 @@ class _TradeBottomSheetTabState extends State { _formKey.currentState?.validate(); }, validator: (value) { - Amount quantity = Amount.parseAmount(value); - - // TODO(holzeis): fetch min amount to trade from coordinator - if (quantity.toInt < 1) { - return "Min quantity to trade is 1"; - } - - Amount margin = tradeValues.margin!; - - int? optCounterPartyMargin = - provider.counterpartyMargin(direction, coordinatorLeverage); - if (optCounterPartyMargin == null) { - return "Counterparty margin not available"; - } - int counterpartyMargin = optCounterPartyMargin; - - int usableCounterpartyMarginInPosition = positionChangeNotifier - .coordinatorMarginUsableForTrade(Leverage(coordinatorLeverage), direction) - .sats; - - // This condition has to stay as the first thing to check, so we reset showing the info - if (counterpartyMargin > - counterpartyUsableBalance + usableCounterpartyMarginInPosition) { - setState(() => showCapacityInfo = true); - - return "Insufficient capacity"; - } else if (showCapacityInfo) { - setState(() => showCapacityInfo = true); - } - - Amount fee = provider.orderMatchingFee(direction) ?? Amount.zero(); - if (usableBalance < margin.sats + fee.sats) { - return "Insufficient balance"; - } - - if (margin.sats > maxMargin) { - return "Max margin is $maxMargin"; - } - if (margin.sats < minTradeMargin.sats) { - return "Min margin is ${minTradeMargin.sats}"; - } + // TODO(bonomat): we need new checks here. For now, YOLO + // Amount quantity = Amount.parseAmount(value); + // + // // TODO(holzeis): fetch min amount to trade from coordinator + // if (quantity.toInt < 1) { + // return "Min quantity to trade is 1"; + // } + // + // Amount margin = tradeValues.margin!; + // + // int? optCounterPartyMargin = + // provider.counterpartyMargin(direction, coordinatorLeverage); + // if (optCounterPartyMargin == null) { + // return "Counterparty margin not available"; + // } + // int counterpartyMargin = optCounterPartyMargin; + // + // int usableCounterpartyMarginInPosition = positionChangeNotifier + // .coordinatorMarginUsableForTrade(Leverage(coordinatorLeverage), direction) + // .sats; + // + // // This condition has to stay as the first thing to check, so we reset showing the info + // if (counterpartyMargin > + // counterpartyUsableBalance + usableCounterpartyMarginInPosition) { + // setState(() => showCapacityInfo = true); + // + // return "Insufficient capacity"; + // } else if (showCapacityInfo) { + // setState(() => showCapacityInfo = true); + // } + // + // Amount fee = provider.orderMatchingFee(direction) ?? Amount.zero(); + // if (usableBalance < margin.sats + fee.sats) { + // return "Insufficient balance"; + // } + // + // if (margin.sats > maxMargin) { + // return "Max margin is $maxMargin"; + // } + // if (margin.sats < minTradeMargin.sats) { + // return "Min margin is ${minTradeMargin.sats}"; + // } showCapacityInfo = false; return null; From e86cd9438118f6c5837eacd6146b2d3502541edf Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Tue, 2 Jan 2024 16:35:56 +0100 Subject: [PATCH 06/15] chore: change main screen to show on-chain balance first Signed-off-by: Philipp Hoenisch --- mobile/lib/features/wallet/balance.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mobile/lib/features/wallet/balance.dart b/mobile/lib/features/wallet/balance.dart index 46dfcf74e..e7016ce49 100644 --- a/mobile/lib/features/wallet/balance.dart +++ b/mobile/lib/features/wallet/balance.dart @@ -65,14 +65,15 @@ class _BalanceBoxState extends State<_BalanceBox> { int selectedTitleIndex = 1; List titles = [ + 'DLC-channel', 'On-chain', - 'Lightning', 'USD-P', ]; List balances = [ - const BalanceRow(walletType: WalletType.onChain), + // TODO(bonomat): this should show the balance from the dlc channel now const BalanceRow(walletType: WalletType.lightning), + const BalanceRow(walletType: WalletType.onChain), const BalanceRow(walletType: WalletType.stable), ]; From c540b360bb450a469e70afbe5eefa5458d6621ca Mon Sep 17 00:00:00 2001 From: Lucas Soriano del Pino Date: Wed, 3 Jan 2024 16:06:41 +1100 Subject: [PATCH 07/15] chore(app): Update dependencies based on local Flutter upgrade --- mobile/pubspec.lock | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 06fe9ad9c..7724ae365 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -197,10 +197,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" colorize: dependency: transitive description: @@ -644,10 +644,10 @@ packages: dependency: "direct main" description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mime: dependency: transitive description: @@ -1049,18 +1049,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -1089,26 +1089,26 @@ packages: dependency: "direct main" description: name: test - sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" + sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f url: "https://pub.dev" source: hosted - version: "1.24.3" + version: "1.24.9" test_api: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" test_core: dependency: transitive description: name: test_core - sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" + sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.9" timeago: dependency: "direct main" description: @@ -1289,10 +1289,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -1350,5 +1350,5 @@ packages: source: hosted version: "2.1.1" sdks: - dart: ">=3.1.2 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.10.0" From 37fe492817f89b96cc84e5846e47a3c971dceee7 Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Wed, 3 Jan 2024 11:22:08 +0100 Subject: [PATCH 08/15] chore: clean-up just fund Signed-off-by: Philipp Hoenisch --- crates/tests-e2e/examples/fund.rs | 229 +----------------------------- 1 file changed, 4 insertions(+), 225 deletions(-) diff --git a/crates/tests-e2e/examples/fund.rs b/crates/tests-e2e/examples/fund.rs index ba1b6c18f..4652f093c 100644 --- a/crates/tests-e2e/examples/fund.rs +++ b/crates/tests-e2e/examples/fund.rs @@ -1,20 +1,11 @@ -use anyhow::bail; use anyhow::Context; use anyhow::Result; -use bitcoin::Address; use bitcoin::Amount; use clap::Parser; use ln_dlc_node::node::NodeInfo; -use local_ip_address::local_ip; -use reqwest::Response; -use reqwest::StatusCode; -use serde::Deserialize; -use std::time::Duration; use tests_e2e::bitcoind; -use tests_e2e::bitcoind::Bitcoind; use tests_e2e::coordinator::Coordinator; use tests_e2e::http::init_reqwest; -use tests_e2e::maker::Maker; use tracing::metadata::LevelFilter; use tracing_subscriber::filter::Directive; use tracing_subscriber::layer::SubscriberExt; @@ -42,10 +33,10 @@ pub struct Opts { async fn main() -> Result<()> { init_tracing(LevelFilter::DEBUG).expect("tracing to initialise"); let opts = Opts::parse(); - fund_everything(&opts.faucet, &opts.coordinator, &opts.maker).await + fund_everything(&opts.faucet, &opts.coordinator).await } -async fn fund_everything(faucet: &str, coordinator: &str, maker: &str) -> Result<()> { +async fn fund_everything(faucet: &str, coordinator: &str) -> Result<()> { let client = init_reqwest(); let coordinator = Coordinator::new(client.clone(), coordinator); let coord_addr = coordinator.get_new_address().await?; @@ -56,229 +47,17 @@ async fn fund_everything(faucet: &str, coordinator: &str, maker: &str) -> Result .fund(&coord_addr, Amount::ONE_BTC) .await .context("Could not fund the faucet's on-chain wallet")?; - let maker = Maker::new(init_reqwest(), maker); - let maker_addr = maker.get_new_address().await?; - bitcoind.fund(&maker_addr, Amount::ONE_BTC).await?; bitcoind.mine(10).await?; - maker - .sync() - .await - .context("Failed to sync maker's on-chain wallet")?; let coordinator_balance = coordinator.get_balance().await?; tracing::info!( - onchain = %coordinator_balance.onchain, - offchain = %coordinator_balance.offchain, + onchain = %Amount::from_sat(coordinator_balance.onchain), + offchain = %Amount::from_sat(coordinator_balance.offchain), "Coordinator balance", ); let coordinator_node_info: NodeInfo = coordinator.get_node_info().await?; tracing::info!(?coordinator_node_info); - - let lnd_addr: LndAddr = reqwest::get(&format!("{faucet}/lnd/v1/newaddress")) - .await? - .json() - .await?; - - bitcoind - .fund( - &lnd_addr.address, - Amount::ONE_BTC - .checked_mul(10) - .expect("small integers to multiply"), - ) - .await?; - bitcoind.mine(10).await?; - - if let Err(e) = coordinator.sync_wallet().await { - tracing::warn!("Failed to sync coordinator's on-chain wallet: {e:#}"); - } - - let lnd_balance = get_text(&format!("{faucet}/lnd/v1/balance/blockchain")).await?; - tracing::info!("Faucet balance before opening another channel: {lnd_balance}"); - - tracing::info!("Opening new faucet channel"); - - open_channel( - &coordinator_node_info, - Amount::ONE_BTC * 5, - faucet, - &bitcoind, - ) - .await?; - - let faucet_ready_timeout = Duration::from_secs(60); - - tracing::info!(timeout = ?faucet_ready_timeout, "Waiting until new faucet channel is ready"); - - tokio::time::timeout(faucet_ready_timeout, async { - loop { - if let Some(faucet_node_info) = get_node_info(faucet).await? { - if faucet_node_info.num_channels > 0 - && faucet_node_info.node.alias == "10101.finance" - { - return anyhow::Ok(()); - } - } - - let retry_interval = Duration::from_secs(1); - tracing::info!(?retry_interval, "Faucet channel not yet ready. Retrying"); - - // Manually broadcasting node announcement to get the channel ready ASAP. - coordinator.broadcast_node_announcement().await?; - - tokio::time::sleep(retry_interval).await; - } - }) - .await - .with_context(|| { - format!( - "New faucet channel not ready after {faucet_ready_timeout:?}. Please wipe and try again" - ) - })??; - - let lnd_channels = get_text(&format!("{faucet}/lnd/v1/channels")).await?; - tracing::info!("Open faucet channels: {}", lnd_channels); - - maker - .open_channel(coordinator_node_info, 10_000_000, None) - .await - .expect("To be able to open a channel from maker to coordinator"); - let maker_node_info = maker.get_node_info().await.expect("To get node info"); - - tracing::info!( - ?maker_node_info, - ?coordinator_node_info, - "Opened channel from maker to coordinator", - ); - - bitcoind.mine(10).await?; - - maker - .sync() - .await - .expect("to be able to sync on-chain wallet for maker"); - let maker_balance = maker.get_balance().await?; - tracing::info!( - onchain = %maker_balance.onchain, - offchain = %maker_balance.offchain, - "Maker balance", - ); - - Ok(()) -} - -#[derive(Deserialize)] -struct LndAddr { - address: Address, -} - -async fn get_text(url: &str) -> Result { - Ok(reqwest::get(url).await?.text().await?) -} - -async fn post_query(path: &str, body: String, faucet: &str) -> Result { - let faucet = faucet.to_string(); - let client = init_reqwest(); - let response = client - .post(format!("{faucet}/{path}")) - .body(body) - .send() - .await?; - - if !response.status().is_success() { - bail!(response.text().await?) - } - Ok(response) -} - -async fn get_query(path: &str, faucet: &str) -> Result { - let faucet = faucet.to_string(); - let client = init_reqwest(); - let response = client.get(format!("{faucet}/{path}")).send().await?; - - Ok(response) -} - -#[derive(Deserialize, Debug, Clone)] -pub struct LndNodeInfo { - node: Node, - num_channels: u32, -} - -#[derive(Deserialize, Debug, Clone)] -pub struct Node { - alias: String, -} - -async fn get_node_info(faucet: &str) -> Result> { - let response = get_query( - "lnd/v1/graph/node/02dd6abec97f9a748bf76ad502b004ce05d1b2d1f43a9e76bd7d85e767ffb022c9", - faucet, - ) - .await?; - if response.status() == StatusCode::NOT_FOUND { - tracing::warn!("Node info not yet found."); - return Ok(None); - } - - let node_info = response.json().await?; - Ok(Some(node_info)) -} - -/// Instructs lnd to open a public channel with the target node. -/// 1. Connect to the target node. -/// 2. Open channel to the target node. -async fn open_channel( - node_info: &NodeInfo, - amount: Amount, - faucet: &str, - bitcoind: &Bitcoind, -) -> Result<()> { - // Hacky way of checking whether we need to patch the coordinator - // address when running locally - let host = if faucet.to_string().contains("localhost") { - let port = node_info.address.port(); - let ip_address = local_ip()?; - let host = format!("{ip_address}:{port}"); - tracing::info!("Running locally, patching host to {host}"); - host - } else { - node_info.address.to_string() - }; - tracing::info!("Connecting lnd to {host}"); - let res = post_query( - "lnd/v1/peers", - format!( - r#"{{"addr": {{ "pubkey": "{}", "host": "{host}" }}, "perm":false }}"]"#, - node_info.pubkey - ), - faucet, - ) - .await; - - tracing::debug!(?res, "Response after attempting to connect lnd to {host}"); - - tokio::time::sleep(Duration::from_secs(5)).await; - - tracing::info!("Opening channel to {} with {amount}", node_info); - post_query( - "lnd/v1/channels", - format!( - r#"{{"node_pubkey_string":"{}","local_funding_amount":"{}", "min_confs":1 }}"#, - node_info.pubkey, - amount.to_sat() - ), - faucet, - ) - .await?; - - bitcoind.mine(10).await?; - - tracing::info!("connected to channel"); - - tracing::info!("You can now use the lightning faucet {faucet}/faucet/"); - Ok(()) } From 9e134060856bf707dc3d16a345491789f0da85d0 Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Wed, 3 Jan 2024 12:21:45 +0100 Subject: [PATCH 09/15] chore: extract fund into own crate for faster compile time Signed-off-by: Philipp Hoenisch --- Cargo.lock | 17 +++ crates/commons/Cargo.toml | 7 +- crates/fund/Cargo.toml | 18 +++ crates/{tests-e2e => fund}/examples/fund.rs | 11 +- crates/fund/src/bitcoind.rs | 90 ++++++++++++ crates/fund/src/coordinator.rs | 153 ++++++++++++++++++++ crates/fund/src/http.rs | 8 + crates/fund/src/lib.rs | 5 + justfile | 2 +- 9 files changed, 301 insertions(+), 10 deletions(-) create mode 100644 crates/fund/Cargo.toml rename crates/{tests-e2e => fund}/examples/fund.rs (93%) create mode 100644 crates/fund/src/bitcoind.rs create mode 100644 crates/fund/src/coordinator.rs create mode 100644 crates/fund/src/http.rs create mode 100644 crates/fund/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 5bc3099b0..bd363509a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -652,6 +652,7 @@ dependencies = [ "rust_decimal", "rust_decimal_macros", "secp256k1", + "secp256k1-zkp", "serde", "serde_json", "sha2", @@ -1325,6 +1326,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "fund" +version = "0.1.0" +dependencies = [ + "anyhow", + "bitcoin", + "clap", + "commons", + "reqwest", + "serde", + "time 0.3.20", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "futures" version = "0.3.26" diff --git a/crates/commons/Cargo.toml b/crates/commons/Cargo.toml index 2d24a1dc2..035891c2a 100644 --- a/crates/commons/Cargo.toml +++ b/crates/commons/Cargo.toml @@ -7,11 +7,13 @@ edition = "2021" [dependencies] anyhow = "1" -bdk = { version = "0.28.0", default-features = false, features = ["key-value-db", "use-esplora-blocking"] } +bdk = { version = "0.28.0", default-features = false, features = ["key-value-db", "use-esplora-blocking", "std"] } bitcoin = { version = "0.29.2", features = ["serde"] } lightning = "0.0.117" rust_decimal = { version = "1", features = ["serde-with-float"] } +rust_decimal_macros = "1" secp256k1 = { version = "0.24.3", features = ["serde"] } +secp256k1-zkp = { version = "0.7.0", features = ["global-context"] } serde = { version = "1", features = ["derive"] } serde_json = "1" sha2 = { version = "0.10", default-features = false } @@ -19,6 +21,3 @@ time = { version = "0.3", features = ["serde", "std"] } tokio-tungstenite = { version = "0.20" } trade = { path = "../trade" } uuid = { version = "1.3.0", features = ["v4", "serde"] } - -[dev-dependencies] -rust_decimal_macros = "1" diff --git a/crates/fund/Cargo.toml b/crates/fund/Cargo.toml new file mode 100644 index 000000000..2efbd6270 --- /dev/null +++ b/crates/fund/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "fund" +version = "0.1.0" +edition = "2021" + +[lib] + +[dependencies] +anyhow = "1" +bitcoin = "0.29.2" +clap = { version = "4", features = ["derive"] } +commons = { path = "../commons" } +reqwest = { version = "0.11", default-features = false, features = ["json"] } +serde = { version = "1.0.152", features = ["serde_derive"] } +time = { version = "0.3", features = ["serde", "serde-well-known"] } +tokio = { version = "1", default-features = false, features = ["io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time", "tracing"] } +tracing = "0.1.37" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/crates/tests-e2e/examples/fund.rs b/crates/fund/examples/fund.rs similarity index 93% rename from crates/tests-e2e/examples/fund.rs rename to crates/fund/examples/fund.rs index 4652f093c..2e933e6d6 100644 --- a/crates/tests-e2e/examples/fund.rs +++ b/crates/fund/examples/fund.rs @@ -2,10 +2,9 @@ use anyhow::Context; use anyhow::Result; use bitcoin::Amount; use clap::Parser; -use ln_dlc_node::node::NodeInfo; -use tests_e2e::bitcoind; -use tests_e2e::coordinator::Coordinator; -use tests_e2e::http::init_reqwest; +use fund::bitcoind; +use fund::coordinator::Coordinator; +use fund::http::init_reqwest; use tracing::metadata::LevelFilter; use tracing_subscriber::filter::Directive; use tracing_subscriber::layer::SubscriberExt; @@ -49,6 +48,8 @@ async fn fund_everything(faucet: &str, coordinator: &str) -> Result<()> { .context("Could not fund the faucet's on-chain wallet")?; bitcoind.mine(10).await?; + coordinator.sync_wallet().await?; + let coordinator_balance = coordinator.get_balance().await?; tracing::info!( onchain = %Amount::from_sat(coordinator_balance.onchain), @@ -56,7 +57,7 @@ async fn fund_everything(faucet: &str, coordinator: &str) -> Result<()> { "Coordinator balance", ); - let coordinator_node_info: NodeInfo = coordinator.get_node_info().await?; + let coordinator_node_info = coordinator.get_node_info().await?; tracing::info!(?coordinator_node_info); Ok(()) } diff --git a/crates/fund/src/bitcoind.rs b/crates/fund/src/bitcoind.rs new file mode 100644 index 000000000..1bb649a8c --- /dev/null +++ b/crates/fund/src/bitcoind.rs @@ -0,0 +1,90 @@ +use anyhow::bail; +use anyhow::Result; +use bitcoin::Address; +use bitcoin::Amount; +use reqwest::Client; +use reqwest::Response; +use serde::Deserialize; +use std::time::Duration; + +/// A wrapper over the bitcoind HTTP API +/// +/// It does not aim to be complete, functionality will be added as needed +pub struct Bitcoind { + client: Client, + host: String, +} + +impl Bitcoind { + pub fn new(client: Client, host: String) -> Self { + Self { client, host } + } + + pub fn new_local(client: Client) -> Self { + let host = "http://localhost:8080/bitcoin".to_string(); + Self::new(client, host) + } + + /// Instructs `bitcoind` to generate to address. + pub async fn mine(&self, n: u16) -> Result<()> { + #[derive(Deserialize, Debug)] + struct BitcoindResponse { + result: String, + } + + let response: BitcoindResponse = self + .client + .post(&self.host) + .body(r#"{"jsonrpc": "1.0", "method": "getnewaddress", "params": []}"#.to_string()) + .send() + .await? + .json() + .await?; + + self.client + .post(&self.host) + .body(format!( + r#"{{"jsonrpc": "1.0", "method": "generatetoaddress", "params": [{}, "{}"]}}"#, + n, response.result + )) + .send() + .await?; + + // For the mined blocks to be picked up by the subsequent wallet syncs + tokio::time::sleep(Duration::from_secs(5)).await; + + Ok(()) + } + + /// An alias for send_to_address + pub async fn fund(&self, address: &Address, amount: Amount) -> Result { + self.send_to_address(address, amount).await + } + + pub async fn send_to_address(&self, address: &Address, amount: Amount) -> Result { + let response = self + .client + .post(&self.host) + .body(format!( + r#"{{"jsonrpc": "1.0", "method": "sendtoaddress", "params": ["{}", "{}", "", "", false, false, null, null, false, 1.0]}}"#, + address, + amount.to_btc(), + )) + .send() + .await?; + Ok(response) + } + + pub async fn post(&self, endpoint: &str, body: Option) -> Result { + let mut builder = self.client.post(endpoint.to_string()); + if let Some(body) = body { + builder = builder.body(body); + } + let response = builder.send().await?; + + if !response.status().is_success() { + bail!(response.text().await?) + } + Ok(response) + } +} diff --git a/crates/fund/src/coordinator.rs b/crates/fund/src/coordinator.rs new file mode 100644 index 000000000..c0b44658d --- /dev/null +++ b/crates/fund/src/coordinator.rs @@ -0,0 +1,153 @@ +use anyhow::Context; +use anyhow::Result; +use bitcoin::secp256k1::PublicKey; +use bitcoin::Address; +use reqwest::Client; +use serde::Deserialize; +use serde::Serialize; +use std::net::SocketAddr; + +#[derive(Debug, Clone, Copy, Deserialize, Serialize)] +pub struct NodeInfo { + pub pubkey: PublicKey, + pub address: SocketAddr, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct InvoiceParams { + pub amount: Option, + pub description: Option, + pub expiry: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Balance { + pub offchain: u64, + pub onchain: u64, +} + +/// A wrapper over the coordinator HTTP API. +/// +/// It does not aim to be complete, functionality will be added as needed. +pub struct Coordinator { + client: Client, + host: String, +} + +#[derive(Deserialize)] +pub struct DlcChannels { + #[serde(flatten)] + pub channel_details: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct DlcChannel { + pub channel_id: String, + pub dlc_channel_id: Option, + pub counter_party: String, + pub subchannel_state: SubChannelState, +} +#[derive(Deserialize, Debug)] +pub struct Channel { + pub channel_id: String, + pub counterparty: String, + pub funding_txo: Option, + pub original_funding_txo: Option, + pub outbound_capacity_msat: u64, +} + +#[derive(Deserialize, Debug, PartialEq, Eq)] +pub enum SubChannelState { + Signed, + Closing, + OnChainClosed, + CounterOnChainClosed, + CloseConfirmed, + // We don't care about other states for now + #[serde(other)] + Other, +} + +impl Coordinator { + pub fn new(client: Client, host: &str) -> Self { + Self { + client, + host: host.to_string(), + } + } + + pub fn new_local(client: Client) -> Self { + Self::new(client, "http://localhost:8000") + } + + /// Check whether the coordinator is running. + pub async fn is_running(&self) -> bool { + self.get("/health").await.is_ok() + } + + pub async fn is_node_connected(&self, node_id: &str) -> Result { + let result = self + .get(&format!("/api/admin/is_connected/{node_id}")) + .await? + .status() + .is_success(); + Ok(result) + } + + pub async fn sync_wallet(&self) -> Result<()> { + self.post("/api/admin/sync").await?; + Ok(()) + } + + pub async fn get_new_address(&self) -> Result
{ + Ok(self.get("/api/newaddress").await?.text().await?.parse()?) + } + + pub async fn get_balance(&self) -> Result { + Ok(self.get("/api/admin/balance").await?.json().await?) + } + + pub async fn get_node_info(&self) -> Result { + self.get("/api/node") + .await? + .json() + .await + .context("could not parse json") + } + + pub async fn broadcast_node_announcement(&self) -> Result { + let status = self + .post("/api/admin/broadcast_announcement") + .await? + .error_for_status()?; + Ok(status) + } + + pub async fn get_dlc_channels(&self) -> Result> { + Ok(self.get("/api/admin/dlc_channels").await?.json().await?) + } + + pub async fn get_channels(&self) -> Result> { + Ok(self.get("/api/admin/channels").await?.json().await?) + } + + async fn get(&self, path: &str) -> Result { + self.client + .get(format!("{0}{path}", self.host)) + .send() + .await + .context("Could not send GET request to coordinator")? + .error_for_status() + .context("Coordinator did not return 200 OK") + } + + async fn post(&self, path: &str) -> Result { + self.client + .post(format!("{0}{path}", self.host)) + .send() + .await + .context("Could not send POST request to coordinator")? + .error_for_status() + .context("Coordinator did not return 200 OK") + } +} diff --git a/crates/fund/src/http.rs b/crates/fund/src/http.rs new file mode 100644 index 000000000..5dd5345cb --- /dev/null +++ b/crates/fund/src/http.rs @@ -0,0 +1,8 @@ +use reqwest::Client; + +pub fn init_reqwest() -> Client { + Client::builder() + .timeout(std::time::Duration::from_secs(30)) + .build() + .unwrap() +} diff --git a/crates/fund/src/lib.rs b/crates/fund/src/lib.rs new file mode 100644 index 000000000..b7d5d54f3 --- /dev/null +++ b/crates/fund/src/lib.rs @@ -0,0 +1,5 @@ +#![allow(clippy::unwrap_used)] + +pub mod bitcoind; +pub mod coordinator; +pub mod http; diff --git a/justfile b/justfile index f6a114ca6..1b8b3022a 100644 --- a/justfile +++ b/justfile @@ -160,7 +160,7 @@ run-local-android args="": --flavor local fund args="": - cargo run -p tests-e2e --example fund + cargo run -p fund --example fund # Fund remote regtest instance fund-regtest: From b477eb3a640c6ae03bd32478c471b0160111e699 Mon Sep 17 00:00:00 2001 From: Philipp Hoenisch Date: Tue, 2 Jan 2024 10:28:58 +0100 Subject: [PATCH 10/15] feat: Allow opening a vanilla DLC channel --- Cargo.lock | 10 +- Cargo.toml | 10 +- coordinator/src/collaborative_revert.rs | 3 +- coordinator/src/node.rs | 44 ++- coordinator/src/node/resize.rs | 8 +- crates/ln-dlc-node/src/ldk_node_wallet.rs | 7 +- crates/ln-dlc-node/src/ln_dlc_wallet.rs | 75 +++-- crates/ln-dlc-node/src/node/dlc_channel.rs | 302 ++++++++++++++++++ crates/ln-dlc-node/src/node/mod.rs | 1 + crates/ln-dlc-node/src/node/sub_channel.rs | 34 +- .../src/tests/dlc/collaborative_settlement.rs | 10 +- crates/ln-dlc-node/src/tests/dlc/create.rs | 12 +- .../tests/dlc/dlc_setup_with_reconnects.rs | 48 +-- crates/ln-dlc-node/src/tests/dlc_channel.rs | 89 ++++++ crates/ln-dlc-node/src/tests/load.rs | 10 +- crates/ln-dlc-node/src/tests/mod.rs | 7 +- mobile/native/src/ln_dlc/mod.rs | 7 +- mobile/native/src/ln_dlc/node.rs | 134 +++++++- 18 files changed, 663 insertions(+), 148 deletions(-) create mode 100644 crates/ln-dlc-node/src/node/dlc_channel.rs create mode 100644 crates/ln-dlc-node/src/tests/dlc_channel.rs diff --git a/Cargo.lock b/Cargo.lock index bd363509a..522907432 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1092,7 +1092,7 @@ dependencies = [ [[package]] name = "dlc" version = "0.4.0" -source = "git+https://github.com/p2pderivatives/rust-dlc?rev=f235bd2#f235bd2ca2be6b51b61a342deffb36b766d595ba" +source = "git+https://github.com/p2pderivatives/rust-dlc?rev=3286a6a#3286a6a73fae55622b26ed5a2e2728a6adb0fa9c" dependencies = [ "bitcoin", "miniscript 8.0.2", @@ -1104,7 +1104,7 @@ dependencies = [ [[package]] name = "dlc-manager" version = "0.4.0" -source = "git+https://github.com/p2pderivatives/rust-dlc?rev=f235bd2#f235bd2ca2be6b51b61a342deffb36b766d595ba" +source = "git+https://github.com/p2pderivatives/rust-dlc?rev=3286a6a#3286a6a73fae55622b26ed5a2e2728a6adb0fa9c" dependencies = [ "async-trait", "bitcoin", @@ -1120,7 +1120,7 @@ dependencies = [ [[package]] name = "dlc-messages" version = "0.4.0" -source = "git+https://github.com/p2pderivatives/rust-dlc?rev=f235bd2#f235bd2ca2be6b51b61a342deffb36b766d595ba" +source = "git+https://github.com/p2pderivatives/rust-dlc?rev=3286a6a#3286a6a73fae55622b26ed5a2e2728a6adb0fa9c" dependencies = [ "bitcoin", "dlc", @@ -1133,7 +1133,7 @@ dependencies = [ [[package]] name = "dlc-trie" version = "0.4.0" -source = "git+https://github.com/p2pderivatives/rust-dlc?rev=f235bd2#f235bd2ca2be6b51b61a342deffb36b766d595ba" +source = "git+https://github.com/p2pderivatives/rust-dlc?rev=3286a6a#3286a6a73fae55622b26ed5a2e2728a6adb0fa9c" dependencies = [ "bitcoin", "dlc", @@ -2584,7 +2584,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p2pd-oracle-client" version = "0.1.0" -source = "git+https://github.com/p2pderivatives/rust-dlc?rev=f235bd2#f235bd2ca2be6b51b61a342deffb36b766d595ba" +source = "git+https://github.com/p2pderivatives/rust-dlc?rev=3286a6a#3286a6a73fae55622b26ed5a2e2728a6adb0fa9c" dependencies = [ "chrono", "dlc-manager", diff --git a/Cargo.toml b/Cargo.toml index c6b125f79..caf7e3096 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,11 +22,11 @@ resolver = "2" # `p2pderivatives/rust-dlc#feature/ln-dlc-channels`: 4e104b4. This patch ensures backwards # compatibility for 10101 through the `rust-lightning:0.0.116` upgrade. We will be able to drop it # once all users have been upgraded and traded once. -dlc-manager = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "f235bd2" } -dlc-messages = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "f235bd2" } -dlc = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "f235bd2" } -p2pd-oracle-client = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "f235bd2" } -dlc-trie = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "f235bd2" } +dlc-manager = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "3286a6a" } +dlc-messages = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "3286a6a" } +dlc = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "3286a6a" } +p2pd-oracle-client = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "3286a6a" } +dlc-trie = { git = "https://github.com/p2pderivatives/rust-dlc", rev = "3286a6a" } # We should usually track the `p2pderivatives/split-tx-experiment[-10101]` branch. lightning = { git = "https://github.com/p2pderivatives/rust-lightning/", rev = "121bc324" } diff --git a/coordinator/src/collaborative_revert.rs b/coordinator/src/collaborative_revert.rs index 61a6ef6b7..55ec25a9d 100644 --- a/coordinator/src/collaborative_revert.rs +++ b/coordinator/src/collaborative_revert.rs @@ -446,8 +446,7 @@ pub fn confirm_collaborative_revert( if let Some(mut subchannel) = optional_subchannel.cloned() { subchannel.state = SubChannelState::OnChainClosed; - node.sub_channel_manager - .get_dlc_manager() + node.dlc_manager .get_store() .upsert_sub_channel(&subchannel)?; } diff --git a/coordinator/src/node.rs b/coordinator/src/node.rs index ec7249490..9482ed9db 100644 --- a/coordinator/src/node.rs +++ b/coordinator/src/node.rs @@ -325,16 +325,11 @@ impl Node { }], }; - let channel_details = self.get_counterparty_channel(trade_params.pubkey)?; - self.inner - .propose_sub_channel(channel_details.clone(), contract_input) - .await - .context("Could not propose dlc channel")?; - let temporary_contract_id = self .inner - .get_temporary_contract_id_by_sub_channel_id(channel_details.channel_id) - .context("unable to extract temporary contract id")?; + .propose_dlc_channel(contract_input, trade_params.pubkey) + .await + .context("Could not propose dlc channel")?; // After the dlc channel has been proposed the position can be created. Note, this // fixes https://github.com/get10101/10101/issues/537, where the position was created @@ -607,7 +602,7 @@ impl Node { .on_dlc_message(&msg, node_id) .with_context(|| { format!( - "Failed to handle {} message from {node_id}", + "Failed to handle {} dlc message from {node_id}", dlc_message_name(&msg) ) })?, @@ -734,21 +729,22 @@ impl Node { Ok(()) } - fn coordinator_leverage_for_trade(&self, counterparty_peer_id: &PublicKey) -> Result { - let mut conn = self.pool.get()?; - - let channel_details = self.get_counterparty_channel(*counterparty_peer_id)?; - let user_channel_id = Uuid::from_u128(channel_details.user_channel_id).to_string(); - let channel = db::channels::get(&user_channel_id, &mut conn)?.with_context(|| { - format!("Couldn't find shadow channel with user channel ID {user_channel_id}",) - })?; - let leverage_coordinator = match channel.liquidity_option_id { - Some(liquidity_option_id) => { - let liquidity_option = db::liquidity_options::get(&mut conn, liquidity_option_id)?; - liquidity_option.coordinator_leverage - } - None => 1.0, - }; + fn coordinator_leverage_for_trade(&self, _counterparty_peer_id: &PublicKey) -> Result { + // TODO(bonomat): we will need to configure the leverage on the coordinator differently now + // let channel_details = self.get_counterparty_channel(*counterparty_peer_id)?; + // let user_channel_id = Uuid::from_u128(channel_details.user_channel_id).to_string(); + // let channel = db::channels::get(&user_channel_id, &mut conn)?.with_context(|| { + // format!("Couldn't find shadow channel with user channel ID {user_channel_id}",) + // })?; + // let leverage_coordinator = match channel.liquidity_option_id { + // Some(liquidity_option_id) => { + // let liquidity_option = db::liquidity_options::get(&mut conn, + // liquidity_option_id)?; liquidity_option.coordinator_leverage + // } + // None => 1.0, + // }; + + let leverage_coordinator = 2.0; Ok(leverage_coordinator) } diff --git a/coordinator/src/node/resize.rs b/coordinator/src/node/resize.rs index 1abc79bd5..ad1cfa60a 100644 --- a/coordinator/src/node/resize.rs +++ b/coordinator/src/node/resize.rs @@ -297,9 +297,11 @@ impl Node { tokio::spawn({ let node = self.inner.clone(); async move { - if let Err(e) = node - .propose_sub_channel(channel_details.clone(), contract_input) - .await + if let Err(e) = + // TODO(bonomat): we will need to use the new dlc channel protocol here + node + .propose_sub_channel(channel_details.clone(), contract_input) + .await { tracing::error!( channel_id = %channel_details.channel_id.to_hex(), diff --git a/crates/ln-dlc-node/src/ldk_node_wallet.rs b/crates/ln-dlc-node/src/ldk_node_wallet.rs index 698210a51..9375b7bb5 100644 --- a/crates/ln-dlc-node/src/ldk_node_wallet.rs +++ b/crates/ln-dlc-node/src/ldk_node_wallet.rs @@ -93,7 +93,7 @@ where } } - fn bdk_lock(&self) -> MutexGuard> { + pub fn bdk_lock(&self) -> MutexGuard> { self.inner.lock() } @@ -200,6 +200,11 @@ where Ok(self.bdk_lock().get_balance()?) } + pub fn get_utxos(&self) -> Result, Error> { + let utxos = self.bdk_lock().list_unspent()?; + Ok(utxos) + } + /// Build the PSBT for sending funds to a given address. fn build_psbt( &self, diff --git a/crates/ln-dlc-node/src/ln_dlc_wallet.rs b/crates/ln-dlc-node/src/ln_dlc_wallet.rs index 7aefac035..c5e500033 100644 --- a/crates/ln-dlc-node/src/ln_dlc_wallet.rs +++ b/crates/ln-dlc-node/src/ln_dlc_wallet.rs @@ -9,7 +9,9 @@ use anyhow::Result; use bdk::blockchain::EsploraBlockchain; use bdk::esplora_client::TxStatus; use bdk::sled; +use bdk::SignOptions; use bdk::TransactionDetails; +use bitcoin::psbt::PartiallySignedTransaction; use bitcoin::secp256k1::All; use bitcoin::secp256k1::PublicKey; use bitcoin::secp256k1::Secp256k1; @@ -21,7 +23,6 @@ use bitcoin::KeyPair; use bitcoin::Network; use bitcoin::Script; use bitcoin::Transaction; -use bitcoin::TxOut; use bitcoin::Txid; use dlc_manager::error::Error; use dlc_manager::Blockchain; @@ -226,37 +227,32 @@ impl Blockchain for LnDlcWallet { } impl Signer for LnDlcWallet { - fn sign_tx_input( - &self, - tx: &mut Transaction, - input_index: usize, - tx_out: &TxOut, - _: Option