Skip to content

Commit 44aad2a

Browse files
committed
db-analyser: support full block application in --store-ledger
1 parent ed5e401 commit 44aad2a

File tree

5 files changed

+69
-30
lines changed

5 files changed

+69
-30
lines changed

ouroboros-consensus-cardano/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ Lastly the user can provide the analysis that should be run on the chain:
127127
slot number, it will create one on the next available slot number (and issue a
128128
warning about this fact).
129129

130+
By default, for better performance, blocks are only *re*applied, skipping eg
131+
validation of signatures and Plutus scripts. If desired (eg when investigating
132+
a Ledger bug), one can use `--full-ledger-validation` to also perform these
133+
checks. If there is an error on block application, the previous ledger state
134+
is stored.
135+
130136
* `--count-blocks` prints out the number of blocks it saw on the chain
131137

132138
* `--benchmark-ledger-ops` applies the main ledger calculations to each block in

ouroboros-consensus-cardano/app/DBAnalyser/Parsers.hs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module DBAnalyser.Parsers (
99
) where
1010

1111
import Cardano.Crypto (RequiresNetworkMagic (..))
12+
import Cardano.Tools.DBAnalyser.Analysis
1213
import Cardano.Tools.DBAnalyser.Block.Byron
1314
import Cardano.Tools.DBAnalyser.Block.Cardano
1415
import Cardano.Tools.DBAnalyser.Block.Shelley
@@ -117,10 +118,19 @@ parseAnalysis = asum [
117118
]
118119

119120
storeLedgerParser :: Parser AnalysisName
120-
storeLedgerParser = (StoreLedgerStateAt . SlotNo) <$> option auto
121-
( long "store-ledger"
122-
<> metavar "SLOT_NUMBER"
123-
<> help "Store ledger state at specific slot number" )
121+
storeLedgerParser = do
122+
slot <- SlotNo <$> option auto
123+
( long "store-ledger"
124+
<> metavar "SLOT_NUMBER"
125+
<> help "Store ledger state at specific slot number" )
126+
ledgerValidation <- flag LedgerReapply LedgerApply
127+
( long "full-ledger-validation"
128+
<> help ( "Use full block application while applying blocks to ledger states, "
129+
<> "also validating signatures and scripts. "
130+
<> "This is much slower than block reapplication (the default)."
131+
)
132+
)
133+
pure $ StoreLedgerStateAt slot ledgerValidation
124134

125135
checkNoThunksParser :: Parser AnalysisName
126136
checkNoThunksParser = CheckNoThunksEvery <$> option auto

