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

Commit 4818274

Browse files
Merge pull request #3470 from input-output-hk/matt-noonan/restoration
This PR delivers the first part of a wallet's restoration using the new data layer.
2 parents bf712f0 + 047bdf1 commit 4818274

31 files changed

+1433
-817
lines changed

wallet-new/cardano-sl-wallet-new.cabal

+3-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ library
7272
Cardano.Wallet.Kernel.Addresses
7373
Cardano.Wallet.Kernel.BIP39
7474
Cardano.Wallet.Kernel.BListener
75-
Cardano.Wallet.Kernel.ChainState
7675
Cardano.Wallet.Kernel.CoinSelection
7776
Cardano.Wallet.Kernel.CoinSelection.FromGeneric
7877
Cardano.Wallet.Kernel.CoinSelection.Generic
@@ -81,6 +80,7 @@ library
8180
Cardano.Wallet.Kernel.CoinSelection.Generic.LargestFirst
8281
Cardano.Wallet.Kernel.CoinSelection.Generic.Random
8382
Cardano.Wallet.Kernel.DB.AcidState
83+
Cardano.Wallet.Kernel.DB.BlockContext
8484
Cardano.Wallet.Kernel.DB.BlockMeta
8585
Cardano.Wallet.Kernel.DB.HdWallet
8686
Cardano.Wallet.Kernel.DB.HdWallet.Create
@@ -101,6 +101,7 @@ library
101101
Cardano.Wallet.Kernel.DB.Updates
102102
Cardano.Wallet.Kernel.DB.Util.AcidState
103103
Cardano.Wallet.Kernel.DB.Util.IxSet
104+
Cardano.Wallet.Kernel.Decrypt
104105
Cardano.Wallet.Kernel.Diffusion
105106
Cardano.Wallet.Kernel.Internal
106107
Cardano.Wallet.Kernel.Invariants
@@ -110,6 +111,7 @@ library
110111
Cardano.Wallet.Kernel.Pending
111112
Cardano.Wallet.Kernel.PrefilterTx
112113
Cardano.Wallet.Kernel.Read
114+
Cardano.Wallet.Kernel.Restore
113115
Cardano.Wallet.Kernel.Submission
114116
Cardano.Wallet.Kernel.Submission.Worker
115117
Cardano.Wallet.Kernel.Transactions

wallet-new/src/Cardano/Wallet/Kernel.hs

+8-6
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,15 @@ initPassiveWallet :: (Severity -> Text -> IO ())
9393
-> IO PassiveWallet
9494
initPassiveWallet logMessage keystore Handles{..} node = do
9595
submission <- newMVar (newWalletSubmission rho)
96+
restore <- newMVar Map.empty
9697
return PassiveWallet {
97-
_walletLogMessage = logMessage
98-
, _walletKeystore = keystore
99-
, _wallets = hAcid
100-
, _walletMeta = hMeta
101-
, _walletNode = node
102-
, _walletSubmission = submission
98+
_walletLogMessage = logMessage
99+
, _walletKeystore = keystore
100+
, _wallets = hAcid
101+
, _walletMeta = hMeta
102+
, _walletNode = node
103+
, _walletSubmission = submission
104+
, _walletRestorationTask = restore
103105
}
104106
where
105107
rho = defaultResubmitFunction (exponentialBackoff 255 1.25)

wallet-new/src/Cardano/Wallet/Kernel/Accounts.hs

