Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

Commit

Permalink
Merge pull request #3470 from input-output-hk/matt-noonan/restoration
Browse files Browse the repository at this point in the history
This PR delivers the first part of a wallet's restoration using the new data layer.
  • Loading branch information
adinapoli-iohk authored Aug 27, 2018
2 parents bf712f0 + 047bdf1 commit 4818274
Show file tree
Hide file tree
Showing 31 changed files with 1,433 additions and 817 deletions.
4 changes: 3 additions & 1 deletion wallet-new/cardano-sl-wallet-new.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ library
Cardano.Wallet.Kernel.Addresses
Cardano.Wallet.Kernel.BIP39
Cardano.Wallet.Kernel.BListener
Cardano.Wallet.Kernel.ChainState
Cardano.Wallet.Kernel.CoinSelection
Cardano.Wallet.Kernel.CoinSelection.FromGeneric
Cardano.Wallet.Kernel.CoinSelection.Generic
Expand All @@ -81,6 +80,7 @@ library
Cardano.Wallet.Kernel.CoinSelection.Generic.LargestFirst
Cardano.Wallet.Kernel.CoinSelection.Generic.Random
Cardano.Wallet.Kernel.DB.AcidState
Cardano.Wallet.Kernel.DB.BlockContext
Cardano.Wallet.Kernel.DB.BlockMeta
Cardano.Wallet.Kernel.DB.HdWallet
Cardano.Wallet.Kernel.DB.HdWallet.Create
Expand All @@ -101,6 +101,7 @@ library
Cardano.Wallet.Kernel.DB.Updates
Cardano.Wallet.Kernel.DB.Util.AcidState
Cardano.Wallet.Kernel.DB.Util.IxSet
Cardano.Wallet.Kernel.Decrypt
Cardano.Wallet.Kernel.Diffusion
Cardano.Wallet.Kernel.Internal
Cardano.Wallet.Kernel.Invariants
Expand All @@ -110,6 +111,7 @@ library
Cardano.Wallet.Kernel.Pending
Cardano.Wallet.Kernel.PrefilterTx
Cardano.Wallet.Kernel.Read
Cardano.Wallet.Kernel.Restore
Cardano.Wallet.Kernel.Submission
Cardano.Wallet.Kernel.Submission.Worker
Cardano.Wallet.Kernel.Transactions
Expand Down
14 changes: 8 additions & 6 deletions wallet-new/src/Cardano/Wallet/Kernel.hs
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,15 @@ initPassiveWallet :: (Severity -> Text -> IO ())
-> IO PassiveWallet
initPassiveWallet logMessage keystore Handles{..} node = do
submission <- newMVar (newWalletSubmission rho)
restore <- newMVar Map.empty
return PassiveWallet {
_walletLogMessage = logMessage
, _walletKeystore = keystore
, _wallets = hAcid
, _walletMeta = hMeta
, _walletNode = node
, _walletSubmission = submission
_walletLogMessage = logMessage
, _walletKeystore = keystore
, _wallets = hAcid
, _walletMeta = hMeta
, _walletNode = node
, _walletSubmission = submission
, _walletRestorationTask = restore
}
where
rho = defaultResubmitFunction (exponentialBackoff 255 1.25)
Expand Down
15 changes: 9 additions & 6 deletions wallet-new/src/Cardano/Wallet/Kernel/Accounts.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ import Cardano.Wallet.Kernel.DB.AcidState (CreateHdAccount (..), DB,
DeleteHdAccount (..), UpdateHdAccountName (..))
import Cardano.Wallet.Kernel.DB.HdWallet (AccountName (..),
HdAccount (..), HdAccountId (..), HdAccountIx (..),
HdRootId, UnknownHdAccount (..), hdAccountName)
HdAccountState (..), HdAccountUpToDate (..), HdRootId,
UnknownHdAccount (..), hdAccountName)
import Cardano.Wallet.Kernel.DB.HdWallet.Create
(CreateHdAccountError (..), initHdAccount)
import Cardano.Wallet.Kernel.DB.HdWallet.Derivation
(HardeningMode (..), deriveIndex)
import Cardano.Wallet.Kernel.DB.Spec (Checkpoint, initCheckpoint)
import Cardano.Wallet.Kernel.DB.Spec (initCheckpoint)
import Cardano.Wallet.Kernel.Internal (PassiveWallet, walletKeystore,
wallets)
import qualified Cardano.Wallet.Kernel.Keystore as Keystore
Expand Down Expand Up @@ -115,7 +116,7 @@ createHdRndAccount _spendingPassword accountName _esk rootId pw = do
tryGenerateAccount gen collisions = do
newIndex <- deriveIndex (flip uniformR gen) HdAccountIx HardDerivation
let hdAccountId = HdAccountId rootId newIndex
newAccount = initHdAccount hdAccountId firstCheckpoint &
newAccount = initHdAccount hdAccountId initState &
hdAccountName .~ accountName
db = pw ^. wallets
res <- update db (CreateHdAccount newAccount)
Expand All @@ -136,9 +137,11 @@ createHdRndAccount _spendingPassword accountName _esk rootId pw = do
maxAllowedCollisions :: Word32
maxAllowedCollisions = 42

