-
Notifications
You must be signed in to change notification settings - Fork 629
[CBR-150] Implement rollback #3245
Changes from all commits
6c84686
3e30806
8c35c78
20b192f
3b6317a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,15 +9,19 @@ module Cardano.Wallet.Kernel ( | |
PassiveWallet -- opaque | ||
, DB -- opaque | ||
, WalletId | ||
, applyBlock | ||
, applyBlocks | ||
, bracketPassiveWallet | ||
, init | ||
, walletLogMessage | ||
, walletPassive | ||
-- * The only effectful getter you will ever need | ||
-- ** Respond to block chain events | ||
, applyBlock | ||
, applyBlocks | ||
, switchToFork | ||
-- *** Testing | ||
, observableRollbackUseInTestsOnly | ||
-- ** The only effectful getter you will ever need | ||
, getWalletSnapshot | ||
-- * Pure getters acting on a DB snapshot | ||
-- ** Pure getters acting on a DB snapshot | ||
, module Getters | ||
-- * Active wallet | ||
, ActiveWallet -- opaque | ||
|
@@ -49,7 +53,8 @@ import Cardano.Wallet.Kernel.Types (WalletId (..)) | |
|
||
import Cardano.Wallet.Kernel.DB.AcidState (ApplyBlock (..), | ||
CancelPending (..), DB, NewPending (..), NewPendingError, | ||
Snapshot (..), defDB) | ||
ObservableRollbackUseInTestsOnly (..), Snapshot (..), | ||
SwitchToFork (..), defDB) | ||
import Cardano.Wallet.Kernel.DB.HdWallet | ||
import Cardano.Wallet.Kernel.DB.InDb | ||
import Cardano.Wallet.Kernel.DB.Resolved (ResolvedBlock) | ||
|
@@ -140,7 +145,7 @@ applyBlock pw@PassiveWallet{..} b | |
= do | ||
blocksByAccount <- prefilterBlock' pw b | ||
-- apply block to all Accounts in all Wallets | ||
void $ update' _wallets $ ApplyBlock blocksByAccount | ||
update' _wallets $ ApplyBlock blocksByAccount | ||
|
||
-- | Apply multiple blocks, one at a time, to all wallets in the PassiveWallet | ||
-- | ||
|
@@ -150,6 +155,25 @@ applyBlocks :: PassiveWallet | |
-> IO () | ||
applyBlocks = mapM_ . applyBlock | ||
|
||
-- | Switch to a new fork | ||
-- | ||
-- NOTE: The Ouroboros protocol says that this is only valid if the number of | ||
-- resolved blocks exceeds the length of blocks to roll back. | ||
switchToFork :: PassiveWallet | ||
-> Int -- ^ Number of blocks to roll back | ||
-> [ResolvedBlock] -- ^ Blocks in the new fork | ||
-> IO () | ||
switchToFork pw@PassiveWallet{..} n bs = do | ||
blockssByAccount <- mapM (prefilterBlock' pw) bs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something we might need to revisit later (jotting down out loud notes here): another good testament for CBR-341, as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a comment to CBR-341 that this |
||
update' _wallets $ SwitchToFork n blockssByAccount | ||
|
||
-- | Observable rollback | ||
-- | ||
-- Only used for tests. See 'switchToFork'. | ||
observableRollbackUseInTestsOnly :: PassiveWallet -> IO () | ||
observableRollbackUseInTestsOnly PassiveWallet{..} = | ||
update' _wallets $ ObservableRollbackUseInTestsOnly | ||
|
||
{------------------------------------------------------------------------------- | ||
Active wallet | ||
-------------------------------------------------------------------------------} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,14 +14,12 @@ module Cardano.Wallet.Kernel.DB.Spec ( | |
, pendingTransactions | ||
, checkpointUtxo | ||
, checkpointUtxoBalance | ||
, checkpointExpected | ||
, checkpointPending | ||
, checkpointBlockMeta | ||
-- ** Lenses into the current checkpoint | ||
, currentCheckpoint | ||
, currentUtxo | ||
, currentUtxoBalance | ||
, currentExpected | ||
, currentPending | ||
, currentPendingTxs | ||
, currentBlockMeta | ||
|
@@ -33,9 +31,9 @@ import Control.Lens (to) | |
import Control.Lens.TH (makeLenses) | ||
import qualified Data.Map.Strict as M | ||
import Data.SafeCopy (base, deriveSafeCopy) | ||
import Formatting (bprint, (%)) | ||
import Formatting.Buildable (build) | ||
import Serokell.Util.Text (listJsonIndent) | ||
import Formatting (bprint, build, (%)) | ||
import qualified Formatting.Buildable | ||
import Serokell.Util.Text (listJsonIndent, mapJson) | ||
|
||
import qualified Pos.Core as Core | ||
import qualified Pos.Core.Txp as Txp | ||
|
@@ -80,11 +78,23 @@ removePending ids (Pending (InDb old)) = Pending (InDb $ old `withoutKeys` ids) | |
|
||
-- | Per-wallet state | ||
-- | ||
-- This is the same across all wallet types. | ||
-- NOTE: At the moment this does not included the expected UTxO. The expected | ||
-- UTxO is used for two things: | ||
-- | ||
-- * Block resolution (translating tx inputs to their corresponding outputs, so | ||
-- that we know the corresponding addresses, needed for prefilering) | ||
-- * Minimum balance computation | ||
-- | ||
-- Fortunately however we can rely on a full node as backing, so we don't need | ||
-- to use the expected UTxO for block resolution (this is explained in the | ||
-- formal spec in section "Prefiltering -- Consequences", under "possible | ||
-- alternatives"), and minimum balance computation is a new feature that we | ||
-- haven't implemented yet. | ||
-- | ||
-- NOTE: This is the same across all wallet types. | ||
data Checkpoint = Checkpoint { | ||
_checkpointUtxo :: InDb Core.Utxo | ||
, _checkpointUtxoBalance :: InDb Core.Coin | ||
, _checkpointExpected :: InDb Core.Utxo | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we tracking in a ticket anywhere that we need to tackle expected balance separately from this PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
, _checkpointPending :: Pending | ||
, _checkpointBlockMeta :: BlockMeta | ||
} | ||
|
@@ -107,14 +117,12 @@ currentCheckpoint = neHead | |
|
||
currentUtxo :: Lens' Checkpoints Core.Utxo | ||
currentUtxoBalance :: Lens' Checkpoints Core.Coin | ||
currentExpected :: Lens' Checkpoints Core.Utxo | ||
currentBlockMeta :: Lens' Checkpoints BlockMeta | ||
currentPending :: Lens' Checkpoints Pending | ||
currentPendingTxs :: Lens' Checkpoints PendingTxs | ||
|
||
currentUtxo = currentCheckpoint . checkpointUtxo . fromDb | ||
currentUtxoBalance = currentCheckpoint . checkpointUtxoBalance . fromDb | ||
currentExpected = currentCheckpoint . checkpointExpected . fromDb | ||
currentBlockMeta = currentCheckpoint . checkpointBlockMeta | ||
currentPending = currentCheckpoint . checkpointPending | ||
currentPendingTxs = currentPending . pendingTransactions . fromDb | ||
|
@@ -134,3 +142,17 @@ instance Buildable Pending where | |
build (Pending p) = | ||
let elems = p ^. fromDb . to M.toList | ||
in bprint ("Pending " % listJsonIndent 4) (map fst elems) | ||
|
||
instance Buildable Checkpoint where | ||
build Checkpoint{..} = bprint | ||
( "Checkpoint" | ||
% "{ utxo: " % mapJson | ||
% ", utxoBalance: " % build | ||
% ", pending: " % build | ||
% ", blockMeta: " % build | ||
% "}" | ||
) | ||
(_fromDb _checkpointUtxo) | ||
(_fromDb _checkpointUtxoBalance) | ||
_checkpointPending | ||
_checkpointBlockMeta |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cannot get more explicit than this! π¬