ouroboros-consensus-cardano/app/db-analyser.hs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
-- [--db-validation ARG]
99
-- [--show-slot-block-no | --count-tx-outputs |
1010
-- --show-block-header-size | --show-block-txs-size |
11-
-- --show-ebbs | --store-ledger SLOT_NUMBER | --count-blocks |
12-
-- --checkThunks BLOCK_COUNT | --trace-ledger |
13-
-- --repro-mempool-and-forge INT | --benchmark-ledger-ops
14-
-- [--out-file FILE] |
11+
-- --show-ebbs | --store-ledger SLOT_NUMBER
12+
-- [--full-ledger-validation] |
13+
-- --count-blocks | --checkThunks BLOCK_COUNT |
14+
-- --trace-ledger | --repro-mempool-and-forge INT |
15+
-- --benchmark-ledger-ops [--out-file FILE] |
1516
-- --get-block-application-metrics NUM [--out-file FILE]]
1617
-- [--num-blocks-to-process INT] COMMAND
1718
module Main (main) where

ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBAnalyser/Analysis.hs

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module Cardano.Tools.DBAnalyser.Analysis (
1717
, AnalysisName (..)
1818
, AnalysisResult (..)
1919
, AnalysisStartFrom (..)
20+
, LedgerApplicationMode (..)
2021
, Limit (..)
2122
, NumberOfBlocks (..)
2223
, SStartFrom (..)
@@ -51,7 +52,7 @@ import Ouroboros.Consensus.HeaderValidation (HasAnnTip (..),
5152
HeaderState (..), headerStatePoint, tickHeaderState,
5253
validateHeader)
5354
import Ouroboros.Consensus.Ledger.Abstract (LedgerCfg, LedgerConfig,
54-
applyBlockLedgerResult, applyChainTick,
55+
applyBlockLedgerResult, applyChainTick, tickThenApply,
5556
tickThenApplyLedgerResult, tickThenReapply)
5657
import Ouroboros.Consensus.Ledger.Basics (LedgerResult (..),
5758
LedgerState, getTipSlot)
@@ -72,6 +73,7 @@ import Ouroboros.Consensus.Storage.LedgerDB (DiskSnapshot (..),
7273
writeSnapshot)
7374
import Ouroboros.Consensus.Storage.Serialisation (SizeInBytes,
7475
encodeDisk)
76+
import Ouroboros.Consensus.Util ((..:))
7577
import qualified Ouroboros.Consensus.Util.IOLike as IOLike
7678
import Ouroboros.Consensus.Util.ResourceRegistry
7779
import System.FS.API (SomeHasFS (..))
@@ -88,7 +90,7 @@ data AnalysisName =
8890
| ShowBlockTxsSize
8991
| ShowEBBs
9092
| OnlyValidation
91-
| StoreLedgerStateAt SlotNo
93+
| StoreLedgerStateAt SlotNo LedgerApplicationMode
9294
| CountBlocks
9395
| CheckNoThunksEvery Word64
9496
| TraceLedgerProcessing
@@ -109,6 +111,11 @@ data AnalysisResult =
109111
newtype NumberOfBlocks = NumberOfBlocks { unNumberOfBlocks :: Word64 }
110112
deriving (Eq, Show, Num, Read)
111113

114+
-- | Whether to apply blocks to a ledger state via /reapplication/ (eg skipping
115+
-- signature checks/Plutus scripts) or full /application/ (much slower).
116+
data LedgerApplicationMode = LedgerReapply | LedgerApply
117+
deriving (Eq, Show)
118+
112119
runAnalysis ::
113120
forall blk.
114121
( HasAnalysis blk
@@ -133,7 +140,7 @@ runAnalysis analysisName = case go analysisName of
133140
go ShowBlockTxsSize = mkAnalysis $ showBlockTxsSize
134141
go ShowEBBs = mkAnalysis $ showEBBs
135142
go OnlyValidation = mkAnalysis @StartFromPoint $ \_ -> pure Nothing
136-
go (StoreLedgerStateAt slotNo) = mkAnalysis $ storeLedgerStateAt slotNo
143+
go (StoreLedgerStateAt slotNo lgrAppMode) = mkAnalysis $ storeLedgerStateAt slotNo lgrAppMode
137144
go CountBlocks = mkAnalysis $ countBlocks
138145
go (CheckNoThunksEvery nBks) = mkAnalysis $ checkNoThunksEvery nBks
139146
go TraceLedgerProcessing = mkAnalysis $ traceLedgerProcessing
@@ -221,6 +228,8 @@ data TraceEvent blk =
221228
-- ^ triggered once during StoreLedgerStateAt analysis,
222229
-- when snapshot was created in slot proceeding the
223230
-- requested one
231+
| LedgerErrorEvent (Point blk) (ExtValidationError blk)
232+
-- ^ triggered when applying a block with the given point failed
224233
| BlockTxSizeEvent SlotNo Int SizeInBytes
225234
-- ^ triggered for all blocks during ShowBlockTxsSize analysis,
226235
-- it holds:
@@ -241,7 +250,7 @@ data TraceEvent blk =
241250
-- * total time spent in the mutator when calling 'Mempool.getSnapshotFor'
242251
-- * total time spent in gc when calling 'Mempool.getSnapshotFor'
243252

244-
instance HasAnalysis blk => Show (TraceEvent blk) where
253+
instance (HasAnalysis blk, LedgerSupportsProtocol blk) => Show (TraceEvent blk) where
245254
show (StartedEvent analysisName) = "Started " <> (show analysisName)
246255
show DoneEvent = "Done"
247256
show (BlockSlotEvent bn sn) = intercalate "\t" $ [
@@ -272,6 +281,8 @@ instance HasAnalysis blk => Show (TraceEvent blk) where
272281
show (SnapshotWarningEvent requested actual) =
273282
"Snapshot was created at " <> show actual <> " " <>
274283
"because there was no block forged at requested " <> show requested
284+
show (LedgerErrorEvent pt err) =
285+
"Applying block at " <> show pt <> " failed: " <> show err
275286
show (BlockTxSizeEvent slot numBlocks txsSize) = intercalate "\t" [
276287
show slot
277288
, "Num txs in block = " <> show numBlocks
@@ -396,21 +407,33 @@ storeLedgerStateAt ::
396407
, HasAnalysis blk
397408
, LedgerSupportsProtocol blk
398409
)
399-
=> SlotNo -> Analysis blk StartFromLedgerState
400-
storeLedgerStateAt slotNo (AnalysisEnv { db, registry, startFrom, cfg, limit, ledgerDbFS, tracer }) = do
410+
=> SlotNo
411+
-> LedgerApplicationMode
412+
-> Analysis blk StartFromLedgerState
413+
storeLedgerStateAt slotNo ledgerAppMode env = do
401414
void $ processAllUntil db registry GetBlock startFrom limit initLedger process
402415
pure Nothing
403416
where
417+
AnalysisEnv { db, registry, startFrom, cfg, limit, ledgerDbFS, tracer } = env
404418
FromLedgerState initLedger = startFrom
405419

406420
process :: ExtLedgerState blk -> blk -> IO (NextStep, ExtLedgerState blk)
407421
process oldLedger blk = do
408422
let ledgerCfg = ExtLedgerCfg cfg
409-
newLedger = tickThenReapply ledgerCfg blk oldLedger
410-
when (blockSlot blk >= slotNo) $ storeLedgerState blk newLedger
411-
when (blockSlot blk > slotNo) $ issueWarning blk
412-
when ((unBlockNo $ blockNo blk) `mod` 1000 == 0) $ reportProgress blk
413-
return (continue blk, newLedger)
423+
case runExcept $ tickThenXApply ledgerCfg blk oldLedger of
424+
Right newLedger -> do
425+
when (blockSlot blk >= slotNo) $ storeLedgerState newLedger
426+
when (blockSlot blk > slotNo) $ issueWarning blk
427+
when ((unBlockNo $ blockNo blk) `mod` 1000 == 0) $ reportProgress blk
428+
return (continue blk, newLedger)
429+
Left err -> do
430+
traceWith tracer $ LedgerErrorEvent (blockPoint blk) err
431+
storeLedgerState oldLedger
432+
pure (Stop, oldLedger)
433+
434+
tickThenXApply = case ledgerAppMode of
435+
LedgerReapply -> pure ..: tickThenReapply
436+
LedgerApply -> tickThenApply
414437

415438
continue :: blk -> NextStep
416439
continue blk
@@ -422,16 +445,15 @@ storeLedgerStateAt slotNo (AnalysisEnv { db, registry, startFrom, cfg, limit, le
422445
reportProgress blk = let event = BlockSlotEvent (blockNo blk) (blockSlot blk)
423446
in traceWith tracer event
424447

425-
storeLedgerState ::
426-
blk
427-
-> ExtLedgerState blk
428-
-> IO ()
429-
storeLedgerState blk ledgerState = do
430-
let snapshot = DiskSnapshot
431-
(unSlotNo $ blockSlot blk)
432-
(Just $ "db-analyser")
433-
writeSnapshot ledgerDbFS encLedger snapshot ledgerState
434-
traceWith tracer $ SnapshotStoredEvent (blockSlot blk)
448+
storeLedgerState :: ExtLedgerState blk -> IO ()
449+
storeLedgerState ledgerState = case pointSlot pt of
450+
NotOrigin slot -> do
451+
let snapshot = DiskSnapshot (unSlotNo slot) (Just "db-analyser")
452+
writeSnapshot ledgerDbFS encLedger snapshot ledgerState
453+
traceWith tracer $ SnapshotStoredEvent slot
454+
Origin -> pure ()
455+
where
456+
pt = headerStatePoint $ headerState ledgerState
435457

436458
encLedger :: ExtLedgerState blk -> Encoding
437459
encLedger =

ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBAnalyser/Types.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ data DBAnalyserConfig = DBAnalyserConfig {
2020
, confLimit :: Limit
2121
}
2222

23-
-- | Whether to validate the on-disk files of the ChainDB. This is completely
23+
-- | The extent of the ChainDB on-disk files validation. This is completely
2424
-- unrelated to validation of the ledger rules.
2525
data ValidateBlocks = ValidateAllBlocks | MinimumBlockValidation

0 commit comments

Comments
 (0)