From b75da6961bf196ed2fb913efd9c2be0056f35e90 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Thu, 21 Mar 2019 11:39:42 +0100 Subject: [PATCH 1/3] [DEVOPS-1250] backport RCD-47 fix about 'hasSpendingPassword' metadata with extra sanity check Since a few users have already ran the migration, they might have migrated wallet with incorrect metadata, wrongly stating that their wallet has no spending password, and as a consequence, preventing them from doing anything with their wallet. So, we do now run an extra sanity check upon every start to make sure that the wallet acid state metadata matches what we find in the keystore. --- wallet/src/Cardano/Wallet/Action.hs | 4 +- wallet/src/Cardano/Wallet/Kernel/Migration.hs | 57 +++++++++++++++++-- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/wallet/src/Cardano/Wallet/Action.hs b/wallet/src/Cardano/Wallet/Action.hs index 6c03908697d..16f6cf1d18f 100644 --- a/wallet/src/Cardano/Wallet/Action.hs +++ b/wallet/src/Cardano/Wallet/Action.hs @@ -22,7 +22,8 @@ import Cardano.Wallet.Kernel (PassiveWallet) import qualified Cardano.Wallet.Kernel as Kernel import qualified Cardano.Wallet.Kernel.Internal as Kernel.Internal import qualified Cardano.Wallet.Kernel.Keystore as Keystore -import Cardano.Wallet.Kernel.Migration (migrateLegacyDataLayer) +import Cardano.Wallet.Kernel.Migration (migrateLegacyDataLayer, + sanityCheckSpendingPassword) import qualified Cardano.Wallet.Kernel.Mode as Kernel.Mode import qualified Cardano.Wallet.Kernel.NodeStateAdaptor as NodeStateAdaptor import Cardano.Wallet.Server.CLI (WalletBackendParams, @@ -68,6 +69,7 @@ actionWithWallet params genesisConfig walletConfig txpConfig ntpConfig nodeParam let pm = configProtocolMagic genesisConfig WalletLayer.Kernel.bracketPassiveWallet pm dbMode logMessage' keystore nodeState (npFInjects nodeParams) $ \walletLayer passiveWallet -> do migrateLegacyDataLayer passiveWallet dbPath (getFullMigrationFlag params) + sanityCheckSpendingPassword passiveWallet let plugs = plugins (walletLayer, passiveWallet) dbMode diff --git a/wallet/src/Cardano/Wallet/Kernel/Migration.hs b/wallet/src/Cardano/Wallet/Kernel/Migration.hs index 83c3c5f4130..d1c46966d08 100644 --- a/wallet/src/Cardano/Wallet/Kernel/Migration.hs +++ b/wallet/src/Cardano/Wallet/Kernel/Migration.hs @@ -1,10 +1,17 @@ -module Cardano.Wallet.Kernel.Migration (migrateLegacyDataLayer) where +{-# LANGUAGE LambdaCase #-} + +module Cardano.Wallet.Kernel.Migration + ( migrateLegacyDataLayer + , sanityCheckSpendingPassword + ) where import Universum +import Data.Acid.Advanced (update') import Data.Text (pack) import Data.Time (defaultTimeLocale, formatTime, getCurrentTime, iso8601DateFormat) +import Pos.Crypto.Signing (checkPassMatches) import System.Directory (doesDirectoryExist, makeAbsolute, renamePath) import Formatting ((%)) @@ -15,10 +22,15 @@ import Pos.Crypto (EncryptedSecretKey) import Pos.Util.Wlog (Severity (..)) import qualified Cardano.Wallet.Kernel as Kernel +import Cardano.Wallet.Kernel.DB.AcidState (UpdateHdRootPassword (..)) import qualified Cardano.Wallet.Kernel.DB.HdWallet as HD +import Cardano.Wallet.Kernel.DB.InDb (InDb (..)) +import qualified Cardano.Wallet.Kernel.DB.Read as Kernel import qualified Cardano.Wallet.Kernel.Internal as Kernel import Cardano.Wallet.Kernel.Keystore as Keystore +import qualified Cardano.Wallet.Kernel.Read as Kernel import Cardano.Wallet.Kernel.Restore (restoreWallet) +import Cardano.Wallet.Kernel.Util.Core (getCurrentTimestamp) {------------------------------------------------------------------------------- Pure helper functions for migration. @@ -104,9 +116,7 @@ restore pw forced esk = do rootId = HD.eskToHdRootId nm esk let -- DEFAULTS for wallet restoration - -- we don't have a spending password during migration - hasSpendingPassword = False - -- we cannot derive an address without a spending password + hasSpendingPassword = isNothing $ checkPassMatches mempty esk defaultAddress = Nothing defaultWalletName = HD.WalletName "" defaultAssuranceLevel = HD.AssuranceLevelStrict @@ -132,3 +142,42 @@ restore pw forced esk = do True -> do logMsg Error ("Migration failed! " <> msg <> " You are advised to delete the newly created db and try again.") exitFailure + +-- | Verify that the spending password metadata are correctly set. We mistakenly +-- forgot to port a fix from RCD-47 done on 2.0.x onto 3.0.0 and, for a few +-- users, have migrated / restored their wallet with a wrong spending password +-- metadata (arbitrarily set to `False`), making their wallet completely +-- unusable. +-- +-- This checks makes sure that the 'hasSpendingPassword' metadata correctly +-- reflects the wallet condition. To be run on each start-up, unfortunately. +sanityCheckSpendingPassword + :: Kernel.PassiveWallet + -> IO () +sanityCheckSpendingPassword pw = do + let nm = makeNetworkMagic (pw ^. Kernel.walletProtocolMagic) + wKeys <- Keystore.getKeys (pw ^. Kernel.walletKeystore) + db <- Kernel.getWalletSnapshot pw + lastUpdateNow <- InDb <$> getCurrentTimestamp + forM_ wKeys $ \esk -> do + let hasSpendingPassword = case checkPassMatches mempty esk of + Nothing -> HD.HasSpendingPassword lastUpdateNow + Just _ -> HD.NoSpendingPassword + let rootId = HD.eskToHdRootId nm esk + whenDiscrepancy db rootId hasSpendingPassword restoreTruth >>= \case + Left (HD.UnknownHdRoot _) -> + logMsg Error "Failed to update spending password status, HDRoot is gone?" + Right _ -> + return () + where + logMsg = pw ^. Kernel.walletLogMessage + whenDiscrepancy db rootId hasSpendingPassword action = do + case (hasSpendingPassword, Kernel.lookupHdRootId db rootId) of + (_, Left e) -> + return $ Left e + (HD.HasSpendingPassword _, Right root) | root ^. HD.hdRootHasPassword == HD.NoSpendingPassword -> + action rootId hasSpendingPassword + _ -> -- Avoid making a DB update when there's no need + return $ Right () + restoreTruth rootId hasSpendingPassword = + void <$> update' (pw ^. Kernel.wallets) (UpdateHdRootPassword rootId hasSpendingPassword) From af431e85de9bb99ed45104f175db160d0f8298e5 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Thu, 21 Mar 2019 11:44:36 +0100 Subject: [PATCH 2/3] [DEVOPS-1250] add CHANGELOG entry about DEVOPS-1250 hotfix --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa741207c20..c1389efc3ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +## Cardano SL 3.0.1 + +### Fixes + +- Fix inconsistent 'hasSpendingPassword' resolution from legacy data layer migration ([DEVOPS-1250](https://iohk.myjetbrains.com/youtrack/issue/DEVOPS-1250) [#4112](https://github.com/input-output-hk/cardano-sl/pull/4112)) + ## Cardano SL 3.0.0 ### Fixes From 787721966e66ad109ee1867234d493471ceb1b5a Mon Sep 17 00:00:00 2001 From: Samuel Leathers Date: Thu, 21 Mar 2019 11:32:15 -0400 Subject: [PATCH 3/3] [DEVOPS-1250] csl-daedalus applicationVersion bump --- lib/configuration.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/configuration.yaml b/lib/configuration.yaml index 198b9c4371b..8776dca318d 100644 --- a/lib/configuration.yaml +++ b/lib/configuration.yaml @@ -14851,7 +14851,7 @@ mainnet_wallet_win64: &mainnet_wallet_win64 <<: *mainnet_full update: applicationName: csl-daedalus - applicationVersion: 13 + applicationVersion: 14 lastKnownBlockVersion: bvMajor: 0 bvMinor: 1 @@ -14861,7 +14861,7 @@ mainnet_wallet_macos64: &mainnet_wallet_macos64 <<: *mainnet_full update: applicationName: csl-daedalus - applicationVersion: 13 + applicationVersion: 14 lastKnownBlockVersion: bvMajor: 0 bvMinor: 1 @@ -14871,7 +14871,7 @@ mainnet_wallet_linux64: &mainnet_wallet_linux64 <<: *mainnet_full update: applicationName: csl-daedalus - applicationVersion: 13 + applicationVersion: 14 lastKnownBlockVersion: bvMajor: 0 bvMinor: 1 @@ -14945,7 +14945,7 @@ testnet_wallet: &testnet_wallet <<: *testnet_full update: &testnet_wallet_update applicationName: csl-daedalus - applicationVersion: 9 + applicationVersion: 10 lastKnownBlockVersion: bvMajor: 0 bvMinor: 0 @@ -14984,7 +14984,7 @@ mainnet_dryrun_wallet_win64: &mainnet_dryrun_wallet_win64 <<: *mainnet_dryrun_full update: applicationName: csl-daedalus - applicationVersion: 22 + applicationVersion: 23 lastKnownBlockVersion: bvMajor: 0 bvMinor: 2 @@ -14994,7 +14994,7 @@ mainnet_dryrun_wallet_macos64: &mainnet_dryrun_wallet_macos64 <<: *mainnet_dryrun_full update: applicationName: csl-daedalus - applicationVersion: 22 + applicationVersion: 23 lastKnownBlockVersion: bvMajor: 0 bvMinor: 2 @@ -15004,7 +15004,7 @@ mainnet_dryrun_wallet_linux64: &mainnet_dryrun_wallet_linux64 <<: *mainnet_dryrun_full update: applicationName: csl-daedalus - applicationVersion: 22 + applicationVersion: 23 lastKnownBlockVersion: bvMajor: 0 bvMinor: 2