-- | The first 'Checkpoint' known to this 'Account'.
firstCheckpoint :: Checkpoint
firstCheckpoint = initCheckpoint mempty
-- Initial account state
initState :: HdAccountState
initState = HdAccountStateUpToDate HdAccountUpToDate {
_hdUpToDateCheckpoints = one $ initCheckpoint mempty
}

-- | Deletes an HD 'Account' from the data storage.
deleteAccount :: HdAccountId
Expand Down
3 changes: 1 addition & 2 deletions wallet-new/src/Cardano/Wallet/Kernel/Addresses.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import Cardano.Wallet.Kernel.DB.HdWallet.Create
(CreateHdAddressError (..), initHdAddress)
import Cardano.Wallet.Kernel.DB.HdWallet.Derivation
(HardeningMode (..), deriveIndex)
import Cardano.Wallet.Kernel.DB.InDb (InDb (..))
import Cardano.Wallet.Kernel.Internal (PassiveWallet, walletKeystore,
wallets)
import qualified Cardano.Wallet.Kernel.Keystore as Keystore
Expand Down Expand Up @@ -144,7 +143,7 @@ createHdRndAddress spendingPassword esk accId pw = do
case mbAddr of
Nothing -> return (Left $ CreateAddressHdRndGenerationFailed accId)
Just (newAddress, _) -> do
let hdAddress = initHdAddress hdAddressId (InDb newAddress)
let hdAddress = initHdAddress hdAddressId newAddress
let db = pw ^. wallets
res <- update db (CreateHdAddress hdAddress)
case res of
Expand Down
44 changes: 19 additions & 25 deletions wallet-new/src/Cardano/Wallet/Kernel/BListener.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
module Cardano.Wallet.Kernel.BListener (
-- * Respond to block chain events
applyBlock
, applyBlocks
, switchToFork
-- * Testing
, observableRollbackUseInTestsOnly
Expand All @@ -13,16 +12,15 @@ import Universum hiding (State)
import Control.Concurrent.MVar (modifyMVar_)
import Data.Acid.Advanced (update')

import Pos.Core (SlotId)
import Pos.Core.Chrono (OldestFirst)
import Pos.Crypto (EncryptedSecretKey)

import Cardano.Wallet.Kernel.DB.AcidState (ApplyBlock (..),
ObservableRollbackUseInTestsOnly (..),
RollbackDuringRestoration, SwitchToFork (..))
ObservableRollbackUseInTestsOnly (..), SwitchToFork (..),
SwitchToForkError (..))
import Cardano.Wallet.Kernel.DB.BlockContext
import Cardano.Wallet.Kernel.DB.HdWallet
import Cardano.Wallet.Kernel.DB.InDb
import Cardano.Wallet.Kernel.DB.Resolved (ResolvedBlock, rbSlotId)
import Cardano.Wallet.Kernel.DB.Resolved (ResolvedBlock, rbContext)
import Cardano.Wallet.Kernel.DB.Spec.Update (ApplyBlockFailed)
import Cardano.Wallet.Kernel.DB.TxMeta.Types
import Cardano.Wallet.Kernel.Internal
import qualified Cardano.Wallet.Kernel.NodeStateAdaptor as Node
Expand All @@ -41,35 +39,31 @@ import Cardano.Wallet.Kernel.Types (WalletId (..))
-- TODO: Improve performance (CBR-379)
prefilterBlock' :: PassiveWallet
-> ResolvedBlock
-> IO ((SlotId, Map HdAccountId PrefilteredBlock), [TxMeta])
-> IO ((BlockContext, Map HdAccountId PrefilteredBlock), [TxMeta])
prefilterBlock' pw b = do
aux <$> getWalletCredentials pw
where
aux :: [(WalletId, EncryptedSecretKey)]
-> ((SlotId, Map HdAccountId PrefilteredBlock), [TxMeta])
-> ((BlockContext, Map HdAccountId PrefilteredBlock), [TxMeta])
aux ws =
let (conMap, conMeta) = mconcat $ map (uncurry (prefilterBlock b)) ws
in ((b ^. rbSlotId, conMap), conMeta)
in ((b ^. rbContext, conMap), conMeta)

-- | Notify all the wallets in the PassiveWallet of a new block
applyBlock :: PassiveWallet
-> ResolvedBlock
-> IO ()
-> IO (Either ApplyBlockFailed ())
applyBlock pw@PassiveWallet{..} b = do
k <- Node.getSecurityParameter _walletNode
((slotId, blocksByAccount), metas) <- prefilterBlock' pw b
((ctxt, blocksByAccount), metas) <- prefilterBlock' pw b
-- apply block to all Accounts in all Wallets
confirmed <- update' _wallets $ ApplyBlock k (InDb slotId) blocksByAccount
modifyMVar_ _walletSubmission $ return . Submission.remPending confirmed
mapM_ (putTxMeta _walletMeta) metas

-- | Apply multiple blocks, one at a time, to all wallets in the PassiveWallet
--
-- TODO(@matt-noonan) this will be the responsibility of the worker thread (as part of CBR-243: Wallet restoration)
applyBlocks :: PassiveWallet
-> OldestFirst [] ResolvedBlock
-> IO ()
applyBlocks = mapM_ . applyBlock
mConfirmed <- update' _wallets $ ApplyBlock k ctxt blocksByAccount
case mConfirmed of
Left err -> return $ Left err
Right confirmed -> do
modifyMVar_ _walletSubmission $ return . Submission.remPending confirmed
mapM_ (putTxMeta _walletMeta) metas
return $ Right ()

-- | Switch to a new fork
--
Expand All @@ -78,7 +72,7 @@ applyBlocks = mapM_ . applyBlock
switchToFork :: PassiveWallet
-> Int -- ^ Number of blocks to roll back
-> [ResolvedBlock] -- ^ Blocks in the new fork
-> IO (Either RollbackDuringRestoration ())
-> IO (Either SwitchToForkError ())
switchToFork pw@PassiveWallet{..} n bs = do
k <- Node.getSecurityParameter _walletNode
blocksAndMeta <- mapM (prefilterBlock' pw) bs
Expand All @@ -98,7 +92,7 @@ switchToFork pw@PassiveWallet{..} n bs = do
-- Only used for tests. See 'switchToFork'.
-- TODO(kde): Do we want tests to deal with metadata?
observableRollbackUseInTestsOnly :: PassiveWallet
-> IO (Either RollbackDuringRestoration ())
-> IO (Either SwitchToForkError ())
observableRollbackUseInTestsOnly PassiveWallet{..} = do
res <- update' _wallets $ ObservableRollbackUseInTestsOnly
case res of
Expand Down
Loading

0 comments on commit 4818274

Please sign in to comment.