@@ -34,12 +34,13 @@ use lightning::routing::scoring::{
3434use lightning:: sign:: { EntropySource , NodeSigner } ;
3535use lightning:: util:: config:: HTLCInterceptionFlags ;
3636use lightning:: util:: persist:: {
37- KVStore , CHANNEL_MANAGER_PERSISTENCE_KEY , CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE ,
38- CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE ,
37+ migrate_kv_store_data , KVStore , CHANNEL_MANAGER_PERSISTENCE_KEY ,
38+ CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE , CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE ,
3939} ;
4040use lightning:: util:: ser:: ReadableArgs ;
4141use lightning:: util:: sweep:: OutputSweeper ;
4242use lightning_persister:: fs_store:: v1:: FilesystemStore ;
43+ use lightning_persister:: fs_store:: v2:: FilesystemStoreV2 ;
4344use vss_client:: headers:: VssHeaderProvider ;
4445
4546use crate :: chain:: ChainSource ;
@@ -629,15 +630,20 @@ impl NodeBuilder {
629630 self . build_with_store ( node_entropy, kv_store)
630631 }
631632
632- /// Builds a [`Node`] instance with a [`FilesystemStore `] backend and according to the options
633+ /// Builds a [`Node`] instance with a [`FilesystemStoreV2 `] backend and according to the options
633634 /// previously configured.
635+ ///
636+ /// If the storage directory contains data from a v1 filesystem store, it will be
637+ /// automatically migrated to the v2 format.
634638 pub fn build_with_fs_store ( & self , node_entropy : NodeEntropy ) -> Result < Node , BuildError > {
635639 let mut storage_dir_path: PathBuf = self . config . storage_dir_path . clone ( ) . into ( ) ;
636640 storage_dir_path. push ( "fs_store" ) ;
637641
638642 fs:: create_dir_all ( storage_dir_path. clone ( ) )
639643 . map_err ( |_| BuildError :: StoragePathAccessFailed ) ?;
640- let kv_store = FilesystemStore :: new ( storage_dir_path) ;
644+
645+ let kv_store = open_or_migrate_fs_store ( storage_dir_path) ?;
646+
641647 self . build_with_store ( node_entropy, kv_store)
642648 }
643649
@@ -1087,7 +1093,7 @@ impl ArcedNodeBuilder {
10871093 self . inner . read ( ) . unwrap ( ) . build ( * node_entropy) . map ( Arc :: new)
10881094 }
10891095
1090- /// Builds a [`Node`] instance with a [`FilesystemStore `] backend and according to the options
1096+ /// Builds a [`Node`] instance with a [`FilesystemStoreV2 `] backend and according to the options
10911097 /// previously configured.
10921098 pub fn build_with_fs_store (
10931099 & self , node_entropy : Arc < NodeEntropy > ,
@@ -1998,6 +2004,40 @@ fn build_with_store_internal(
19982004 } )
19992005}
20002006
2007+ /// Opens a [`FilesystemStoreV2`], automatically migrating from v1 format if necessary.
2008+ ///
2009+ /// If the directory contains v1 data (files at the top level), the data is migrated to v2 format
2010+ /// in a temporary directory, the original is renamed to `fs_store_v1_backup`, and the migrated
2011+ /// directory is moved into place.
2012+ fn open_or_migrate_fs_store ( storage_dir_path : PathBuf ) -> Result < FilesystemStoreV2 , BuildError > {
2013+ match FilesystemStoreV2 :: new ( storage_dir_path. clone ( ) ) {
2014+ Ok ( store) => Ok ( store) ,
2015+ Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: InvalidData => {
2016+ // The directory contains v1 data, migrate to v2.
2017+ let mut v1_store = FilesystemStore :: new ( storage_dir_path. clone ( ) ) ;
2018+
2019+ let mut v2_dir = storage_dir_path. clone ( ) ;
2020+ v2_dir. set_file_name ( "fs_store_v2_migrating" ) ;
2021+ fs:: create_dir_all ( v2_dir. clone ( ) ) . map_err ( |_| BuildError :: StoragePathAccessFailed ) ?;
2022+ let mut v2_store = FilesystemStoreV2 :: new ( v2_dir. clone ( ) )
2023+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
2024+
2025+ migrate_kv_store_data ( & mut v1_store, & mut v2_store)
2026+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
2027+
2028+ // Swap directories: rename v1 out of the way, move v2 into place.
2029+ let mut backup_dir = storage_dir_path. clone ( ) ;
2030+ backup_dir. set_file_name ( "fs_store_v1_backup" ) ;
2031+ fs:: rename ( & storage_dir_path, & backup_dir)
2032+ . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
2033+ fs:: rename ( & v2_dir, & storage_dir_path) . map_err ( |_| BuildError :: KVStoreSetupFailed ) ?;
2034+
2035+ FilesystemStoreV2 :: new ( storage_dir_path) . map_err ( |_| BuildError :: KVStoreSetupFailed )
2036+ } ,
2037+ Err ( _) => Err ( BuildError :: KVStoreSetupFailed ) ,
2038+ }
2039+ }
2040+
20012041fn optionally_install_rustls_cryptoprovider ( ) {
20022042 // Acquire a global Mutex, ensuring that only one process at a time install the provider. This
20032043 // is mostly required for running tests concurrently.
0 commit comments