From 25ef91ce67b0b3a2cf4f8b0f5c1c6ceb08604dd3 Mon Sep 17 00:00:00 2001 From: Psycho-Pirate Date: Thu, 16 Jan 2025 14:37:22 +0530 Subject: [PATCH 1/2] Custom Keysmanager and openchannel_without_peer_addr added MyKeysManager is a custom keysmanager that can be used to set custom channel secrets. Setting custom channel is essential for interacting with Lnprototest. A method called openchannel_without_peer_addr is also added. This allows creating a channel with a peer that is already connected. This is also needed for Lnprototest tests regarding open channel. --- src/args.rs | 14 +++- src/cli.rs | 56 ++++++++++++- src/keys.rs | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 72 +++++++++++++--- src/sweep.rs | 5 +- 5 files changed, 362 insertions(+), 16 deletions(-) create mode 100644 src/keys.rs diff --git a/src/args.rs b/src/args.rs index e59852ed..6634d9fe 100644 --- a/src/args.rs +++ b/src/args.rs @@ -9,7 +9,7 @@ use std::str::FromStr; pub(crate) fn parse_startup_args() -> Result { if env::args().len() < 3 { - println!("ldk-tutorial-node requires at least 2 arguments: `cargo run [:@]: ldk_storage_directory_path [] [bitcoin-network] [announced-node-name announced-listen-addr*]`"); + println!("ldk-tutorial-node requires at least 2 arguments: `cargo run [:@]: ldk_storage_directory_path [] [bitcoin-network] [channel-secrets] [announced-node-name announced-listen-addr*]`"); return Err(()); } let bitcoind_rpc_info = env::args().skip(1).next().unwrap(); @@ -69,6 +69,17 @@ pub(crate) fn parse_startup_args() -> Result { return Err(()); }; + let channel_secrets = match env::args().skip(arg_idx + 1).next() { + Some(s) => { + if s.len() != 389 { + panic!("Channel secrets should be seperated by '/' and total string length should be 389"); + } + arg_idx += 1; + Some(s) + } + None => None, + }; + let ldk_announced_node_name = match env::args().skip(arg_idx + 1).next().as_ref() { Some(s) => { if s.len() > 32 { @@ -106,6 +117,7 @@ pub(crate) fn parse_startup_args() -> Result { ldk_announced_listen_addr, ldk_announced_node_name, network, + channel_secrets, }) } diff --git a/src/cli.rs b/src/cli.rs index c55623af..b485bede 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,5 +1,6 @@ use crate::disk::{self, INBOUND_PAYMENTS_FNAME, OUTBOUND_PAYMENTS_FNAME}; use crate::hex_utils; +use crate::keys::MyKeysManager; use crate::{ ChainMonitor, ChannelManager, HTLCStatus, InboundPaymentInfoStorage, MillisatAmount, NetworkGraph, OutboundPaymentInfoStorage, PaymentInfo, PeerManager, @@ -18,7 +19,7 @@ use lightning::ln::types::ChannelId; use lightning::offers::offer::{self, Offer}; use lightning::routing::gossip::NodeId; use lightning::routing::router::{PaymentParameters, RouteParameters}; -use lightning::sign::{EntropySource, KeysManager}; +use lightning::sign::EntropySource; use lightning::types::payment::{PaymentHash, PaymentPreimage}; use lightning::util::config::{ChannelHandshakeConfig, ChannelHandshakeLimits, UserConfig}; use lightning::util::persist::KVStore; @@ -43,11 +44,12 @@ pub(crate) struct LdkUserInfo { pub(crate) ldk_announced_listen_addr: Vec, pub(crate) ldk_announced_node_name: [u8; 32], pub(crate) network: Network, + pub(crate) channel_secrets: Option, } pub(crate) fn poll_for_user_input( peer_manager: Arc, channel_manager: Arc, - chain_monitor: Arc, keys_manager: Arc, + chain_monitor: Arc, keys_manager: Arc, network_graph: Arc, inbound_payments: Arc>, outbound_payments: Arc>, ldk_data_dir: String, network: Network, logger: Arc, fs_store: Arc, @@ -74,6 +76,54 @@ pub(crate) fn poll_for_user_input( if let Some(word) = words.next() { match word { "help" => help(), + "openchannel_without_peer_addr" => { + // opens a channel with a connected node + let peer_pubkey = words.next(); + let channel_value_sat = words.next(); + if peer_pubkey.is_none() || channel_value_sat.is_none() { + println!("ERROR: openchannel_without_peer_addr has 2 required arguments: `openchannel_without_peer_addr pubkey channel_amt_satoshis` [--public]"); + continue; + } + let peer_pubkey = peer_pubkey.unwrap(); + let chan_amt_sat: Result = channel_value_sat.unwrap().parse(); + if chan_amt_sat.is_err() { + println!("ERROR: channel amount must be a number"); + continue; + } + + + let (mut announce_channel, mut with_anchors) = (false, false); + while let Some(word) = words.next() { + match word { + "--public" | "--public=true" => announce_channel = true, + "--public=false" => announce_channel = false, + "--with-anchors" | "--with-anchors=true" => with_anchors = true, + "--with-anchors=false" => with_anchors = false, + _ => { + println!("ERROR: invalid boolean flag format. Valid formats: `--option`, `--option=true` `--option=false`"); + continue; + }, + } + } + let pubkey = peer_pubkey; + let pubkey = hex_utils::to_compressed_pubkey(pubkey); + if open_channel( + pubkey.unwrap(), + chan_amt_sat.unwrap(), + announce_channel, + with_anchors, + channel_manager.clone(), + ) + .is_ok() + { + // let peer_data_path = format!("{}/channel_peer_data", ldk_data_dir.clone()); + // let _ = disk::persist_channel_peer( + // Path::new(&peer_data_path), + // peer_pubkey_and_ip_addr, + // ); + } + }, + "openchannel" => { let peer_pubkey_and_ip_addr = words.next(); let channel_value_sat = words.next(); @@ -848,7 +898,7 @@ fn keysend( fn get_invoice( amt_msat: u64, inbound_payments: &mut InboundPaymentInfoStorage, - channel_manager: &ChannelManager, keys_manager: Arc, network: Network, + channel_manager: &ChannelManager, keys_manager: Arc, network: Network, expiry_secs: u32, logger: Arc, ) { let currency = match network { diff --git a/src/keys.rs b/src/keys.rs new file mode 100644 index 00000000..090771eb --- /dev/null +++ b/src/keys.rs @@ -0,0 +1,231 @@ +use std::sync::Arc; + +use bitcoin::secp256k1::{Secp256k1, SecretKey}; +use lightning::sign::{InMemorySigner, NodeSigner, OutputSpender, SignerProvider}; + +use lightning::sign::{EntropySource, KeysManager}; +use lightning_invoice::RawBolt11Invoice; + +pub struct MyKeys { + pub keys_manager: Arc, +} + +impl MyKeys { + pub fn new(seed: [u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self { + MyKeys { + keys_manager: Arc::new(MyKeysManager::new( + &seed, + starting_time_secs, + starting_time_nanos, + )), + } + } + + pub fn with_channel_keys(seed: [u8; 32], starting_time_secs: u64, starting_time_nanos: u32, channels_keys: String) -> Self { + let keys = channels_keys.split('/').collect::>(); + + let mut manager = + MyKeysManager::new(&seed, starting_time_secs, starting_time_nanos); + manager.set_channel_keys( + keys[0].to_string(), + keys[1].to_string(), + keys[2].to_string(), + keys[3].to_string(), + keys[4].to_string(), + keys[5].to_string(), + ); + MyKeys { + keys_manager: Arc::new(manager), + } + } + + pub fn inner(&self) -> Arc { + self.keys_manager.clone() + } +} + +/// MyKeysManager is a custom keysmanager that allows the use of custom channel secrets. +pub struct MyKeysManager { + pub(crate) inner: KeysManager, + + funding_key: Option, + revocation_base_secret: Option, + payment_base_secret: Option, + delayed_payment_base_secret: Option, + htlc_base_secret: Option, + shachain_seed: Option<[u8; 32]>, +} + +impl MyKeysManager { + pub fn new(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self { + let inner = KeysManager::new(seed, starting_time_secs, starting_time_nanos); + Self { + inner, + funding_key: None, + revocation_base_secret: None, + payment_base_secret: None, + delayed_payment_base_secret: None, + htlc_base_secret: None, + shachain_seed: None, + } + } + + pub fn get_node_secret_key(&self) -> SecretKey { + self.inner.get_node_secret_key() + } + + pub fn set_channel_keys( + &mut self, + funding_key: String, + revocation_base_secret: String, + payment_base_secret: String, + delayed_payment_base_secret: String, + htlc_base_secret: String, + _shachain_seed: String, + ) { + use std::str::FromStr; + + self.funding_key = Some(SecretKey::from_str(&funding_key).unwrap()); + self.revocation_base_secret = Some(SecretKey::from_str(&revocation_base_secret).unwrap()); + self.payment_base_secret = Some(SecretKey::from_str(&payment_base_secret).unwrap()); + self.delayed_payment_base_secret = + Some(SecretKey::from_str(&delayed_payment_base_secret).unwrap()); + self.htlc_base_secret = Some(SecretKey::from_str(&htlc_base_secret).unwrap()); + self.shachain_seed = Some(self.inner.get_secure_random_bytes()) + } +} + +impl EntropySource for MyKeysManager { + fn get_secure_random_bytes(&self) -> [u8; 32] { + self.inner.get_secure_random_bytes() + } +} + +impl NodeSigner for MyKeysManager { + fn ecdh( + &self, + recipient: lightning::sign::Recipient, + other_key: &bitcoin::secp256k1::PublicKey, + tweak: Option<&bitcoin::secp256k1::Scalar>, + ) -> Result { + self.inner.ecdh(recipient, other_key, tweak) + } + + fn get_inbound_payment_key_material(&self) -> lightning::sign::KeyMaterial { + self.inner.get_inbound_payment_key_material() + } + + fn get_node_id( + &self, + recipient: lightning::sign::Recipient, + ) -> Result { + self.inner.get_node_id(recipient) + } + + fn sign_bolt12_invoice( + &self, + invoice: &lightning::offers::invoice::UnsignedBolt12Invoice, + ) -> Result { + self.inner.sign_bolt12_invoice(invoice) + } + + fn sign_bolt12_invoice_request( + &self, + invoice_request: &lightning::offers::invoice_request::UnsignedInvoiceRequest, + ) -> Result { + self.inner.sign_bolt12_invoice_request(invoice_request) + } + + fn sign_gossip_message( + &self, + msg: lightning::ln::msgs::UnsignedGossipMessage, + ) -> Result { + self.inner.sign_gossip_message(msg) + } + + fn sign_invoice( + &self, + invoice: &RawBolt11Invoice, + recipient: lightning::sign::Recipient, + ) -> Result { + self.inner.sign_invoice(invoice, recipient) + } +} + + +impl OutputSpender for MyKeysManager { + fn spend_spendable_outputs( + &self, + descriptors: &[&lightning::sign::SpendableOutputDescriptor], + outputs: Vec, + change_destination_script: bitcoin::ScriptBuf, + feerate_sat_per_1000_weight: u32, + locktime: Option, + secp_ctx: &bitcoin::secp256k1::Secp256k1, + ) -> Result { + self.inner.spend_spendable_outputs( + descriptors, + outputs, + change_destination_script, + feerate_sat_per_1000_weight, + locktime, + secp_ctx, + ) + } +} + +impl SignerProvider for MyKeysManager { + type EcdsaSigner = InMemorySigner; + + fn derive_channel_signer( + &self, + channel_value_satoshis: u64, + channel_keys_id: [u8; 32], + ) -> Self::EcdsaSigner { + if self.funding_key.is_some() { + let commitment_seed = [ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + ]; + return InMemorySigner::new( + &Secp256k1::new(), + self.funding_key.unwrap(), + self.revocation_base_secret.unwrap(), + self.payment_base_secret.unwrap(), + self.delayed_payment_base_secret.unwrap(), + self.htlc_base_secret.unwrap(), + commitment_seed, + channel_value_satoshis, + channel_keys_id, + self.shachain_seed.unwrap(), + ); + } + self.inner + .derive_channel_signer(channel_value_satoshis, channel_keys_id) + } + + fn generate_channel_keys_id( + &self, + inbound: bool, + channel_value_satoshis: u64, + user_channel_id: u128, + ) -> [u8; 32] { + self.inner + .generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id) + } + + fn get_destination_script(&self, channel_keys_id: [u8; 32]) -> Result { + self.inner.get_destination_script(channel_keys_id) + } + + fn get_shutdown_scriptpubkey(&self) -> Result { + self.inner.get_shutdown_scriptpubkey() + } + + fn read_chan_signer( + &self, + reader: &[u8], + ) -> Result { + self.inner.read_chan_signer(reader) + } +} diff --git a/src/main.rs b/src/main.rs index cfe5705c..ae489781 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,9 +5,12 @@ mod convert; mod disk; mod hex_utils; mod sweep; +mod keys; use crate::bitcoind_client::BitcoindClient; use crate::disk::FilesystemLogger; +use crate::keys::MyKeysManager; +use crate::keys::MyKeys; use bitcoin::blockdata::transaction::Transaction; use bitcoin::consensus::encode; use bitcoin::io; @@ -21,17 +24,20 @@ use lightning::events::bump_transaction::{BumpTransactionEventHandler, Wallet}; use lightning::events::{Event, PaymentFailureReason, PaymentPurpose}; use lightning::ln::channelmanager::{self, RecentPaymentDetails}; use lightning::ln::channelmanager::{ - ChainParameters, ChannelManagerReadArgs, PaymentId, SimpleArcChannelManager, + ChainParameters, ChannelManagerReadArgs, PaymentId }; use lightning::ln::msgs::DecodeError; -use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler, SimpleArcPeerManager}; +use lightning::ln::peer_handler; +use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler}; use lightning::ln::types::ChannelId; -use lightning::onion_message::messenger::{DefaultMessageRouter, SimpleArcOnionMessenger}; +use lightning::onion_message::messenger; +use lightning::onion_message::messenger::DefaultMessageRouter; use lightning::routing::gossip; use lightning::routing::gossip::{NodeId, P2PGossipSync}; use lightning::routing::router::DefaultRouter; +use lightning::routing::scoring::ProbabilisticScorer; use lightning::routing::scoring::ProbabilisticScoringFeeParameters; -use lightning::sign::{EntropySource, InMemorySigner, KeysManager}; +use lightning::sign::{EntropySource, InMemorySigner}; use lightning::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::util::config::UserConfig; use lightning::util::persist::{ @@ -139,8 +145,8 @@ type ChainMonitor = chainmonitor::ChainMonitor< MonitorUpdatingPersister< Arc, Arc, - Arc, - Arc, + Arc, + Arc, Arc, Arc, >, @@ -153,6 +159,16 @@ pub(crate) type GossipVerifier = lightning_block_sync::gossip::GossipVerifier< Arc, >; +pub type SimpleArcPeerManager = peer_handler::PeerManager< + SD, + Arc>, + Arc>>, C, Arc>>, + Arc>, + Arc, + IgnoringMessageHandler, + Arc +>; + pub(crate) type PeerManager = SimpleArcPeerManager< SocketDescriptor, ChainMonitor, @@ -162,18 +178,47 @@ pub(crate) type PeerManager = SimpleArcPeerManager< FilesystemLogger, >; +pub type SimpleArcChannelManager = channelmanager::ChannelManager< + Arc, + Arc, + Arc, + Arc, + Arc, + Arc, + Arc>>, + Arc, + Arc, + Arc>>, Arc>>>, + ProbabilisticScoringFeeParameters, + ProbabilisticScorer>>, Arc>, + >>, + Arc +>; + pub(crate) type ChannelManager = SimpleArcChannelManager; pub(crate) type NetworkGraph = gossip::NetworkGraph>; +pub type SimpleArcOnionMessenger = messenger::OnionMessenger< + Arc, + Arc, + Arc, + Arc>, + Arc>>, Arc, Arc>>, + Arc>, + Arc>, + IgnoringMessageHandler +>; + type OnionMessenger = SimpleArcOnionMessenger; pub(crate) type BumpTxEventHandler = BumpTransactionEventHandler< Arc, Arc, Arc>>, - Arc, + Arc, Arc, >; @@ -184,7 +229,7 @@ pub(crate) type OutputSweeper = ldk_sweep::OutputSweeper< Arc, Arc, Arc, - Arc, + Arc, >; // Needed due to rust-lang/rust#63033. @@ -192,7 +237,7 @@ struct OutputSweeperWrapper(Arc); async fn handle_ldk_events( channel_manager: Arc, bitcoind_client: &BitcoindClient, - network_graph: &NetworkGraph, keys_manager: &KeysManager, + network_graph: &NetworkGraph, keys_manager: &MyKeysManager, bump_tx_event_handler: &BumpTxEventHandler, peer_manager: Arc, inbound_payments: Arc>, outbound_payments: Arc>, fs_store: Arc, @@ -632,8 +677,15 @@ async fn start_ldk() { key }; let cur = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(); - let keys_manager = Arc::new(KeysManager::new(&keys_seed, cur.as_secs(), cur.subsec_nanos())); + let keys_manager = match args.channel_secrets { + Some(ref secrets) => { + MyKeys::with_channel_keys(keys_seed, cur.as_secs(), cur.subsec_nanos(), secrets.to_string()).inner() + } + None => { + MyKeys::new(keys_seed, cur.as_secs(), cur.subsec_nanos()).inner() + } + }; let bump_tx_event_handler = Arc::new(BumpTransactionEventHandler::new( Arc::clone(&broadcaster), Arc::new(Wallet::new(Arc::clone(&bitcoind_client), Arc::clone(&logger))), diff --git a/src/sweep.rs b/src/sweep.rs index 7ab3b824..2e7775ac 100644 --- a/src/sweep.rs +++ b/src/sweep.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::{fs, io}; -use lightning::sign::{EntropySource, KeysManager, SpendableOutputDescriptor}; +use lightning::sign::{EntropySource, SpendableOutputDescriptor}; use lightning::util::logger::Logger; use lightning::util::persist::KVStore; use lightning::util::ser::{Readable, WithoutLength, Writeable}; @@ -12,6 +12,7 @@ use lightning_persister::fs_store::FilesystemStore; use crate::disk::FilesystemLogger; use crate::hex_utils; +use crate::keys::MyKeysManager; use crate::OutputSweeper; const DEPRECATED_PENDING_SPENDABLE_OUTPUT_DIR: &'static str = "pending_spendable_outputs"; @@ -19,7 +20,7 @@ const DEPRECATED_PENDING_SPENDABLE_OUTPUT_DIR: &'static str = "pending_spendable /// We updated to use LDK's OutputSweeper as part of upgrading to LDK 0.0.123, so migrate away from /// the old sweep persistence. pub(crate) async fn migrate_deprecated_spendable_outputs( - ldk_data_dir: String, keys_manager: Arc, logger: Arc, + ldk_data_dir: String, keys_manager: Arc, logger: Arc, persister: Arc, sweeper: Arc, ) { lightning::log_info!(&*logger, "Beginning migration of deprecated spendable outputs"); From ab9b95ad23f680751cb5ed4a664484563382422a Mon Sep 17 00:00:00 2001 From: Psycho-Pirate Date: Thu, 16 Jan 2025 16:16:26 +0530 Subject: [PATCH 2/2] formatting code --- src/args.rs | 2 +- src/cli.rs | 1 - src/keys.rs | 367 ++++++++++++++++++++++++---------------------------- src/main.rs | 48 +++---- 4 files changed, 197 insertions(+), 221 deletions(-) diff --git a/src/args.rs b/src/args.rs index 6634d9fe..22f516e4 100644 --- a/src/args.rs +++ b/src/args.rs @@ -76,7 +76,7 @@ pub(crate) fn parse_startup_args() -> Result { } arg_idx += 1; Some(s) - } + }, None => None, }; diff --git a/src/cli.rs b/src/cli.rs index b485bede..51be7d35 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -91,7 +91,6 @@ pub(crate) fn poll_for_user_input( continue; } - let (mut announce_channel, mut with_anchors) = (false, false); while let Some(word) = words.next() { match word { diff --git a/src/keys.rs b/src/keys.rs index 090771eb..a0b94e0e 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -7,225 +7,200 @@ use lightning::sign::{EntropySource, KeysManager}; use lightning_invoice::RawBolt11Invoice; pub struct MyKeys { - pub keys_manager: Arc, + pub keys_manager: Arc, } impl MyKeys { - pub fn new(seed: [u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self { - MyKeys { - keys_manager: Arc::new(MyKeysManager::new( - &seed, - starting_time_secs, - starting_time_nanos, - )), - } - } - - pub fn with_channel_keys(seed: [u8; 32], starting_time_secs: u64, starting_time_nanos: u32, channels_keys: String) -> Self { - let keys = channels_keys.split('/').collect::>(); - - let mut manager = - MyKeysManager::new(&seed, starting_time_secs, starting_time_nanos); - manager.set_channel_keys( - keys[0].to_string(), - keys[1].to_string(), - keys[2].to_string(), - keys[3].to_string(), - keys[4].to_string(), - keys[5].to_string(), - ); - MyKeys { - keys_manager: Arc::new(manager), - } - } - - pub fn inner(&self) -> Arc { - self.keys_manager.clone() - } + pub fn new(seed: [u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self { + MyKeys { + keys_manager: Arc::new(MyKeysManager::new( + &seed, + starting_time_secs, + starting_time_nanos, + )), + } + } + + pub fn with_channel_keys( + seed: [u8; 32], starting_time_secs: u64, starting_time_nanos: u32, channels_keys: String, + ) -> Self { + let keys = channels_keys.split('/').collect::>(); + + let mut manager = MyKeysManager::new(&seed, starting_time_secs, starting_time_nanos); + manager.set_channel_keys( + keys[0].to_string(), + keys[1].to_string(), + keys[2].to_string(), + keys[3].to_string(), + keys[4].to_string(), + keys[5].to_string(), + ); + MyKeys { keys_manager: Arc::new(manager) } + } + + pub fn inner(&self) -> Arc { + self.keys_manager.clone() + } } /// MyKeysManager is a custom keysmanager that allows the use of custom channel secrets. pub struct MyKeysManager { - pub(crate) inner: KeysManager, - - funding_key: Option, - revocation_base_secret: Option, - payment_base_secret: Option, - delayed_payment_base_secret: Option, - htlc_base_secret: Option, - shachain_seed: Option<[u8; 32]>, + pub(crate) inner: KeysManager, + + funding_key: Option, + revocation_base_secret: Option, + payment_base_secret: Option, + delayed_payment_base_secret: Option, + htlc_base_secret: Option, + shachain_seed: Option<[u8; 32]>, } impl MyKeysManager { - pub fn new(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self { - let inner = KeysManager::new(seed, starting_time_secs, starting_time_nanos); - Self { - inner, - funding_key: None, - revocation_base_secret: None, - payment_base_secret: None, - delayed_payment_base_secret: None, - htlc_base_secret: None, - shachain_seed: None, - } - } - - pub fn get_node_secret_key(&self) -> SecretKey { + pub fn new(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self { + let inner = KeysManager::new(seed, starting_time_secs, starting_time_nanos); + Self { + inner, + funding_key: None, + revocation_base_secret: None, + payment_base_secret: None, + delayed_payment_base_secret: None, + htlc_base_secret: None, + shachain_seed: None, + } + } + + pub fn get_node_secret_key(&self) -> SecretKey { self.inner.get_node_secret_key() } - pub fn set_channel_keys( - &mut self, - funding_key: String, - revocation_base_secret: String, - payment_base_secret: String, - delayed_payment_base_secret: String, - htlc_base_secret: String, - _shachain_seed: String, - ) { - use std::str::FromStr; - - self.funding_key = Some(SecretKey::from_str(&funding_key).unwrap()); - self.revocation_base_secret = Some(SecretKey::from_str(&revocation_base_secret).unwrap()); - self.payment_base_secret = Some(SecretKey::from_str(&payment_base_secret).unwrap()); - self.delayed_payment_base_secret = - Some(SecretKey::from_str(&delayed_payment_base_secret).unwrap()); - self.htlc_base_secret = Some(SecretKey::from_str(&htlc_base_secret).unwrap()); - self.shachain_seed = Some(self.inner.get_secure_random_bytes()) - } + pub fn set_channel_keys( + &mut self, funding_key: String, revocation_base_secret: String, + payment_base_secret: String, delayed_payment_base_secret: String, htlc_base_secret: String, + _shachain_seed: String, + ) { + use std::str::FromStr; + + self.funding_key = Some(SecretKey::from_str(&funding_key).unwrap()); + self.revocation_base_secret = Some(SecretKey::from_str(&revocation_base_secret).unwrap()); + self.payment_base_secret = Some(SecretKey::from_str(&payment_base_secret).unwrap()); + self.delayed_payment_base_secret = + Some(SecretKey::from_str(&delayed_payment_base_secret).unwrap()); + self.htlc_base_secret = Some(SecretKey::from_str(&htlc_base_secret).unwrap()); + self.shachain_seed = Some(self.inner.get_secure_random_bytes()) + } } impl EntropySource for MyKeysManager { - fn get_secure_random_bytes(&self) -> [u8; 32] { - self.inner.get_secure_random_bytes() - } + fn get_secure_random_bytes(&self) -> [u8; 32] { + self.inner.get_secure_random_bytes() + } } impl NodeSigner for MyKeysManager { - fn ecdh( - &self, - recipient: lightning::sign::Recipient, - other_key: &bitcoin::secp256k1::PublicKey, - tweak: Option<&bitcoin::secp256k1::Scalar>, - ) -> Result { - self.inner.ecdh(recipient, other_key, tweak) - } - - fn get_inbound_payment_key_material(&self) -> lightning::sign::KeyMaterial { - self.inner.get_inbound_payment_key_material() - } - - fn get_node_id( - &self, - recipient: lightning::sign::Recipient, - ) -> Result { - self.inner.get_node_id(recipient) - } - - fn sign_bolt12_invoice( - &self, - invoice: &lightning::offers::invoice::UnsignedBolt12Invoice, - ) -> Result { - self.inner.sign_bolt12_invoice(invoice) - } - - fn sign_bolt12_invoice_request( - &self, - invoice_request: &lightning::offers::invoice_request::UnsignedInvoiceRequest, - ) -> Result { - self.inner.sign_bolt12_invoice_request(invoice_request) - } - - fn sign_gossip_message( - &self, - msg: lightning::ln::msgs::UnsignedGossipMessage, - ) -> Result { - self.inner.sign_gossip_message(msg) - } - - fn sign_invoice( - &self, - invoice: &RawBolt11Invoice, - recipient: lightning::sign::Recipient, - ) -> Result { - self.inner.sign_invoice(invoice, recipient) - } -} + fn ecdh( + &self, recipient: lightning::sign::Recipient, other_key: &bitcoin::secp256k1::PublicKey, + tweak: Option<&bitcoin::secp256k1::Scalar>, + ) -> Result { + self.inner.ecdh(recipient, other_key, tweak) + } + + fn get_inbound_payment_key_material(&self) -> lightning::sign::KeyMaterial { + self.inner.get_inbound_payment_key_material() + } + fn get_node_id( + &self, recipient: lightning::sign::Recipient, + ) -> Result { + self.inner.get_node_id(recipient) + } + + fn sign_bolt12_invoice( + &self, invoice: &lightning::offers::invoice::UnsignedBolt12Invoice, + ) -> Result { + self.inner.sign_bolt12_invoice(invoice) + } + + fn sign_bolt12_invoice_request( + &self, invoice_request: &lightning::offers::invoice_request::UnsignedInvoiceRequest, + ) -> Result { + self.inner.sign_bolt12_invoice_request(invoice_request) + } + + fn sign_gossip_message( + &self, msg: lightning::ln::msgs::UnsignedGossipMessage, + ) -> Result { + self.inner.sign_gossip_message(msg) + } + + fn sign_invoice( + &self, invoice: &RawBolt11Invoice, recipient: lightning::sign::Recipient, + ) -> Result { + self.inner.sign_invoice(invoice, recipient) + } +} impl OutputSpender for MyKeysManager { - fn spend_spendable_outputs( - &self, - descriptors: &[&lightning::sign::SpendableOutputDescriptor], - outputs: Vec, - change_destination_script: bitcoin::ScriptBuf, - feerate_sat_per_1000_weight: u32, - locktime: Option, - secp_ctx: &bitcoin::secp256k1::Secp256k1, - ) -> Result { - self.inner.spend_spendable_outputs( - descriptors, - outputs, - change_destination_script, - feerate_sat_per_1000_weight, - locktime, - secp_ctx, - ) - } + fn spend_spendable_outputs( + &self, descriptors: &[&lightning::sign::SpendableOutputDescriptor], + outputs: Vec, change_destination_script: bitcoin::ScriptBuf, + feerate_sat_per_1000_weight: u32, locktime: Option, + secp_ctx: &bitcoin::secp256k1::Secp256k1, + ) -> Result { + self.inner.spend_spendable_outputs( + descriptors, + outputs, + change_destination_script, + feerate_sat_per_1000_weight, + locktime, + secp_ctx, + ) + } } impl SignerProvider for MyKeysManager { - type EcdsaSigner = InMemorySigner; - - fn derive_channel_signer( - &self, - channel_value_satoshis: u64, - channel_keys_id: [u8; 32], - ) -> Self::EcdsaSigner { - if self.funding_key.is_some() { - let commitment_seed = [ - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - ]; - return InMemorySigner::new( - &Secp256k1::new(), - self.funding_key.unwrap(), - self.revocation_base_secret.unwrap(), - self.payment_base_secret.unwrap(), - self.delayed_payment_base_secret.unwrap(), - self.htlc_base_secret.unwrap(), - commitment_seed, - channel_value_satoshis, - channel_keys_id, - self.shachain_seed.unwrap(), - ); - } - self.inner - .derive_channel_signer(channel_value_satoshis, channel_keys_id) - } - - fn generate_channel_keys_id( - &self, - inbound: bool, - channel_value_satoshis: u64, - user_channel_id: u128, - ) -> [u8; 32] { - self.inner - .generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id) - } - - fn get_destination_script(&self, channel_keys_id: [u8; 32]) -> Result { - self.inner.get_destination_script(channel_keys_id) - } - - fn get_shutdown_scriptpubkey(&self) -> Result { - self.inner.get_shutdown_scriptpubkey() - } - - fn read_chan_signer( - &self, - reader: &[u8], - ) -> Result { - self.inner.read_chan_signer(reader) - } + type EcdsaSigner = InMemorySigner; + + fn derive_channel_signer( + &self, channel_value_satoshis: u64, channel_keys_id: [u8; 32], + ) -> Self::EcdsaSigner { + if self.funding_key.is_some() { + let commitment_seed = [ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + ]; + return InMemorySigner::new( + &Secp256k1::new(), + self.funding_key.unwrap(), + self.revocation_base_secret.unwrap(), + self.payment_base_secret.unwrap(), + self.delayed_payment_base_secret.unwrap(), + self.htlc_base_secret.unwrap(), + commitment_seed, + channel_value_satoshis, + channel_keys_id, + self.shachain_seed.unwrap(), + ); + } + self.inner.derive_channel_signer(channel_value_satoshis, channel_keys_id) + } + + fn generate_channel_keys_id( + &self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128, + ) -> [u8; 32] { + self.inner.generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id) + } + + fn get_destination_script(&self, channel_keys_id: [u8; 32]) -> Result { + self.inner.get_destination_script(channel_keys_id) + } + + fn get_shutdown_scriptpubkey(&self) -> Result { + self.inner.get_shutdown_scriptpubkey() + } + + fn read_chan_signer( + &self, reader: &[u8], + ) -> Result { + self.inner.read_chan_signer(reader) + } } diff --git a/src/main.rs b/src/main.rs index ae489781..e98bc4d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,13 +4,13 @@ mod cli; mod convert; mod disk; mod hex_utils; -mod sweep; mod keys; +mod sweep; use crate::bitcoind_client::BitcoindClient; use crate::disk::FilesystemLogger; -use crate::keys::MyKeysManager; use crate::keys::MyKeys; +use crate::keys::MyKeysManager; use bitcoin::blockdata::transaction::Transaction; use bitcoin::consensus::encode; use bitcoin::io; @@ -23,9 +23,7 @@ use lightning::chain::{BestBlock, Filter, Watch}; use lightning::events::bump_transaction::{BumpTransactionEventHandler, Wallet}; use lightning::events::{Event, PaymentFailureReason, PaymentPurpose}; use lightning::ln::channelmanager::{self, RecentPaymentDetails}; -use lightning::ln::channelmanager::{ - ChainParameters, ChannelManagerReadArgs, PaymentId -}; +use lightning::ln::channelmanager::{ChainParameters, ChannelManagerReadArgs, PaymentId}; use lightning::ln::msgs::DecodeError; use lightning::ln::peer_handler; use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler}; @@ -166,7 +164,7 @@ pub type SimpleArcPeerManager = peer_handler::PeerManager< Arc>, Arc, IgnoringMessageHandler, - Arc + Arc, >; pub(crate) type PeerManager = SimpleArcPeerManager< @@ -185,15 +183,17 @@ pub type SimpleArcChannelManager = channelmanager::ChannelManager< Arc, Arc, Arc, - Arc>>, - Arc, - Arc, - Arc>>, Arc>>>, - ProbabilisticScoringFeeParameters, - ProbabilisticScorer>>, Arc>, - >>, - Arc + Arc< + DefaultRouter< + Arc>>, + Arc, + Arc, + Arc>>, Arc>>>, + ProbabilisticScoringFeeParameters, + ProbabilisticScorer>>, Arc>, + >, + >, + Arc, >; pub(crate) type ChannelManager = @@ -209,7 +209,7 @@ pub type SimpleArcOnionMessenger = messenger::OnionMessenger< Arc>>, Arc, Arc>>, Arc>, Arc>, - IgnoringMessageHandler + IgnoringMessageHandler, >; type OnionMessenger = @@ -679,13 +679,15 @@ async fn start_ldk() { let cur = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(); let keys_manager = match args.channel_secrets { - Some(ref secrets) => { - MyKeys::with_channel_keys(keys_seed, cur.as_secs(), cur.subsec_nanos(), secrets.to_string()).inner() - } - None => { - MyKeys::new(keys_seed, cur.as_secs(), cur.subsec_nanos()).inner() - } - }; + Some(ref secrets) => MyKeys::with_channel_keys( + keys_seed, + cur.as_secs(), + cur.subsec_nanos(), + secrets.to_string(), + ) + .inner(), + None => MyKeys::new(keys_seed, cur.as_secs(), cur.subsec_nanos()).inner(), + }; let bump_tx_event_handler = Arc::new(BumpTransactionEventHandler::new( Arc::clone(&broadcaster), Arc::new(Wallet::new(Arc::clone(&bitcoind_client), Arc::clone(&logger))),