+9-6
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ import Cardano.Wallet.Kernel.DB.AcidState (CreateHdAccount (..), DB,
2222
DeleteHdAccount (..), UpdateHdAccountName (..))
2323
import Cardano.Wallet.Kernel.DB.HdWallet (AccountName (..),
2424
HdAccount (..), HdAccountId (..), HdAccountIx (..),
25-
HdRootId, UnknownHdAccount (..), hdAccountName)
25+
HdAccountState (..), HdAccountUpToDate (..), HdRootId,
26+
UnknownHdAccount (..), hdAccountName)
2627
import Cardano.Wallet.Kernel.DB.HdWallet.Create
2728
(CreateHdAccountError (..), initHdAccount)
2829
import Cardano.Wallet.Kernel.DB.HdWallet.Derivation
2930
(HardeningMode (..), deriveIndex)
30-
import Cardano.Wallet.Kernel.DB.Spec (Checkpoint, initCheckpoint)
31+
import Cardano.Wallet.Kernel.DB.Spec (initCheckpoint)
3132
import Cardano.Wallet.Kernel.Internal (PassiveWallet, walletKeystore,
3233
wallets)
3334
import qualified Cardano.Wallet.Kernel.Keystore as Keystore
@@ -115,7 +116,7 @@ createHdRndAccount _spendingPassword accountName _esk rootId pw = do
115116
tryGenerateAccount gen collisions = do
116117
newIndex <- deriveIndex (flip uniformR gen) HdAccountIx HardDerivation
117118
let hdAccountId = HdAccountId rootId newIndex
118-
newAccount = initHdAccount hdAccountId firstCheckpoint &
119+
newAccount = initHdAccount hdAccountId initState &
119120
hdAccountName .~ accountName
120121
db = pw ^. wallets
121122
res <- update db (CreateHdAccount newAccount)
@@ -136,9 +137,11 @@ createHdRndAccount _spendingPassword accountName _esk rootId pw = do
136137
maxAllowedCollisions :: Word32
137138
maxAllowedCollisions = 42
138139

139-
-- | The first 'Checkpoint' known to this 'Account'.
140-
firstCheckpoint :: Checkpoint
141-
firstCheckpoint = initCheckpoint mempty
140+
-- Initial account state
141+
initState :: HdAccountState
142+
initState = HdAccountStateUpToDate HdAccountUpToDate {
143+
_hdUpToDateCheckpoints = one $ initCheckpoint mempty
144+
}
142145

143146
-- | Deletes an HD 'Account' from the data storage.
144147
deleteAccount :: HdAccountId

wallet-new/src/Cardano/Wallet/Kernel/Addresses.hs

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import Cardano.Wallet.Kernel.DB.HdWallet.Create
2727
(CreateHdAddressError (..), initHdAddress)
2828
import Cardano.Wallet.Kernel.DB.HdWallet.Derivation
2929
(HardeningMode (..), deriveIndex)
30-
import Cardano.Wallet.Kernel.DB.InDb (InDb (..))
3130
import Cardano.Wallet.Kernel.Internal (PassiveWallet, walletKeystore,
3231
wallets)
3332
import qualified Cardano.Wallet.Kernel.Keystore as Keystore
@@ -144,7 +143,7 @@ createHdRndAddress spendingPassword esk accId pw = do
144143
case mbAddr of
145144
Nothing -> return (Left $ CreateAddressHdRndGenerationFailed accId)
146145
Just (newAddress, _) -> do
147-
let hdAddress = initHdAddress hdAddressId (InDb newAddress)
146+
let hdAddress = initHdAddress hdAddressId newAddress
148147
let db = pw ^. wallets
149148
res <- update db (CreateHdAddress hdAddress)
150149
case res of

wallet-new/src/Cardano/Wallet/Kernel/BListener.hs

