# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-lightning = { version = "0.0.123", features = ["max_level_trace"] }
-lightning-block-sync = { version = "0.0.123", features = [ "rpc-client", "tokio" ] }
-lightning-invoice = { version = "0.31.0" }
-lightning-net-tokio = { version = "0.0.123" }
-lightning-persister = { version = "0.0.123" }
-lightning-background-processor = { version = "0.0.123", features = [ "futures" ] }
-lightning-rapid-gossip-sync = { version = "0.0.123" }
+lightning = { version = "0.0.125", features = ["max_level_trace"] }
+lightning-block-sync = { version = "0.0.125", features = [ "rpc-client", "tokio" ] }
+lightning-invoice = { version = "0.32.0" }
+lightning-net-tokio = { version = "0.0.125" }
+lightning-persister = { version = "0.0.125" }
+lightning-background-processor = { version = "0.0.125", features = [ "futures" ] }
+lightning-rapid-gossip-sync = { version = "0.0.125" }
base64 = "0.13.0"
-bitcoin = "0.30.2"
+bitcoin = "0.32"
bitcoin-bech32 = "0.12"
bech32 = "0.8"
libc = "0.2"
use crate::cli::LdkUserInfo;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
use lightning::ln::msgs::SocketAddress;
use std::collections::HashMap;
use std::env;
use crate::disk::FilesystemLogger;
use crate::hex_utils;
use base64;
-use bitcoin::address::{Address, Payload, WitnessVersion};
+use bitcoin::address::Address;
use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
use bitcoin::blockdata::script::ScriptBuf;
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::hash_types::{BlockHash, Txid};
use bitcoin::hashes::Hash;
use bitcoin::key::XOnlyPublicKey;
-use bitcoin::psbt::PartiallySignedTransaction;
+use bitcoin::psbt::Psbt;
use bitcoin::{Network, OutPoint, TxOut, WPubkeyHash};
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
use lightning::events::bump_transaction::{Utxo, WalletSource};
"Failed to make initial call to bitcoind - please check your RPC user/password and access settings")
})?;
let mut fees: HashMap<ConfirmationTarget, AtomicU32> = HashMap::new();
- fees.insert(ConfirmationTarget::OnChainSweep, AtomicU32::new(5000));
+ fees.insert(ConfirmationTarget::MaximumFeeEstimate, AtomicU32::new(50000));
+ fees.insert(ConfirmationTarget::UrgentOnChainSweep, AtomicU32::new(5000));
fees.insert(
ConfirmationTarget::MinAllowedAnchorChannelRemoteFee,
AtomicU32::new(MIN_FEERATE),
fees.insert(ConfirmationTarget::AnchorChannelFee, AtomicU32::new(MIN_FEERATE));
fees.insert(ConfirmationTarget::NonAnchorChannelFee, AtomicU32::new(2000));
fees.insert(ConfirmationTarget::ChannelCloseMinimum, AtomicU32::new(MIN_FEERATE));
+ fees.insert(ConfirmationTarget::OutputSpendingFee, AtomicU32::new(MIN_FEERATE));
let client = Self {
bitcoind_rpc_client: Arc::new(bitcoind_rpc_client),
}
};
- fees.get(&ConfirmationTarget::OnChainSweep)
+ let very_high_prio_estimate = {
+ let high_prio_conf_target = serde_json::json!(2);
+ let high_prio_estimate_mode = serde_json::json!("CONSERVATIVE");
+ let resp = rpc_client
+ .call_method::<FeeResponse>(
+ "estimatesmartfee",
+ &vec![high_prio_conf_target, high_prio_estimate_mode],
+ )
+ .await
+ .unwrap();
+
+ match resp.feerate_sat_per_kw {
+ Some(feerate) => std::cmp::max(feerate, MIN_FEERATE),
+ None => 50000,
+ }
+ };
+
+ fees.get(&ConfirmationTarget::MaximumFeeEstimate)
+ .unwrap()
+ .store(very_high_prio_estimate, Ordering::Release);
+ fees.get(&ConfirmationTarget::UrgentOnChainSweep)
.unwrap()
.store(high_prio_estimate, Ordering::Release);
fees.get(&ConfirmationTarget::MinAllowedAnchorChannelRemoteFee)
fees.get(&ConfirmationTarget::ChannelCloseMinimum)
.unwrap()
.store(background_estimate, Ordering::Release);
+ fees.get(&ConfirmationTarget::OutputSpendingFee)
+ .unwrap()
+ .store(background_estimate, Ordering::Release);
tokio::time::sleep(Duration::from_secs(60)).await;
}
.into_iter()
.filter_map(|utxo| {
let outpoint = OutPoint { txid: utxo.txid, vout: utxo.vout };
- match utxo.address.payload.clone() {
- Payload::WitnessProgram(wp) => match wp.version() {
- WitnessVersion::V0 => WPubkeyHash::from_slice(wp.program().as_bytes())
- .map(|wpkh| Utxo::new_v0_p2wpkh(outpoint, utxo.amount, &wpkh))
- .ok(),
+ let value = bitcoin::Amount::from_sat(utxo.amount);
+ match utxo.address.witness_program() {
+ Some(prog) if prog.is_p2wpkh() => {
+ WPubkeyHash::from_slice(prog.program().as_bytes())
+ .map(|wpkh| Utxo::new_v0_p2wpkh(outpoint, value, &wpkh))
+ .ok()
+ },
+ Some(prog) if prog.is_p2tr() => {
// TODO: Add `Utxo::new_v1_p2tr` upstream.
- WitnessVersion::V1 => XOnlyPublicKey::from_slice(wp.program().as_bytes())
+ XOnlyPublicKey::from_slice(prog.program().as_bytes())
.map(|_| Utxo {
outpoint,
output: TxOut {
- value: utxo.amount,
- script_pubkey: ScriptBuf::new_witness_program(&wp),
+ value,
+ script_pubkey: utxo.address.script_pubkey(),
},
satisfaction_weight: 1 /* empty script_sig */ * WITNESS_SCALE_FACTOR as u64 +
1 /* witness items */ + 1 /* schnorr sig len */ + 64, /* schnorr sig */
})
- .ok(),
- _ => None,
+ .ok()
},
_ => None,
}
})
}
- fn sign_psbt(&self, tx: PartiallySignedTransaction) -> Result<Transaction, ()> {
+ fn sign_psbt(&self, tx: Psbt) -> Result<Transaction, ()> {
let mut tx_bytes = Vec::new();
let _ = tx.unsigned_tx.consensus_encode(&mut tx_bytes).map_err(|_| ());
let tx_hex = hex_utils::hex_str(&tx_bytes);
use crate::hex_utils;
use crate::{
ChannelManager, HTLCStatus, InboundPaymentInfoStorage, MillisatAmount, NetworkGraph,
- OnionMessenger, OutboundPaymentInfoStorage, PaymentInfo, PeerManager,
+ OutboundPaymentInfoStorage, PaymentInfo, PeerManager,
};
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::Hash;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
use bitcoin::secp256k1::PublicKey;
+use lightning::ln::bolt11_payment::payment_parameters_from_invoice;
+use lightning::ln::bolt11_payment::payment_parameters_from_zero_amount_invoice;
use lightning::ln::channelmanager::{PaymentId, RecipientOnionFields, Retry};
+use lightning::ln::invoice_utils as utils;
use lightning::ln::msgs::SocketAddress;
-use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage};
+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::types::payment::{PaymentHash, PaymentPreimage};
use lightning::util::config::{ChannelHandshakeConfig, ChannelHandshakeLimits, UserConfig};
use lightning::util::persist::KVStore;
-use lightning::util::ser::{Writeable, Writer};
-use lightning_invoice::payment::payment_parameters_from_invoice;
-use lightning_invoice::payment::payment_parameters_from_zero_amount_invoice;
-use lightning_invoice::{utils, Bolt11Invoice, Currency};
+use lightning::util::ser::Writeable;
+use lightning_invoice::{Bolt11Invoice, Currency};
use lightning_persister::fs_store::FilesystemStore;
use std::env;
-use std::io;
use std::io::Write;
use std::net::{SocketAddr, ToSocketAddrs};
use std::path::Path;
pub(crate) fn poll_for_user_input(
peer_manager: Arc<PeerManager>, channel_manager: Arc<ChannelManager>,
keys_manager: Arc<KeysManager>, network_graph: Arc<NetworkGraph>,
- onion_messenger: Arc<OnionMessenger>, inbound_payments: Arc<Mutex<InboundPaymentInfoStorage>>,
+ inbound_payments: Arc<Mutex<InboundPaymentInfoStorage>>,
outbound_payments: Arc<Mutex<OutboundPaymentInfoStorage>>, ldk_data_dir: String,
network: Network, logger: Arc<disk::FilesystemLogger>, fs_store: Arc<FilesystemStore>,
) {
println!("Local Node ID is {}.", channel_manager.get_our_node_id());
'read_command: loop {
print!("> ");
- io::stdout().flush().unwrap(); // Without flushing, the `>` doesn't print
+ std::io::stdout().flush().unwrap(); // Without flushing, the `>` doesn't print
let mut line = String::new();
- if let Err(e) = io::stdin().read_line(&mut line) {
+ if let Err(e) = std::io::stdin().read_line(&mut line) {
break println!("ERROR: {}", e);
}
let payment_id = PaymentId(random_bytes);
let amt_msat = match (offer.amount(), user_provided_amt) {
- (Some(offer::Amount::Bitcoin { amount_msats }), _) => *amount_msats,
+ (Some(offer::Amount::Bitcoin { amount_msats }), _) => amount_msats,
(_, Some(amt)) => amt,
(amt, _) => {
println!("ERROR: Cannot process non-Bitcoin-denominated offer value {:?}", amt);
while user_provided_amt.is_none() {
print!("Paying offer for {} msat. Continue (Y/N)? >", amt_msat);
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
- if let Err(e) = io::stdin().read_line(&mut line) {
+ if let Err(e) = std::io::stdin().read_line(&mut line) {
println!("ERROR: {}", e);
break 'read_command;
}
);
},
"getoffer" => {
- let offer_builder = channel_manager.create_offer_builder();
+ let offer_builder = channel_manager.create_offer_builder(None);
if let Err(e) = offer_builder {
println!("ERROR: Failed to initiate offer building: {:?}", e);
continue;
.get(&NodeId::from_pubkey(&chan_info.counterparty.node_id))
{
if let Some(announcement) = &node_info.announcement_info {
- println!("\t\tpeer_alias: {}", announcement.alias);
+ println!("\t\tpeer_alias: {}", announcement.alias());
}
}
println!("\t\tavailable_balance_for_recv_msat: {},", chan_info.inbound_capacity_msat);
}
println!("\t\tchannel_can_send_payments: {},", chan_info.is_usable);
- println!("\t\tpublic: {},", chan_info.is_public);
+ println!("\t\tpublic: {},", chan_info.is_announced);
println!("\t}},");
}
println!("]");
}
fn open_channel(
- peer_pubkey: PublicKey, channel_amt_sat: u64, announced_channel: bool, with_anchors: bool,
- channel_manager: Arc<ChannelManager>,
+ peer_pubkey: PublicKey, channel_amt_sat: u64, announce_for_forwarding: bool,
+ with_anchors: bool, channel_manager: Arc<ChannelManager>,
) -> Result<(), ()> {
let config = UserConfig {
channel_handshake_limits: ChannelHandshakeLimits {
..Default::default()
},
channel_handshake_config: ChannelHandshakeConfig {
- announced_channel,
+ announce_for_forwarding,
negotiate_anchors_zero_fee_htlc_tx: with_anchors,
..Default::default()
},
fn force_close_channel(
channel_id: [u8; 32], counterparty_node_id: PublicKey, channel_manager: Arc<ChannelManager>,
) {
- match channel_manager
- .force_close_broadcasting_latest_txn(&ChannelId(channel_id), &counterparty_node_id)
- {
+ match channel_manager.force_close_broadcasting_latest_txn(
+ &ChannelId(channel_id),
+ &counterparty_node_id,
+ "Manually force-closed".to_string(),
+ ) {
Ok(()) => println!("EVENT: initiating channel force-close"),
Err(e) => println!("ERROR: failed to force-close channel: {:?}", e),
}
use chrono::Utc;
use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringDecayParameters};
use lightning::util::logger::{Logger, Record};
-use lightning::util::ser::{Readable, ReadableArgs, Writer};
+use lightning::util::ser::{Readable, ReadableArgs};
use std::collections::HashMap;
use std::fs;
use std::fs::File;
-use std::io::{BufRead, BufReader};
+use std::io::{BufRead, BufReader, Write};
use std::net::SocketAddr;
use std::path::Path;
use std::sync::Arc;
use crate::disk::FilesystemLogger;
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::consensus::encode;
-use bitcoin::network::constants::Network;
+use bitcoin::io;
+use bitcoin::network::Network;
use bitcoin::BlockHash;
use bitcoin_bech32::WitnessProgram;
use disk::{INBOUND_PAYMENTS_FNAME, OUTBOUND_PAYMENTS_FNAME};
};
use lightning::ln::msgs::DecodeError;
use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler, SimpleArcPeerManager};
-use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
+use lightning::ln::types::ChannelId;
use lightning::onion_message::messenger::{DefaultMessageRouter, SimpleArcOnionMessenger};
use lightning::routing::gossip;
use lightning::routing::gossip::{NodeId, P2PGossipSync};
use lightning::routing::router::DefaultRouter;
use lightning::routing::scoring::ProbabilisticScoringFeeParameters;
use lightning::sign::{EntropySource, InMemorySigner, KeysManager};
+use lightning::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
use lightning::util::config::UserConfig;
use lightning::util::persist::{
self, KVStore, MonitorUpdatingPersister, OUTPUT_SWEEPER_PERSISTENCE_KEY,
use std::fmt;
use std::fs;
use std::fs::File;
-use std::io;
-use std::io::Write;
+use std::io::{BufReader, Write};
use std::net::ToSocketAddrs;
use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering};
impl_writeable_tlv_based_enum!(HTLCStatus,
(0, Pending) => {},
(1, Succeeded) => {},
- (2, Failed) => {};
+ (2, Failed) => {},
);
pub(crate) struct MillisatAmount(Option<u64>);
}
impl Writeable for MillisatAmount {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
self.0.write(w)
}
}
Arc<FilesystemLogger>,
Arc<KeysManager>,
Arc<KeysManager>,
+ Arc<BitcoindClient>,
+ Arc<BitcoindClient>,
>,
>,
>;
encode::deserialize(&hex_utils::to_vec(&signed_tx.hex).unwrap()).unwrap();
// Give the funding transaction back to LDK for opening the channel.
if channel_manager
- .funding_transaction_generated(
- &temporary_channel_id,
- &counterparty_node_id,
- final_tx,
- )
+ .funding_transaction_generated(temporary_channel_id, counterparty_node_id, final_tx)
.is_err()
{
println!(
"\nERROR: Channel went away before we could fund it. The peer disconnected or refused the channel.");
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
}
},
+ Event::FundingTxBroadcastSafe { .. } => {
+ // We don't use the manual broadcasting feature, so this event should never be seen.
+ },
Event::PaymentClaimable {
payment_hash,
purpose,
payment_hash, amount_msat,
);
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
let payment_preimage = match purpose {
PaymentPurpose::Bolt11InvoicePayment { payment_preimage, .. } => payment_preimage,
PaymentPurpose::Bolt12OfferPayment { payment_preimage, .. } => payment_preimage,
};
channel_manager.claim_funds(payment_preimage.unwrap());
},
- Event::PaymentClaimed {
- payment_hash,
- purpose,
- amount_msat,
- receiver_node_id: _,
- htlcs: _,
- sender_intended_total_msat: _,
- } => {
+ Event::PaymentClaimed { payment_hash, purpose, amount_msat, .. } => {
println!(
"\nEVENT: claimed payment from payment hash {} of {} millisatoshis",
payment_hash, amount_msat,
);
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
let (payment_preimage, payment_secret) = match purpose {
PaymentPurpose::Bolt11InvoicePayment {
payment_preimage, payment_secret, ..
payment_preimage
);
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
}
}
fs_store.write("", "", OUTBOUND_PAYMENTS_FNAME, &outbound.encode()).unwrap();
);
}
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
},
Event::PaymentPathSuccessful { .. } => {},
Event::PaymentPathFailed { .. } => {},
Event::ProbeSuccessful { .. } => {},
Event::ProbeFailed { .. } => {},
Event::PaymentFailed { payment_hash, reason, payment_id, .. } => {
- print!(
- "\nEVENT: Failed to send payment to payment hash {}: {:?}",
- payment_hash,
- if let Some(r) = reason { r } else { PaymentFailureReason::RetriesExhausted }
- );
- print!("> ");
- io::stdout().flush().unwrap();
-
- let mut outbound = outbound_payments.lock().unwrap();
- if outbound.payments.contains_key(&payment_id) {
- let payment = outbound.payments.get_mut(&payment_id).unwrap();
- payment.status = HTLCStatus::Failed;
+ if let Some(hash) = payment_hash {
+ print!(
+ "\nEVENT: Failed to send payment to payment ID {}, payment hash {}: {:?}",
+ payment_id,
+ hash,
+ if let Some(r) = reason { r } else { PaymentFailureReason::RetriesExhausted }
+ );
+ } else {
+ print!(
+ "\nEVENT: Failed fetch invoice for payment ID {}: {:?}",
+ payment_id,
+ if let Some(r) = reason { r } else { PaymentFailureReason::RetriesExhausted }
+ );
}
- fs_store.write("", "", OUTBOUND_PAYMENTS_FNAME, &outbound.encode()).unwrap();
- },
- Event::InvoiceRequestFailed { payment_id } => {
- print!("\nEVENT: Failed to request invoice to send payment with id {}", payment_id);
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
let mut outbound = outbound_payments.lock().unwrap();
if outbound.payments.contains_key(&payment_id) {
}
fs_store.write("", "", OUTBOUND_PAYMENTS_FNAME, &outbound.encode()).unwrap();
},
+ Event::InvoiceReceived { .. } => {
+ // We don't use the manual invoice payment logic, so this event should never be seen.
+ },
Event::PaymentForwarded {
prev_channel_id,
next_channel_id,
Some(node) => match &node.announcement_info {
None => "unnamed node".to_string(),
Some(announcement) => {
- format!("node {}", announcement.alias)
+ format!("node {}", announcement.alias())
},
},
}
);
}
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
},
Event::HTLCHandlingFailed { .. } => {},
Event::PendingHTLCsForwardable { time_forwardable } => {
hex_utils::hex_str(&counterparty_node_id.serialize()),
);
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
},
Event::ChannelReady {
ref channel_id,
hex_utils::hex_str(&counterparty_node_id.serialize()),
);
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
},
Event::ChannelClosed {
channel_id,
reason
);
print!("> ");
- io::stdout().flush().unwrap();
+ std::io::stdout().flush().unwrap();
},
Event::DiscardFunding { .. } => {
// A "real" node should probably "lock" the UTXOs spent in funding transactions until
// the funding transaction either confirms, or this event is generated.
},
Event::HTLCIntercepted { .. } => {},
+ Event::OnionMessageIntercepted { .. } => {
+ // We don't use the onion message interception feature, so this event should never be
+ // seen.
+ },
+ Event::OnionMessagePeerConnected { .. } => {
+ // We don't use the onion message interception feature, so we have no use for this
+ // event.
+ },
Event::BumpTransaction(event) => bump_tx_event_handler.handle_event(&event),
Event::ConnectionNeeded { node_id, addresses } => {
tokio::spawn(async move {
thread_rng().fill_bytes(&mut key);
match File::create(keys_seed_path.clone()) {
Ok(mut f) => {
- Write::write_all(&mut f, &key).expect("Failed to write node keys seed to disk");
+ std::io::Write::write_all(&mut f, &key)
+ .expect("Failed to write node keys seed to disk");
f.sync_all().expect("Failed to sync node keys seed to disk");
},
Err(e) => {
1000,
Arc::clone(&keys_manager),
Arc::clone(&keys_manager),
+ Arc::clone(&bitcoind_client),
+ Arc::clone(&bitcoind_client),
));
// Alternatively, you can use the `FilesystemStore` as a `Persist` directly, at the cost of
// larger `ChannelMonitor` update writes (but no deletion or cleanup):
));
// Step 7: Read ChannelMonitor state from disk
- let mut channelmonitors = persister
- .read_all_channel_monitors_with_updates(&bitcoind_client, &bitcoind_client)
- .unwrap();
+ let mut channelmonitors = persister.read_all_channel_monitors_with_updates().unwrap();
// If you are using the `FilesystemStore` as a `Persist` directly, use
// `lightning::util::persist::read_channel_monitors` like this:
//read_channel_monitors(Arc::clone(&persister), Arc::clone(&keys_manager), Arc::clone(&keys_manager)).unwrap();
user_config.manually_accept_inbound_channels = true;
let mut restarting_node = true;
let (channel_manager_blockhash, channel_manager) = {
- if let Ok(mut f) = fs::File::open(format!("{}/manager", ldk_data_dir.clone())) {
+ if let Ok(f) = fs::File::open(format!("{}/manager", ldk_data_dir.clone())) {
let mut channel_monitor_mut_references = Vec::new();
for (_, channel_monitor) in channelmonitors.iter_mut() {
channel_monitor_mut_references.push(channel_monitor);
user_config,
channel_monitor_mut_references,
);
- <(BlockHash, ChannelManager)>::read(&mut f, read_args).unwrap()
+ <(BlockHash, ChannelManager)>::read(&mut BufReader::new(f), read_args).unwrap()
} else {
// We're starting a fresh node.
restarting_node = false;
Arc::clone(&channel_manager),
Arc::new(DefaultMessageRouter::new(Arc::clone(&network_graph), Arc::clone(&keys_manager))),
Arc::clone(&channel_manager),
+ Arc::clone(&channel_manager),
IgnoringMessageHandler {},
));
let mut ephemeral_bytes = [0; 32];
event,
)
.await;
+ Ok(())
}
};
event_handler,
chain_monitor.clone(),
channel_manager.clone(),
+ Some(onion_messenger),
GossipSync::p2p(gossip_sync.clone()),
peer_manager.clone(),
logger.clone(),
// Don't bother trying to announce if we don't have any public channls, though our
// peers should drop such an announcement anyway. Note that announcement may not
// propagate until we have a channel with 6+ confirmations.
- if chan_man.list_channels().iter().any(|chan| chan.is_public) {
+ if chan_man.list_channels().iter().any(|chan| chan.is_announced) {
peer_man.broadcast_node_announcement(
[0; 3],
args.ldk_announced_node_name,
cli_channel_manager,
keys_manager,
network_graph,
- onion_messenger,
inbound_payments,
outbound_payments,
ldk_data_dir,
-use std::io::{Read, Seek, SeekFrom};
+use std::io::{BufReader, Read, Seek, SeekFrom};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{fs, io};
let mut outputs: Vec<SpendableOutputDescriptor> = Vec::new();
if let Ok(dir_iter) = fs::read_dir(&spendables_dir) {
for file_res in dir_iter {
- let mut file = fs::File::open(file_res.unwrap().path()).unwrap();
+ let file = fs::File::open(file_res.unwrap().path()).unwrap();
+ let mut reader = BufReader::new(file);
loop {
// Check if there are any bytes left to read, and if so read a descriptor.
- match file.read_exact(&mut [0; 1]) {
+ match reader.read_exact(&mut [0; 1]) {
Ok(_) => {
- file.seek(SeekFrom::Current(-1)).unwrap();
+ reader.seek(SeekFrom::Current(-1)).unwrap();
},
Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => break,
Err(e) => Err(e).unwrap(),
}
- outputs.push(Readable::read(&mut file).unwrap());
+ outputs.push(Readable::read(&mut reader).unwrap());
}
}
}