Skip to content

Commit

Permalink
persist payments info to disk
Browse files Browse the repository at this point in the history
  • Loading branch information
zoedberg committed May 11, 2023
1 parent 7aceee9 commit b88e454
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 48 deletions.
52 changes: 28 additions & 24 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ use std::env;
use std::io;
use std::io::Write;
use std::net::{SocketAddr, ToSocketAddrs};
use std::ops::Deref;
use std::path::Path;
use std::str::FromStr;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::time::Duration;

pub(crate) struct LdkUserInfo {
Expand Down Expand Up @@ -61,8 +60,8 @@ impl Writeable for UserOnionMessageContents {
pub(crate) async 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: PaymentInfoStorage,
outbound_payments: PaymentInfoStorage, ldk_data_dir: String, network: Network,
onion_messenger: Arc<OnionMessenger>, inbound_payments: Arc<Mutex<PaymentInfoStorage>>,
outbound_payments: Arc<Mutex<PaymentInfoStorage>>, ldk_data_dir: String, network: Network,
logger: Arc<disk::FilesystemLogger>,
) {
println!(
Expand Down Expand Up @@ -157,7 +156,10 @@ pub(crate) async fn poll_for_user_input(
}
};

send_payment(&*channel_manager, &invoice, outbound_payments.clone());
let mut outbound_payments = outbound_payments.lock().unwrap();
send_payment(&*channel_manager, &invoice, &mut outbound_payments);
disk::persist_outbound_payments(ldk_data_dir.clone(), &outbound_payments)
.unwrap();
}
"keysend" => {
let dest_pubkey = match words.next() {
Expand Down Expand Up @@ -187,13 +189,16 @@ pub(crate) async fn poll_for_user_input(
continue;
}
};
let mut outbound_payments = outbound_payments.lock().unwrap();
keysend(
&*channel_manager,
dest_pubkey,
amt_msat,
&*keys_manager,
outbound_payments.clone(),
&mut outbound_payments,
);
disk::persist_outbound_payments(ldk_data_dir.clone(), &outbound_payments)
.unwrap();
}
"getinvoice" => {
let amt_str = words.next();
Expand All @@ -220,15 +225,18 @@ pub(crate) async fn poll_for_user_input(
continue;
}

let mut inbound_payments = inbound_payments.lock().unwrap();
get_invoice(
amt_msat.unwrap(),
Arc::clone(&inbound_payments),
&mut inbound_payments,
&*channel_manager,
Arc::clone(&keys_manager),
network,
expiry_secs.unwrap(),
Arc::clone(&logger),
);
disk::persist_inbound_payments(ldk_data_dir.clone(), &inbound_payments)
.unwrap();
}
"connectpeer" => {
let peer_pubkey_and_ip_addr = words.next();
Expand Down Expand Up @@ -278,9 +286,10 @@ pub(crate) async fn poll_for_user_input(
}
}
"listchannels" => list_channels(&channel_manager, &network_graph),
"listpayments" => {
list_payments(inbound_payments.clone(), outbound_payments.clone())
}
"listpayments" => list_payments(
&inbound_payments.lock().unwrap(),
&outbound_payments.lock().unwrap(),
),
"closechannel" => {
let channel_id_str = words.next();
if channel_id_str.is_none() {
Expand Down Expand Up @@ -527,11 +536,9 @@ fn list_channels(channel_manager: &Arc<ChannelManager>, network_graph: &Arc<Netw
println!("]");
}

fn list_payments(inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage) {
let inbound = inbound_payments.lock().unwrap();
let outbound = outbound_payments.lock().unwrap();
fn list_payments(inbound_payments: &PaymentInfoStorage, outbound_payments: &PaymentInfoStorage) {
print!("[");
for (payment_hash, payment_info) in inbound.deref() {
for (payment_hash, payment_info) in &inbound_payments.payments {
println!("");
println!("\t{{");
println!("\t\tamount_millisatoshis: {},", payment_info.amt_msat);
Expand All @@ -549,7 +556,7 @@ fn list_payments(inbound_payments: PaymentInfoStorage, outbound_payments: Paymen
println!("\t}},");
}

for (payment_hash, payment_info) in outbound.deref() {
for (payment_hash, payment_info) in &outbound_payments.payments {
println!("");
println!("\t{{");
println!("\t\tamount_millisatoshis: {},", payment_info.amt_msat);
Expand Down Expand Up @@ -658,7 +665,7 @@ fn open_channel(
}

fn send_payment(
channel_manager: &ChannelManager, invoice: &Invoice, payment_storage: PaymentInfoStorage,
channel_manager: &ChannelManager, invoice: &Invoice, outbound_payments: &mut PaymentInfoStorage,
) {
let status =
match pay_invoice(invoice, Retry::Timeout(Duration::from_secs(10)), channel_manager) {
Expand All @@ -678,8 +685,7 @@ fn send_payment(
let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
let payment_secret = Some(invoice.payment_secret().clone());

let mut payments = payment_storage.lock().unwrap();
payments.insert(
outbound_payments.payments.insert(
payment_hash,
PaymentInfo {
preimage: None,
Expand All @@ -692,7 +698,7 @@ fn send_payment(

fn keysend<E: EntropySource>(
channel_manager: &ChannelManager, payee_pubkey: PublicKey, amt_msat: u64, entropy_source: &E,
payment_storage: PaymentInfoStorage,
outbound_payments: &mut PaymentInfoStorage,
) {
let payment_preimage = PaymentPreimage(entropy_source.get_secure_random_bytes());
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
Expand Down Expand Up @@ -720,8 +726,7 @@ fn keysend<E: EntropySource>(
}
};

let mut payments = payment_storage.lock().unwrap();
payments.insert(
outbound_payments.payments.insert(
payment_hash,
PaymentInfo {
preimage: None,
Expand All @@ -733,11 +738,10 @@ fn keysend<E: EntropySource>(
}

fn get_invoice(
amt_msat: u64, payment_storage: PaymentInfoStorage, channel_manager: &ChannelManager,
amt_msat: u64, inbound_payments: &mut PaymentInfoStorage, channel_manager: &ChannelManager,
keys_manager: Arc<KeysManager>, network: Network, expiry_secs: u32,
logger: Arc<disk::FilesystemLogger>,
) {
let mut payments = payment_storage.lock().unwrap();
let currency = match network {
Network::Bitcoin => Currency::Bitcoin,
Network::Testnet => Currency::BitcoinTestnet,
Expand Down Expand Up @@ -765,7 +769,7 @@ fn get_invoice(
};

let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner());
payments.insert(
inbound_payments.payments.insert(
payment_hash,
PaymentInfo {
preimage: None,
Expand Down
36 changes: 33 additions & 3 deletions src/disk.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::{cli, NetworkGraph};
use crate::{cli, NetworkGraph, PaymentInfoStorage};
use bitcoin::secp256k1::PublicKey;
use bitcoin::Network;
use chrono::Utc;
use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters};
use lightning::util::logger::{Logger, Record};
use lightning::util::ser::{ReadableArgs, Writer};
use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::io::{BufRead, BufReader, BufWriter};
use std::net::SocketAddr;
use std::path::Path;
use std::sync::Arc;
Expand Down Expand Up @@ -52,6 +52,27 @@ pub(crate) fn persist_channel_peer(path: &Path, peer_info: &str) -> std::io::Res
file.write_all(format!("{}\n", peer_info).as_bytes())
}

pub(crate) fn persist_inbound_payments(
ldk_data_dir: String, inbound_payments: &PaymentInfoStorage,
) -> std::io::Result<()> {
persist_payment_info(Path::new(&format!("{}/inbound_payments", ldk_data_dir)), inbound_payments)
}

pub(crate) fn persist_outbound_payments(
ldk_data_dir: String, outbound_payments: &PaymentInfoStorage,
) -> std::io::Result<()> {
persist_payment_info(
Path::new(&format!("{}/outbound_payments", ldk_data_dir)),
outbound_payments,
)
}

fn persist_payment_info(path: &Path, payment_info: &PaymentInfoStorage) -> std::io::Result<()> {
let mut buf = BufWriter::new(fs::File::create(&path)?);
payment_info.write(&mut buf)?;
buf.into_inner()?.sync_all()
}

pub(crate) fn read_channel_peer_data(
path: &Path,
) -> Result<HashMap<PublicKey, SocketAddr>, std::io::Error> {
Expand Down Expand Up @@ -83,6 +104,15 @@ pub(crate) fn read_network(
NetworkGraph::new(network, logger)
}

pub(crate) fn read_payment_info(path: &Path) -> PaymentInfoStorage {
if let Ok(file) = File::open(path) {
if let Ok(info) = PaymentInfoStorage::read(&mut BufReader::new(file)) {
return info;
}
}
PaymentInfoStorage { payments: HashMap::new() }
}

pub(crate) fn read_scorer(
path: &Path, graph: Arc<NetworkGraph>, logger: Arc<FilesystemLogger>,
) -> ProbabilisticScorer<Arc<NetworkGraph>, Arc<FilesystemLogger>> {
Expand Down
Loading

0 comments on commit b88e454

Please sign in to comment.