Skip to content

Prep lightning-persister for export in the C bindings #874

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 33 additions & 34 deletions lightning-persister/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extern crate lightning;
extern crate bitcoin;
extern crate libc;

use bitcoin::{BlockHash, Txid};
use bitcoin::hash_types::{BlockHash, Txid};
use bitcoin::hashes::hex::{FromHex, ToHex};
use crate::util::DiskWriteable;
use lightning::chain;
Expand All @@ -24,12 +24,10 @@ use lightning::chain::transaction::OutPoint;
use lightning::ln::channelmanager::ChannelManager;
use lightning::util::logger::Logger;
use lightning::util::ser::{ReadableArgs, Writeable};
use std::collections::HashMap;
use std::fs;
use std::io::{Cursor, Error};
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::sync::Arc;

/// FilesystemPersister persists channel data on disk, where each channel's
/// data is stored in a file named after its funding outpoint.
Expand All @@ -53,12 +51,13 @@ impl<Signer: Sign> DiskWriteable for ChannelMonitor<Signer> {
}
}

impl<Signer: Sign, M, T, K, F, L> DiskWriteable for ChannelManager<Signer, Arc<M>, Arc<T>, Arc<K>, Arc<F>, Arc<L>>
where M: chain::Watch<Signer>,
T: BroadcasterInterface,
K: KeysInterface<Signer=Signer>,
F: FeeEstimator,
L: Logger,
impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> DiskWriteable for ChannelManager<Signer, M, T, K, F, L>
where
M::Target: chain::Watch<Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<Signer=Signer>,
F::Target: FeeEstimator,
L::Target: Logger,
{
fn write_to_file(&self, writer: &mut fs::File) -> Result<(), std::io::Error> {
self.write(writer)
Expand Down Expand Up @@ -87,16 +86,16 @@ impl FilesystemPersister {

/// Writes the provided `ChannelManager` to the path provided at `FilesystemPersister`
/// initialization, within a file called "manager".
pub fn persist_manager<Signer, M, T, K, F, L>(
pub fn persist_manager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
data_dir: String,
manager: &ChannelManager<Signer, Arc<M>, Arc<T>, Arc<K>, Arc<F>, Arc<L>>
manager: &ChannelManager<Signer, M, T, K, F, L>
) -> Result<(), std::io::Error>
where Signer: Sign,
M: chain::Watch<Signer>,
T: BroadcasterInterface,
K: KeysInterface<Signer=Signer>,
F: FeeEstimator,
L: Logger
where
M::Target: chain::Watch<Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<Signer=Signer>,
F::Target: FeeEstimator,
L::Target: Logger,
{
let path = PathBuf::from(data_dir);
util::write_to_file(path, "manager".to_string(), manager)
Expand All @@ -105,14 +104,14 @@ impl FilesystemPersister {
/// Read `ChannelMonitor`s from disk.
pub fn read_channelmonitors<Signer: Sign, K: Deref> (
&self, keys_manager: K
) -> Result<HashMap<OutPoint, (BlockHash, ChannelMonitor<Signer>)>, std::io::Error>
where K::Target: KeysInterface<Signer=Signer> + Sized
) -> Result<Vec<(BlockHash, ChannelMonitor<Signer>)>, std::io::Error>
where K::Target: KeysInterface<Signer=Signer> + Sized,
{
let path = self.path_to_monitor_data();
if !Path::new(&path).exists() {
return Ok(HashMap::new());
return Ok(Vec::new());
}
let mut outpoint_to_channelmonitor = HashMap::new();
let mut res = Vec::new();
for file_option in fs::read_dir(path).unwrap() {
let file = file_option.unwrap();
let owned_file_name = file.file_name();
Expand Down Expand Up @@ -144,32 +143,32 @@ impl FilesystemPersister {
let mut buffer = Cursor::new(&contents);
match <(BlockHash, ChannelMonitor<Signer>)>::read(&mut buffer, &*keys_manager) {
Ok((blockhash, channel_monitor)) => {
outpoint_to_channelmonitor.insert(
OutPoint { txid: txid.unwrap(), index: index.unwrap() },
(blockhash, channel_monitor),
);
if channel_monitor.get_funding_txo().0.txid != txid.unwrap() || channel_monitor.get_funding_txo().0.index != index.unwrap() {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "ChannelMonitor was stored in the wrong file"));
}
res.push((blockhash, channel_monitor));
}
Err(e) => return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("Failed to deserialize ChannelMonitor: {}", e),
))
}
}
Ok(outpoint_to_channelmonitor)
Ok(res)
}
}

impl<ChannelSigner: Sign> channelmonitor::Persist<ChannelSigner> for FilesystemPersister {
fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>) -> Result<(), ChannelMonitorUpdateErr> {
let filename = format!("{}_{}", funding_txo.txid.to_hex(), funding_txo.index);
util::write_to_file(self.path_to_monitor_data(), filename, monitor)
.map_err(|_| ChannelMonitorUpdateErr::PermanentFailure)
.map_err(|_| ChannelMonitorUpdateErr::PermanentFailure)
}

fn update_persisted_channel(&self, funding_txo: OutPoint, _update: &ChannelMonitorUpdate, monitor: &ChannelMonitor<ChannelSigner>) -> Result<(), ChannelMonitorUpdateErr> {
let filename = format!("{}_{}", funding_txo.txid.to_hex(), funding_txo.index);
util::write_to_file(self.path_to_monitor_data(), filename, monitor)
.map_err(|_| ChannelMonitorUpdateErr::PermanentFailure)
.map_err(|_| ChannelMonitorUpdateErr::PermanentFailure)
}
}

Expand Down Expand Up @@ -227,21 +226,21 @@ mod tests {
// Check that the persisted channel data is empty before any channels are
// open.
let mut persisted_chan_data_0 = persister_0.read_channelmonitors(nodes[0].keys_manager).unwrap();
assert_eq!(persisted_chan_data_0.keys().len(), 0);
assert_eq!(persisted_chan_data_0.len(), 0);
let mut persisted_chan_data_1 = persister_1.read_channelmonitors(nodes[1].keys_manager).unwrap();
assert_eq!(persisted_chan_data_1.keys().len(), 0);
assert_eq!(persisted_chan_data_1.len(), 0);

// Helper to make sure the channel is on the expected update ID.
macro_rules! check_persisted_data {
($expected_update_id: expr) => {
persisted_chan_data_0 = persister_0.read_channelmonitors(nodes[0].keys_manager).unwrap();
assert_eq!(persisted_chan_data_0.keys().len(), 1);
for (_, mon) in persisted_chan_data_0.values() {
assert_eq!(persisted_chan_data_0.len(), 1);
for (_, mon) in persisted_chan_data_0.iter() {
assert_eq!(mon.get_latest_update_id(), $expected_update_id);
}
persisted_chan_data_1 = persister_1.read_channelmonitors(nodes[1].keys_manager).unwrap();
assert_eq!(persisted_chan_data_1.keys().len(), 1);
for (_, mon) in persisted_chan_data_1.values() {
assert_eq!(persisted_chan_data_1.len(), 1);
for (_, mon) in persisted_chan_data_1.iter() {
assert_eq!(mon.get_latest_update_id(), $expected_update_id);
}
}
Expand Down