@@ -17,7 +17,6 @@ extern crate libc;
1717use bitcoin:: hash_types:: { BlockHash , Txid } ;
1818use bitcoin:: hashes:: hex:: { FromHex , ToHex } ;
1919use lightning:: routing:: network_graph:: NetworkGraph ;
20- use crate :: util:: DiskWriteable ;
2120use lightning:: chain;
2221use lightning:: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
2322use lightning:: chain:: channelmonitor:: { ChannelMonitor , ChannelMonitorUpdate } ;
@@ -28,9 +27,38 @@ use lightning::ln::channelmanager::ChannelManager;
2827use lightning:: util:: logger:: Logger ;
2928use lightning:: util:: ser:: { ReadableArgs , Writeable } ;
3029use std:: fs;
31- use std:: io:: { Cursor , Error } ;
30+ use std:: io:: { Cursor , Error , Write } ;
3231use std:: ops:: Deref ;
33- use std:: path:: { Path , PathBuf } ;
32+ use std:: path:: { Path , PathBuf , MAIN_SEPARATOR } ;
33+
34+
35+ /// Trait that handles persisting a [`ChannelManager`] and [`NetworkGraph`] to disk.
36+ pub trait Persister
37+ {
38+ /// Persist the given [`ChannelManager`] to disk, returning an error if persistence failed
39+ /// (which will cause the BackgroundProcessor which called this method to exit).
40+ fn persist_manager < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > ( & self , channel_manager : & ChannelManager < Signer , M , T , K , F , L > ) -> Result < ( ) , std:: io:: Error > where
41+ M :: Target : ' static + chain:: Watch < Signer > ,
42+ T :: Target : ' static + BroadcasterInterface ,
43+ K :: Target : ' static + KeysInterface < Signer = Signer > ,
44+ F :: Target : ' static + FeeEstimator ,
45+ L :: Target : ' static + Logger ;
46+
47+ /// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed.
48+ fn persist_graph ( & self , network_graph : & NetworkGraph ) -> Result < ( ) , std:: io:: Error > ;
49+ }
50+
51+ /// Trait for a key-value store for persisting some writeable object at some key
52+ pub trait KVStorePersister < W : Writeable > {
53+ /// Persist the given writeable using the provided key
54+ fn persist ( & self , key : String , object : & W ) -> std:: io:: Result < ( ) > ;
55+ }
56+
57+ impl < W : Writeable > KVStorePersister < W > for FilesystemPersister {
58+ fn persist ( & self , key : String , object : & W ) -> std:: io:: Result < ( ) > {
59+ util:: write_to_file ( format ! ( "{}{}{}" , self . path_to_channel_data, MAIN_SEPARATOR , key) , object)
60+ }
61+ }
3462
3563/// FilesystemPersister persists channel data on disk, where each channel's
3664/// data is stored in a file named after its funding outpoint.
@@ -48,31 +76,6 @@ pub struct FilesystemPersister {
4876 path_to_channel_data : String ,
4977}
5078
51- impl < Signer : Sign > DiskWriteable for ChannelMonitor < Signer > {
52- fn write_to_file ( & self , writer : & mut fs:: File ) -> Result < ( ) , Error > {
53- self . write ( writer)
54- }
55- }
56-
57- impl < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > DiskWriteable for ChannelManager < Signer , M , T , K , F , L >
58- where
59- M :: Target : chain:: Watch < Signer > ,
60- T :: Target : BroadcasterInterface ,
61- K :: Target : KeysInterface < Signer =Signer > ,
62- F :: Target : FeeEstimator ,
63- L :: Target : Logger ,
64- {
65- fn write_to_file ( & self , writer : & mut fs:: File ) -> Result < ( ) , std:: io:: Error > {
66- self . write ( writer)
67- }
68- }
69-
70- impl DiskWriteable for NetworkGraph {
71- fn write_to_file ( & self , writer : & mut fs:: File ) -> Result < ( ) , std:: io:: Error > {
72- self . write ( writer)
73- }
74- }
75-
7679impl FilesystemPersister {
7780 /// Initialize a new FilesystemPersister and set the path to the individual channels'
7881 /// files.
@@ -87,34 +90,8 @@ impl FilesystemPersister {
8790 self . path_to_channel_data . clone ( )
8891 }
8992
90- pub ( crate ) fn path_to_monitor_data ( & self ) -> PathBuf {
91- let mut path = PathBuf :: from ( self . path_to_channel_data . clone ( ) ) ;
92- path. push ( "monitors" ) ;
93- path
94- }
95-
96- /// Writes the provided `ChannelManager` to the path provided at `FilesystemPersister`
97- /// initialization, within a file called "manager".
98- pub fn persist_manager < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > (
99- data_dir : String ,
100- manager : & ChannelManager < Signer , M , T , K , F , L >
101- ) -> Result < ( ) , std:: io:: Error >
102- where
103- M :: Target : chain:: Watch < Signer > ,
104- T :: Target : BroadcasterInterface ,
105- K :: Target : KeysInterface < Signer =Signer > ,
106- F :: Target : FeeEstimator ,
107- L :: Target : Logger ,
108- {
109- let path = PathBuf :: from ( data_dir) ;
110- util:: write_to_file ( path, "manager" . to_string ( ) , manager)
111- }
112-
113- /// Write the provided `NetworkGraph` to the path provided at `FilesystemPersister`
114- /// initialization, within a file called "network_graph"
115- pub fn persist_network_graph ( data_dir : String , network_graph : & NetworkGraph ) -> Result < ( ) , std:: io:: Error > {
116- let path = PathBuf :: from ( data_dir) ;
117- util:: write_to_file ( path, "network_graph" . to_string ( ) , network_graph)
93+ pub ( crate ) fn path_to_monitor_data ( & self ) -> String {
94+ format ! ( "{}{}monitors" , self . path_to_channel_data, MAIN_SEPARATOR )
11895 }
11996
12097 /// Read `ChannelMonitor`s from disk.
@@ -124,7 +101,7 @@ impl FilesystemPersister {
124101 where K :: Target : KeysInterface < Signer =Signer > + Sized ,
125102 {
126103 let path = self . path_to_monitor_data ( ) ;
127- if !Path :: new ( & path) . exists ( ) {
104+ if !Path :: new ( & PathBuf :: from ( & path) ) . exists ( ) {
128105 return Ok ( Vec :: new ( ) ) ;
129106 }
130107 let mut res = Vec :: new ( ) ;
@@ -187,18 +164,39 @@ impl<ChannelSigner: Sign> chainmonitor::Persist<ChannelSigner> for FilesystemPer
187164 // even broadcasting!
188165
189166 fn persist_new_channel ( & self , funding_txo : OutPoint , monitor : & ChannelMonitor < ChannelSigner > , _update_id : chainmonitor:: MonitorUpdateId ) -> Result < ( ) , chain:: ChannelMonitorUpdateErr > {
190- let filename = format ! ( "{} _{}" , funding_txo. txid. to_hex( ) , funding_txo. index) ;
191- util :: write_to_file ( self . path_to_monitor_data ( ) , filename , monitor)
167+ let key = format ! ( "monitors{}{} _{}" , MAIN_SEPARATOR , funding_txo. txid. to_hex( ) , funding_txo. index) ;
168+ self . persist ( key , monitor)
192169 . map_err ( |_| chain:: ChannelMonitorUpdateErr :: PermanentFailure )
193170 }
194171
195172 fn update_persisted_channel ( & self , funding_txo : OutPoint , _update : & Option < ChannelMonitorUpdate > , monitor : & ChannelMonitor < ChannelSigner > , _update_id : chainmonitor:: MonitorUpdateId ) -> Result < ( ) , chain:: ChannelMonitorUpdateErr > {
196- let filename = format ! ( "{} _{}" , funding_txo. txid. to_hex( ) , funding_txo. index) ;
197- util :: write_to_file ( self . path_to_monitor_data ( ) , filename , monitor)
173+ let key = format ! ( "monitors{}{} _{}" , MAIN_SEPARATOR , funding_txo. txid. to_hex( ) , funding_txo. index) ;
174+ self . persist ( key , monitor)
198175 . map_err ( |_| chain:: ChannelMonitorUpdateErr :: PermanentFailure )
199176 }
200177}
201178
179+ impl Persister for FilesystemPersister {
180+ fn persist_manager < Signer : Sign , M : Deref , T : Deref , K : Deref , F : Deref , L : Deref > ( & self , channel_manager : & ChannelManager < Signer , M , T , K , F , L > ) -> Result < ( ) , std:: io:: Error > where
181+ M :: Target : ' static + chain:: Watch < Signer > ,
182+ T :: Target : ' static + BroadcasterInterface ,
183+ K :: Target : ' static + KeysInterface < Signer =Signer > ,
184+ F :: Target : ' static + FeeEstimator ,
185+ L :: Target : ' static + Logger {
186+ self . persist ( "manager" . to_string ( ) , channel_manager)
187+ }
188+
189+ fn persist_graph ( & self , network_graph : & NetworkGraph ) -> Result < ( ) , std:: io:: Error > {
190+ if self . persist ( "network_graph" . to_string ( ) , network_graph) . is_err ( )
191+ {
192+ // Persistence errors here are non-fatal as we can just fetch the routing graph
193+ // again later, but they may indicate a disk error which could be fatal elsewhere.
194+ eprintln ! ( "Warning: Failed to persist network graph, check your disk and permissions" ) ;
195+ }
196+ Ok ( ( ) )
197+ }
198+ }
199+
202200#[ cfg( test) ]
203201mod tests {
204202 extern crate lightning;
0 commit comments