diff --git a/src/lib.rs b/src/lib.rs index fb1361db..5f54a9d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,6 +94,8 @@ pub enum StartupError { Bitcoind(BitcoindError), #[cfg(unix)] Daemonization(&'static str), + #[cfg(windows)] + NoWatchonlyInDatadir, } impl fmt::Display for StartupError { @@ -116,6 +118,17 @@ impl fmt::Display for StartupError { Self::Bitcoind(e) => write!(f, "Error setting up bitcoind interface: '{}'.", e), #[cfg(unix)] Self::Daemonization(e) => write!(f, "Error when daemonizing: '{}'.", e), + #[cfg(windows)] + Self::NoWatchonlyInDatadir => { + write!( + f, + "A data directory exists with no watchonly wallet. Really old versions of Liana used to not \ + store the bitcoind watchonly wallet under their own datadir on Windows. A migration will be \ + necessary to be able to use such an old datadir with recent versions of Liana. The migration \ + is automatically performed by Liana version 4 and older. If you want to salvage this datadir \ + first run Liana v4 before running more recent Liana versions." + ) + } } } } @@ -188,70 +201,6 @@ fn setup_sqlite( Ok(sqlite) } -// Try to copy the watchonly wallet from its former location on Windows to its new location. -fn copy_watchonly_wallet( - bitcoind_cookie_path: &path::Path, - bitcoin_net: miniscript::bitcoin::Network, - wallet_name: &str, - new_wallet_path: &path::Path, -) -> bool { - // For the main network both the wallet and the cookie file are stored at the root of the - // datadir. For test networks the wallet is in "//wallets//" and - // the cookie file in "//". - let parent_dir = match bitcoind_cookie_path.parent() { - Some(d) => d, - None => { - log::error!("Could not find the parent directory of the bitcoind cookie file."); - return false; - } - }; - let wallet_path = match bitcoin_net { - miniscript::bitcoin::Network::Bitcoin => parent_dir.join(wallet_name), - miniscript::bitcoin::Network::Testnet - | miniscript::bitcoin::Network::Signet - | miniscript::bitcoin::Network::Regtest => parent_dir - .join("wallets") - .join(wallet_name) - .join("wallet.dat"), - net => panic!( - "Unsupported network '{}', unknown at the time of writing.", - net - ), - }; - - if wallet_path.exists() { - log::info!( - "Found the watchonly wallet file at the former location: '{}'. Copying it to our own datadir.", - wallet_path.as_path().to_string_lossy() - ); - if let Err(e) = fs::create_dir(new_wallet_path) { - log::error!( - "Error while creating the watchonly wallet directory at {}: {}", - wallet_path.to_string_lossy(), - e - ); - return false; - } - let new_wallet_dat_path = new_wallet_path.join("wallet.dat"); - if let Err(e) = fs::copy(wallet_path, new_wallet_dat_path) { - log::error!( - "Error while copying the watchonly wallet to our own datadir: {}", - e - ); - false - } else { - log::info!("Successfully copied the watchonly wallet file."); - true - } - } else { - log::error!( - "No watchonly wallet found at '{}'.", - wallet_path.as_path().to_string_lossy() - ); - false - } -} - // Connect to bitcoind. Setup the watchonly wallet, and do some sanity checks. // If all went well, returns the interface to bitcoind. fn setup_bitcoind( @@ -285,23 +234,10 @@ fn setup_bitcoind( log::info!("Creating a new watchonly wallet on bitcoind."); bitcoind.create_watchonly_wallet(&config.main_descriptor)?; log::info!("Watchonly wallet created."); - } else if !wo_path.exists() && !cfg!(test) { - // TODO: remove this hack. - // NOTE: this is Windows-specific but we don't gate it upon a windows target to be able to - // test this codepath in a functional test. - log::info!( - "A data directory exists with no watchonly wallet. This is most likely due to \ - having been created to an older version of Liana on Windows, where the watchonly \ - wallet would live under bitcoind's datadir. Trying to find the older wallet and copy it in our own datadir." - ); - let wo_name = "lianad_watchonly_wallet"; - if !copy_watchonly_wallet( - &bitcoind_config.cookie_path, - config.bitcoin_config.network, - wo_name, - wo_path.as_path(), - ) { - panic!("Cannot continue without a watchonly wallet. Please contact support."); + } else { + #[cfg(windows)] + if !cfg!(test) && !wo_path.exists() { + return Err(StartupError::NoWatchonlyInDatadir); } } log::info!("Loading our watchonly wallet on bitcoind."); diff --git a/tests/test_misc.py b/tests/test_misc.py index 0628c00b..7add9ad5 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -349,25 +349,3 @@ def test_retry_on_workqueue_exceeded(lianad, bitcoind, executor): # We should have retried the request to bitcoind, which should now succeed along with the call. # This just checks the response we get is sane, nothing particular with this field. assert "block_height" in f_liana.result(TIMEOUT) - - -def test_wo_wallet_copy_from_bitcoind_datadir(lianad, bitcoind): - """Simulate an old install on Windows and make sure the watchonly wallet gets migrated.""" - wo_name = "lianad_watchonly_wallet" - old_wo_path = os.path.join(bitcoind.bitcoin_dir, "regtest", "wallets", wo_name) - new_wo_path = os.path.join(lianad.datadir, "regtest", wo_name) - - # Start lianad. It'll have created the watchonly within our datadir. Move it where it would - # have been created by Liana v1 on Windows. - lianad.stop() - shutil.copytree(new_wo_path, old_wo_path) - shutil.rmtree(new_wo_path) - assert not os.path.isdir(new_wo_path) - - # Now restart lianad. It should detect it within the bitcoind datadir and copy it to its own. - lianad.start() - assert os.path.isdir(new_wo_path) - assert lianad.is_in_log( - "A data directory exists with no watchonly wallet. This is most likely due to.*" - ) - assert lianad.is_in_log("Successfully copied the watchonly wallet file.")