+19-25
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
module Cardano.Wallet.Kernel.BListener (
33
-- * Respond to block chain events
44
applyBlock
5-
, applyBlocks
65
, switchToFork
76
-- * Testing
87
, observableRollbackUseInTestsOnly
@@ -13,16 +12,15 @@ import Universum hiding (State)
1312
import Control.Concurrent.MVar (modifyMVar_)
1413
import Data.Acid.Advanced (update')
1514

16-
import Pos.Core (SlotId)
17-
import Pos.Core.Chrono (OldestFirst)
1815
import Pos.Crypto (EncryptedSecretKey)
1916

2017
import Cardano.Wallet.Kernel.DB.AcidState (ApplyBlock (..),
21-
ObservableRollbackUseInTestsOnly (..),
22-
RollbackDuringRestoration, SwitchToFork (..))
18+
ObservableRollbackUseInTestsOnly (..), SwitchToFork (..),
19+
SwitchToForkError (..))
20+
import Cardano.Wallet.Kernel.DB.BlockContext
2321
import Cardano.Wallet.Kernel.DB.HdWallet
24-
import Cardano.Wallet.Kernel.DB.InDb
25-
import Cardano.Wallet.Kernel.DB.Resolved (ResolvedBlock, rbSlotId)
22+
import Cardano.Wallet.Kernel.DB.Resolved (ResolvedBlock, rbContext)
23+
import Cardano.Wallet.Kernel.DB.Spec.Update (ApplyBlockFailed)
2624
import Cardano.Wallet.Kernel.DB.TxMeta.Types
2725
import Cardano.Wallet.Kernel.Internal
2826
import qualified Cardano.Wallet.Kernel.NodeStateAdaptor as Node
@@ -41,35 +39,31 @@ import Cardano.Wallet.Kernel.Types (WalletId (..))
4139
-- TODO: Improve performance (CBR-379)
4240
prefilterBlock' :: PassiveWallet
4341
-> ResolvedBlock
44-
-> IO ((SlotId, Map HdAccountId PrefilteredBlock), [TxMeta])
42+
-> IO ((BlockContext, Map HdAccountId PrefilteredBlock), [TxMeta])
4543
prefilterBlock' pw b = do
4644
aux <$> getWalletCredentials pw
4745
where
4846
aux :: [(WalletId, EncryptedSecretKey)]
49-
-> ((SlotId, Map HdAccountId PrefilteredBlock), [TxMeta])
47+
-> ((BlockContext, Map HdAccountId PrefilteredBlock), [TxMeta])
5048
aux ws =
5149
let (conMap, conMeta) = mconcat $ map (uncurry (prefilterBlock b)) ws
52-
in ((b ^. rbSlotId, conMap), conMeta)
50+
in ((b ^. rbContext, conMap), conMeta)
5351

5452
-- | Notify all the wallets in the PassiveWallet of a new block
5553
applyBlock :: PassiveWallet
5654
-> ResolvedBlock
57-
-> IO ()
55+
-> IO (Either ApplyBlockFailed ())
5856
applyBlock pw@PassiveWallet{..} b = do
5957
k <- Node.getSecurityParameter _walletNode
60-
((slotId, blocksByAccount), metas) <- prefilterBlock' pw b
58+
((ctxt, blocksByAccount), metas) <- prefilterBlock' pw b
6159
-- apply block to all Accounts in all Wallets
62-
confirmed <- update' _wallets $ ApplyBlock k (InDb slotId) blocksByAccount
63-
modifyMVar_ _walletSubmission $ return . Submission.remPending confirmed
64-
mapM_ (putTxMeta _walletMeta) metas
65-
66-
-- | Apply multiple blocks, one at a time, to all wallets in the PassiveWallet
67-
--
68-
-- TODO(@matt-noonan) this will be the responsibility of the worker thread (as part of CBR-243: Wallet restoration)
69-
applyBlocks :: PassiveWallet
70-
-> OldestFirst [] ResolvedBlock
71-
-> IO ()
72-
applyBlocks = mapM_ . applyBlock
60+
mConfirmed <- update' _wallets $ ApplyBlock k ctxt blocksByAccount
61+
case mConfirmed of
62+
Left err -> return $ Left err
63+
Right confirmed -> do
64+
modifyMVar_ _walletSubmission $ return . Submission.remPending confirmed
65+
mapM_ (putTxMeta _walletMeta) metas
66+
return $ Right ()
7367

7468
-- | Switch to a new fork
7569
--
@@ -78,7 +72,7 @@ applyBlocks = mapM_ . applyBlock
7872
switchToFork :: PassiveWallet
7973
-> Int -- ^ Number of blocks to roll back
8074
-> [ResolvedBlock] -- ^ Blocks in the new fork
81-
-> IO (Either RollbackDuringRestoration ())
75+
-> IO (Either SwitchToForkError ())
8276
switchToFork pw@PassiveWallet{..} n bs = do
8377
k <- Node.getSecurityParameter _walletNode
8478
blocksAndMeta <- mapM (prefilterBlock' pw) bs
@@ -98,7 +92,7 @@ switchToFork pw@PassiveWallet{..} n bs = do
9892
-- Only used for tests. See 'switchToFork'.
9993
-- TODO(kde): Do we want tests to deal with metadata?
10094
observableRollbackUseInTestsOnly :: PassiveWallet
101-
-> IO (Either RollbackDuringRestoration ())
95+
-> IO (Either SwitchToForkError ())
10296
observableRollbackUseInTestsOnly PassiveWallet{..} = do
10397
res <- update' _wallets $ ObservableRollbackUseInTestsOnly
10498
case res of

0 commit comments

Comments
 (0)