@@ -10,7 +10,7 @@ use std::io::Write;
1010use std:: ops:: Deref ;
1111#[ cfg( unix) ]
1212use std:: os:: unix:: fs:: OpenOptionsExt ;
13- use std:: path:: Path ;
13+ use std:: path:: { Path , PathBuf } ;
1414use std:: sync:: { Arc , RwLock } ;
1515
1616use bdk_chain:: indexer:: keychain_txout:: ChangeSet as BdkIndexerChangeSet ;
@@ -26,14 +26,16 @@ use lightning::routing::scoring::{
2626 ChannelLiquidities , ProbabilisticScorer , ProbabilisticScoringDecayParameters ,
2727} ;
2828use lightning:: util:: persist:: {
29- KVStore , KVStoreSync , KVSTORE_NAMESPACE_KEY_ALPHABET , KVSTORE_NAMESPACE_KEY_MAX_LEN ,
30- NETWORK_GRAPH_PERSISTENCE_KEY , NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE ,
31- NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE , OUTPUT_SWEEPER_PERSISTENCE_KEY ,
32- OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE , OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE ,
33- SCORER_PERSISTENCE_KEY , SCORER_PERSISTENCE_PRIMARY_NAMESPACE ,
34- SCORER_PERSISTENCE_SECONDARY_NAMESPACE ,
29+ migrate_kv_store_data , KVStore , KVStoreSync , KVSTORE_NAMESPACE_KEY_ALPHABET ,
30+ KVSTORE_NAMESPACE_KEY_MAX_LEN , NETWORK_GRAPH_PERSISTENCE_KEY ,
31+ NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE , NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE ,
32+ OUTPUT_SWEEPER_PERSISTENCE_KEY , OUTPUT_SWEEPER_PERSISTENCE_PRIMARY_NAMESPACE ,
33+ OUTPUT_SWEEPER_PERSISTENCE_SECONDARY_NAMESPACE , SCORER_PERSISTENCE_KEY ,
34+ SCORER_PERSISTENCE_PRIMARY_NAMESPACE , SCORER_PERSISTENCE_SECONDARY_NAMESPACE ,
3535} ;
3636use lightning:: util:: ser:: { Readable , ReadableArgs , Writeable } ;
37+ use lightning_persister:: fs_store:: v1:: FilesystemStore ;
38+ use lightning_persister:: fs_store:: v2:: { FilesystemStoreV2 , FilesystemStoreV2Error } ;
3739use lightning_types:: string:: PrintableString ;
3840
3941use super :: * ;
@@ -47,7 +49,7 @@ use crate::logger::{log_error, LdkLogger, Logger};
4749use crate :: peer_store:: PeerStore ;
4850use crate :: types:: { Broadcaster , DynStore , KeysManager , Sweeper } ;
4951use crate :: wallet:: ser:: { ChangeSetDeserWrapper , ChangeSetSerWrapper } ;
50- use crate :: { Error , EventQueue , NodeMetrics } ;
52+ use crate :: { BuildError , Error , EventQueue , NodeMetrics } ;
5153
5254pub const EXTERNAL_PATHFINDING_SCORES_CACHE_KEY : & str = "external_pathfinding_scores_cache" ;
5355
@@ -619,6 +621,42 @@ pub(crate) fn read_bdk_wallet_change_set(
619621 Ok ( Some ( change_set) )
620622}
621623
624+ /// Opens a [`FilesystemStoreV2`], automatically migrating from v1 format if necessary.
625+ ///
626+ /// If the directory contains v1 data (files at the top level), the data is migrated to v2 format
627+ /// in a temporary directory, the original is renamed to `fs_store_v1_backup`, and the migrated
628+ /// directory is moved into place.
629+ pub ( crate ) fn open_or_migrate_fs_store (
630+ storage_dir_path : PathBuf ,
631+ ) -> Result < FilesystemStoreV2 , BuildError > {
632+ match FilesystemStoreV2 :: new ( storage_dir_path. clone ( ) ) {
633+ Ok ( store) => Ok ( store) ,
634+ Err ( FilesystemStoreV2Error :: V1DataDetected ( _) ) => {
635+ // The directory contains v1 data, migrate to v2.
636+ let mut v1_store = FilesystemStore :: new ( storage_dir_path. clone ( ) ) ;
637+
638+ let mut v2_dir = storage_dir_path. clone ( ) ;
639+ v2_dir. set_file_name ( "fs_store_v2_migrating" ) ;
640+ fs:: create_dir_all ( v2_dir. clone ( ) ) . map_err ( |_| BuildError :: StoragePathAccessFailed ) ?;
641+ let mut v2_store = FilesystemStoreV2 :: new ( v2_dir. clone ( ) )
642+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
643+
644+ migrate_kv_store_data ( & mut v1_store, & mut v2_store)
645+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
646+
647+ // Swap directories: rename v1 out of the way, move v2 into place.
648+ let mut backup_dir = storage_dir_path. clone ( ) ;
649+ backup_dir. set_file_name ( "fs_store_v1_backup" ) ;
650+ fs:: rename ( & storage_dir_path, & backup_dir)
651+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
652+ fs:: rename ( & v2_dir, & storage_dir_path) . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
653+
654+ FilesystemStoreV2 :: new ( storage_dir_path) . map_err ( |_| BuildError :: KVStoreSetupFailed )
655+ } ,
656+ Err ( _) => Err ( BuildError :: KVStoreSetupFailed ) ,
657+ }
658+ }
659+
622660#[ cfg( test) ]
623661mod tests {
624662 use super :: read_or_generate_seed_file;
0 commit comments