@@ -49,7 +49,17 @@ import Data.Word (Word16, Word32, Word64)
4949import qualified Debug.Trace as Debug
5050import qualified GHC.Stats as GC
5151import LeiosDemoDb (LeiosDbConnection , leiosDbLookupEbBody )
52- import LeiosDemoTypes (BytesSize , EbHash , LeiosPoint , leiosMempoolSize , pointEbHash )
52+ import LeiosDemoTypes
53+ ( BytesSize
54+ , EbHash
55+ , HasLeiosVoting (.. )
56+ , LeiosExtValidationError (.. )
57+ , LeiosPoint
58+ , leiosMempoolSize
59+ , minCertificationThreshold
60+ , pointEbHash
61+ , verifyLeiosCert
62+ )
5363import NoThunks.Class (noThunks )
5464import Ouroboros.Consensus.Block
5565import Ouroboros.Consensus.Config
@@ -65,8 +75,6 @@ import Ouroboros.Consensus.HeaderValidation
6575import Ouroboros.Consensus.Ledger.Abstract
6676 ( ApplyBlock (getBlockKeySets , reapplyBlockLedgerResult )
6777 , applyBlockLedgerResult
68- , tickThenApply
69- , tickThenReapply
7078 )
7179import Ouroboros.Consensus.Ledger.Basics
7280import Ouroboros.Consensus.Ledger.Extended
@@ -86,16 +94,14 @@ import Ouroboros.Consensus.Storage.ImmutableDB (ImmutableDB)
8694import qualified Ouroboros.Consensus.Storage.ImmutableDB as ImmutableDB
8795import qualified Ouroboros.Consensus.Storage.LedgerDB as LedgerDB
8896import Ouroboros.Consensus.Storage.LedgerDB.Forker
89- ( Forker'
90- , LeiosClosureApplied (.. )
91- , ResolveLeiosBlock
97+ ( ResolveLeiosBlock
98+ , announcingRbHash
9299 , applyLeiosClosure
93100 , blockLeiosCert
94101 , headerLeiosAnnouncement
95102 , inlineLeiosClosure
96103 , leiosClosureTxKeySets
97104 , protocolStateLeiosAnnouncement
98- , resolveAndApplyLeiosClosure
99105 , resolveLeiosClosure
100106 )
101107import qualified Ouroboros.Consensus.Util.IOLike as IOLike
@@ -115,6 +121,7 @@ runAnalysis ::
115121 , LedgerSupportsMempool blk
116122 , LedgerSupportsProtocol blk
117123 , ResolveLeiosBlock blk
124+ , HasLeiosVoting blk
118125 , CanStowLedgerTables (LedgerState blk )
119126 ) =>
120127 AnalysisName -> SomeAnalysis blk
@@ -532,6 +539,7 @@ storeLedgerStateAt ::
532539 forall blk .
533540 ( LedgerSupportsProtocol blk
534541 , ResolveLeiosBlock blk
542+ , HasLeiosVoting blk
535543 , HasAnalysis blk
536544 ) =>
537545 SlotNo ->
@@ -545,12 +553,18 @@ storeLedgerStateAt slotNo ledgerAppMode env = do
545553 FromLedgerState ldb internal = startFrom
546554
547555 process :: () -> blk -> IO (NextStep , () )
548- process _ blk = do
549- oldLedger <- IOLike. atomically $ LedgerDB. getVolatileTip ldb
556+ process _ blk =
550557 LedgerDB. withTipForker
551558 ldb
552559 ( \ frk -> do
553- result <- applyBlockLeios leiosDb ledgerAppMode OmitLedgerEvents cfg frk oldLedger blk
560+ result <-
561+ LedgerDB. applyBlock
562+ leiosDb
563+ OmitLedgerEvents
564+ (ExtLedgerCfg cfg)
565+ (apForMode ledgerAppMode blk)
566+ frk
567+ noBlockResolution
554568 case result of
555569 Right newLedger -> do
556570 LedgerDB. forkerPush frk newLedger
@@ -566,7 +580,8 @@ storeLedgerStateAt slotNo ledgerAppMode env = do
566580 when (blockSlot blk >= slotNo) storeLedgerState
567581 return (continue blk, () )
568582 Left err -> do
569- traceWith tracer $ LedgerErrorEvent (blockPoint blk) err
583+ traceWith tracer $
584+ LedgerErrorEvent (blockPoint blk) (LedgerDB. annLedgerErr err)
570585 storeLedgerState
571586 pure (Stop , () )
572587 )
@@ -612,6 +627,7 @@ checkNoThunksEvery ::
612627 ( HasAnalysis blk
613628 , LedgerSupportsProtocol blk
614629 , ResolveLeiosBlock blk
630+ , HasLeiosVoting blk
615631 , CanStowLedgerTables (LedgerState blk )
616632 ) =>
617633 Word64 ->
@@ -663,6 +679,7 @@ traceLedgerProcessing ::
663679 ( HasAnalysis blk
664680 , LedgerSupportsProtocol blk
665681 , ResolveLeiosBlock blk
682+ , HasLeiosVoting blk
666683 ) =>
667684 Analysis blk StartFromLedgerState
668685traceLedgerProcessing
@@ -711,6 +728,7 @@ benchmarkLedgerOps ::
711728 ( LedgerSupportsProtocol blk
712729 , HasAnalysis blk
713730 , ResolveLeiosBlock blk
731+ , HasLeiosVoting blk
714732 ) =>
715733 Maybe FilePath ->
716734 LedgerApplicationMode ->
@@ -760,6 +778,22 @@ benchmarkLedgerOps mOutfile ledgerAppMode AnalysisEnv{db, registry, startFrom, c
760778 ) <-
761779 LedgerDB. withTipForker ledgerDB $ \ frk -> do
762780 st <- IOLike. atomically $ LedgerDB. forkerGetLedgerState frk
781+ -- Verify the certificate before the EB it names is read, which is where
782+ -- 'LedgerDB.applyBlock' verifies it. The closure below applies without
783+ -- validation, so this is the only check its txs ever get.
784+ --
785+ -- The check runs inside the RTS-stats window, so its cost lands in
786+ -- 'DP.totalTime' and 'DP.mut'. It has no column of its own.
787+ case ledgerAppMode of
788+ LedgerReapply -> pure ()
789+ LedgerApply -> case verifyCertRb st blk of
790+ Left err ->
791+ fail $
792+ " benchmark doesn't support invalid certificates: "
793+ <> show rp
794+ <> " "
795+ <> show err
796+ Right () -> pure ()
763797 -- A cert-RB has an empty body. It applies the txs of the EB that its
764798 -- parent announced. Read those txs from the LeiosDb. A block that
765799 -- certifies no EB skips the read, so its EB figures stay 0. A 'clock'
@@ -928,6 +962,7 @@ getBlockApplicationMetrics ::
928962 ( HasAnalysis blk
929963 , LedgerSupportsProtocol blk
930964 , ResolveLeiosBlock blk
965+ , HasLeiosVoting blk
931966 ) =>
932967 NumberOfBlocks -> Maybe FilePath -> Analysis blk StartFromLedgerState
933968getBlockApplicationMetrics (NumberOfBlocks nrBlocks) mOutFile env = do
@@ -983,6 +1018,7 @@ reproMempoolForge ::
9831018 , LedgerSupportsMempool blk
9841019 , LedgerSupportsProtocol blk
9851020 , ResolveLeiosBlock blk
1021+ , HasLeiosVoting blk
9861022 ) =>
9871023 Int ->
9881024 Analysis blk StartFromLedgerState
@@ -1249,6 +1285,44 @@ parentAnnouncement ::
12491285parentAnnouncement =
12501286 protocolStateLeiosAnnouncement @ blk . headerStateChainDep . headerState
12511287
1288+ -- | Verify the Leios certificate of a cert-RB against the committee of the
1289+ -- parent ledger state. 'Right ()' for a block that carries no certificate.
1290+ --
1291+ -- This repeats what 'LedgerDB.applyBlock' does on its 'LedgerDB.ApplyVal' path,
1292+ -- and it returns the same four rejection reasons. An analysis that calls
1293+ -- 'LedgerDB.applyBlock' gets the check from there and must not call this.
1294+ -- 'benchmarkLedgerOps' times each phase of block application on its own, so it
1295+ -- cannot call 'LedgerDB.applyBlock', and it calls this instead.
1296+ --
1297+ -- The check matters because 'applyLeiosClosure' applies the txs of the EB
1298+ -- without validation: no signatures, no scripts, no balances.
1299+ verifyCertRb ::
1300+ forall blk .
1301+ ( ResolveLeiosBlock blk
1302+ , HasLeiosVoting blk
1303+ ) =>
1304+ -- | The unticked parent state
1305+ ExtLedgerState blk EmptyMK ->
1306+ blk ->
1307+ Either LeiosExtValidationError ()
1308+ verifyCertRb parent blk = case blockLeiosCert blk of
1309+ Nothing -> Right ()
1310+ Just cert -> case parentAnnouncement parent of
1311+ -- A cert-RB certifies the EB that its predecessor announced. If the parent
1312+ -- announced none, there is nothing to certify.
1313+ Nothing -> Left (LeiosCertificateWithoutAnnouncement cert)
1314+ Just (announcedPoint, _size) -> case getLeiosCommittee (ledgerState parent) of
1315+ -- A cert-RB in an era with no Leios committee is a protocol violation.
1316+ Nothing -> Left (LeiosMissingCommittee announcedPoint cert)
1317+ Just committee -> case announcingRbHash blk of
1318+ -- A cert-RB always has a non-genesis announcing parent.
1319+ Nothing -> Left (LeiosCertificateAfterGenesis cert announcedPoint)
1320+ Just rbHash ->
1321+ case verifyLeiosCert committee minCertificationThreshold rbHash cert of
1322+ Left invalid ->
1323+ Left (LeiosInvalidCertificate cert announcedPoint rbHash invalid)
1324+ Right _weight -> Right ()
1325+
12521326-- | The EB that this block certifies. 'Nothing' for a block that carries no
12531327-- Leios certificate.
12541328certifiedEbHash ::
@@ -1394,66 +1468,31 @@ applyClosure lcfg closureTxs parent tables =
13941468 where
13951469 stateBeforeEb = ledgerState parent `ltwith` castLedgerTables tables
13961470
1397- -- | Apply one block against the tip forker. For a CertRB, fold the EB closure
1398- -- its parent announced onto the ledger state before applying the (empty) CertRB,
1399- -- as 'Forker.applyBlock' does; other blocks apply as before.
1400- applyBlockLeios ::
1401- forall blk .
1402- ( LedgerSupportsProtocol blk
1403- , ResolveLeiosBlock blk
1404- ) =>
1405- LeiosDbConnection IO ->
1406- LedgerApplicationMode ->
1407- ComputeLedgerEvents ->
1408- TopLevelConfig blk ->
1409- Forker' IO blk ->
1410- -- | Parent tip
1411- ExtLedgerState blk EmptyMK ->
1412- blk ->
1413- IO (Either (ExtValidationError blk ) (ExtLedgerState blk DiffMK ))
1414- applyBlockLeios leiosConn mode evs cfg frk parent blk =
1415- case blockLeiosCert blk of
1416- Nothing -> do
1417- -- Ordinary block: read its inputs, apply its body.
1418- values <- LedgerDB. forkerReadTables frk (getBlockKeySets blk)
1419- pure $ applyInMode (parent `withLedgerTables` values)
1420- Just {} ->
1421- case parentAnnouncement parent of
1422- Nothing ->
1423- -- A CertRB's parent always announced an EB; its absence is a bug.
1424- error " applyBlockLeios: CertRB whose parent announced no EB"
1425- Just (announcedPoint, _size) -> do
1426- res <-
1427- resolveAndApplyLeiosClosure
1428- leiosConn
1429- (configLedger cfg)
1430- (pointEbHash announcedPoint)
1431- (fmap castLedgerTables . LedgerDB. forkerReadTables frk . castLedgerTables)
1432- (castLedgerTables (getBlockKeySets blk :: LedgerTables (ExtLedgerState blk ) KeysMK )) -- the RB body's own input keys
1433- (ledgerState parent)
1434- pure $ case res of
1435- Left lerr ->
1436- Left (ExtValidationErrorLedger lerr)
1437- Right LeiosClosureApplied {lcaStateAfterEB, lcaClosureDiff} ->
1438- -- Apply the CertRB (empty body) on the post-EB state, then prepend
1439- -- the closure diff so the pushed diff covers both.
1440- prependDiffs lcaClosureDiff
1441- <$> applyInMode (parent{ledgerState = lcaStateAfterEB})
1442- where
1443- -- Apply 'blk' to the given ledger state, reapplying or fully applying per 'mode'.
1444- applyInMode ::
1445- ExtLedgerState blk ValuesMK ->
1446- Either (ExtValidationError blk ) (ExtLedgerState blk DiffMK )
1447- applyInMode st = case mode of
1448- LedgerReapply -> Right (tickThenReapply evs (ExtLedgerCfg cfg) blk st)
1449- LedgerApply -> runExcept (tickThenApply evs (ExtLedgerCfg cfg) blk st)
1450-
1451- -- | Read the ledger state at the tip (with the UTxOs this block consumes) and
1452- -- apply the block to it via 'applyBlockLeios'. Fails loudly on any error: an
1453- -- invalid block, or an EB closure that is missing or won't apply.
1471+ -- | The 'Ap' that a 'LedgerApplicationMode' selects.
1472+ --
1473+ -- The difference is not only the cost. On 'LedgerApply' the node verifies the
1474+ -- Leios certificate of a cert-RB, and on 'LedgerReapply' it does not. See
1475+ -- 'verifyCertRb'.
1476+ apForMode :: LedgerApplicationMode -> blk -> LedgerDB. Ap IO (ExtLedgerState blk ) blk
1477+ apForMode = \ case
1478+ LedgerApply -> LedgerDB. ApplyVal
1479+ LedgerReapply -> LedgerDB. ReapplyVal
1480+
1481+ -- | 'LedgerDB.applyBlock' resolves a block only for its @*Ref@ constructors, and
1482+ -- every caller here passes @*Val@. So no analysis ever reaches this.
1483+ noBlockResolution :: LedgerDB. ResolveBlock IO blk
1484+ noBlockResolution _ =
1485+ error " db-analyser: applyBlock asked to resolve a block, but every Ap is a *Val"
1486+
1487+ -- | Read the ledger state at the tip (with the UTxOs this block
1488+ -- consumes) and apply the block to it via the node's own
1489+ -- 'LedgerDB.applyBlock'. Fails on any error: an invalid block, an
1490+ -- invalid Leios certificate, or an EB closure that is missing or
1491+ -- won't apply.
14541492applyBlockAtTip ::
14551493 ( LedgerSupportsProtocol blk
14561494 , ResolveLeiosBlock blk
1495+ , HasLeiosVoting blk
14571496 ) =>
14581497 LeiosDbConnection IO ->
14591498 LedgerApplicationMode ->
@@ -1467,8 +1506,14 @@ applyBlockAtTip leiosConn mode cfg ldb blk =
14671506 oldLedgerTbs <- LedgerDB. forkerReadTables frk (getBlockKeySets blk)
14681507 let preState = oldLedgerSt `withLedgerTables` oldLedgerTbs
14691508 applied <-
1470- either (error . show ) id
1471- <$> applyBlockLeios leiosConn mode OmitLedgerEvents cfg frk oldLedgerSt blk
1509+ either (error . show . LedgerDB. annLedgerErr) id
1510+ <$> LedgerDB. applyBlock
1511+ leiosConn
1512+ OmitLedgerEvents
1513+ (ExtLedgerCfg cfg)
1514+ (apForMode mode blk)
1515+ frk
1516+ noBlockResolution
14721517 pure (preState, applied)
14731518
14741519{- ------------------------------------------------------------------------------
0 commit comments