Skip to content

Commit 6dd17cd

Browse files
committed
consensus: enforce block capacity _before_ the forging logic
Now the forging logic simply includes whatever transactions its given, which is reasonable and simpler. It's the NodeKernel logic that uses the mempool's finger tree in order to slice an appropriately-sized prefix, which is then passed to the now-dumb forging function.
1 parent 6166801 commit 6dd17cd

File tree

6 files changed

+32
-65
lines changed
  • ouroboros-consensus-cardano/src
    • byron/Ouroboros/Consensus/Byron/Ledger
    • shelley/Ouroboros/Consensus/Shelley/Ledger
  • ouroboros-consensus-diffusion/src/ouroboros-consensus-diffusion/Ouroboros/Consensus
  • ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus

6 files changed

+32
-65
lines changed

ouroboros-consensus-cardano/src/byron/Ouroboros/Consensus/Byron/Ledger/Forge.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ forgeByronBlock ::
4848
-> BlockNo -- ^ Current block number
4949
-> SlotNo -- ^ Current slot number
5050
-> TickedLedgerState ByronBlock -- ^ Current ledger
51-
-> [Validated (GenTx ByronBlock)] -- ^ Txs to consider adding in the block
51+
-> [Validated (GenTx ByronBlock)] -- ^ Txs to include
5252
-> PBftIsLeader PBftByronCrypto -- ^ Leader proof ('IsLeader')
5353
-> ByronBlock
5454
forgeByronBlock cfg = forgeRegularBlock (configBlock cfg)
@@ -123,7 +123,7 @@ forgeRegularBlock ::
123123
-> BlockNo -- ^ Current block number
124124
-> SlotNo -- ^ Current slot number
125125
-> TickedLedgerState ByronBlock -- ^ Current ledger
126-
-> [Validated (GenTx ByronBlock)] -- ^ Txs to consider adding in the block
126+
-> [Validated (GenTx ByronBlock)] -- ^ Txs to include
127127
-> PBftIsLeader PBftByronCrypto -- ^ Leader proof ('IsLeader')
128128
-> ByronBlock
129129
forgeRegularBlock cfg bno sno st txs isLeader =
@@ -141,7 +141,7 @@ forgeRegularBlock cfg bno sno st txs isLeader =
141141
foldr
142142
extendBlockPayloads
143143
initBlockPayloads
144-
$ takeLargestPrefixThatFits (byronGenesisConfig cfg) st txs
144+
txs
145145

146146
txPayload :: CC.UTxO.TxPayload
147147
txPayload = CC.UTxO.mkTxPayload (bpTxs blockPayloads)
Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{-# LANGUAGE DisambiguateRecordFields #-}
22
{-# LANGUAGE FlexibleContexts #-}
3-
{-# LANGUAGE OverloadedStrings #-}
43
{-# LANGUAGE ScopedTypeVariables #-}
54
{-# LANGUAGE TypeApplications #-}
65
{-# LANGUAGE TypeFamilies #-}
@@ -13,8 +12,6 @@ import qualified Cardano.Ledger.Shelley.API as SL (Block (..), extractTx)
1312
import qualified Cardano.Ledger.Shelley.BlockChain as SL (bBodySize)
1413
import qualified Cardano.Protocol.TPraos.BHeader as SL
1514
import Control.Exception
16-
import Control.Monad.Except
17-
import Data.List (foldl')
1815
import qualified Data.Sequence.Strict as Seq
1916
import Ouroboros.Consensus.Block
2017
import Ouroboros.Consensus.Config
@@ -31,22 +28,21 @@ import Ouroboros.Consensus.Shelley.Ledger.Mempool
3128
import Ouroboros.Consensus.Shelley.Protocol.Abstract (ProtoCrypto,
3229
ProtocolHeaderSupportsKES (configSlotsPerKESPeriod),
3330
mkHeader)
34-
import Ouroboros.Consensus.Util.Assert
3531

3632
{-------------------------------------------------------------------------------
3733
Forging
3834
-------------------------------------------------------------------------------}
3935

4036
forgeShelleyBlock ::
4137
forall m era proto.
42-
(ShelleyCompatible proto era, TxLimits (ShelleyBlock proto era), Monad m)
38+
(ShelleyCompatible proto era, Monad m)
4339
=> HotKey (EraCrypto era) m
4440
-> CanBeLeader proto
4541
-> TopLevelConfig (ShelleyBlock proto era)
4642
-> BlockNo -- ^ Current block number
4743
-> SlotNo -- ^ Current slot number
4844
-> TickedLedgerState (ShelleyBlock proto era) -- ^ Current ledger
49-
-> [Validated (GenTx (ShelleyBlock proto era))] -- ^ Txs to add in the block
45+
-> [Validated (GenTx (ShelleyBlock proto era))] -- ^ Txs to include
5046
-> IsLeader proto
5147
-> m (ShelleyBlock proto era)
5248
forgeShelleyBlock
@@ -63,17 +59,16 @@ forgeShelleyBlock
6359
let blk = mkShelleyBlock $ SL.Block hdr body
6460
return $
6561
assert (verifyBlockIntegrity (configSlotsPerKESPeriod $ configConsensus cfg) blk) $
66-
assertWithMsg bodySizeEstimate blk
62+
blk
6763
where
68-
lcfg = configLedger cfg
69-
7064
protocolVersion = shelleyProtocolVersion $ configBlock cfg
7165

7266
body =
7367
SL.toTxSeq @era
74-
. Seq.fromList
75-
. fmap extractTx
76-
$ takeLargestPrefixThatFits lcfg tickedLedger txs
68+
$ Seq.fromList
69+
$ fmap extractTx txs
70+
71+
actualBodySize = SL.bBodySize protocolVersion body
7772

7873
extractTx :: Validated (GenTx (ShelleyBlock proto era)) -> Core.Tx era
7974
extractTx (ShelleyValidatedTx _txid vtx) = SL.extractTx vtx
@@ -84,26 +79,3 @@ forgeShelleyBlock
8479
. castHash
8580
. getTipHash
8681
$ tickedLedger
87-
88-
bodySizeEstimate :: Either String ()
89-
bodySizeEstimate
90-
| actualBodySize > estimatedBodySize + fixedBlockBodyOverhead
91-
= throwError $
92-
"Actual block body size > Estimated block body size + fixedBlockBodyOverhead: "
93-
<> show actualBodySize
94-
<> " > "
95-
<> show estimatedBodySize
96-
<> " + "
97-
<> show (fixedBlockBodyOverhead :: Int)
98-
| otherwise
99-
= return ()
100-
101-
actualBodySize, estimatedBodySize :: Int
102-
actualBodySize = SL.bBodySize protocolVersion body
103-
104-
estimatedBodySize =
105-
fromIntegral . unByteSize
106-
$ foldl' (<>) mempty
107-
$ map
108-
(txMeasureByteSize . txMeasure lcfg tickedLedger . txForgetValidated)
109-
txs

ouroboros-consensus-diffusion/src/ouroboros-consensus-diffusion/Ouroboros/Consensus/NodeKernel.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,11 @@ forkBlockForging IS{..} blockForging =
514514
(ForgeInKnownSlot currentSlot tickedLedgerState)
515515
pure (mempoolHash, mempoolSlotNo, snap)
516516

517-
let txs = [ vtx | (vtx, _tno, _byteSize) <- snapshotTxs mempoolSnapshot ]
517+
let txs =
518+
snapshotTake mempoolSnapshot
519+
$ blockCapacityTxMeasure (configLedger cfg) tickedLedgerState
520+
-- NB respect the capacity of the ledger state we're extending,
521+
-- which is /not/ 'snapshotLedgerState'
518522

519523
-- force the mempool's computation before the tracer event
520524
_ <- evaluate (length txs)

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Block/Forging.hs

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ module Ouroboros.Consensus.Block.Forging (
2020
, forgeStateUpdateInfoFromUpdateInfo
2121
-- * 'UpdateInfo'
2222
, UpdateInfo (..)
23-
-- * Selecting transaction sequence prefixes
24-
, takeLargestPrefixThatFits
2523
) where
2624

2725
import Control.Tracer (Tracer, traceWith)
2826
import Data.Kind (Type)
29-
import qualified Data.Measure as Measure
3027
import Data.Text (Text)
3128
import GHC.Stack
3229
import Ouroboros.Consensus.Block.Abstract
@@ -125,11 +122,11 @@ data BlockForging m blk = BlockForging {
125122

126123
-- | Forge a block
127124
--
128-
-- The function is passed the contents of the mempool; this is a set of
129-
-- transactions that is guaranteed to be consistent with the ledger state
130-
-- (also provided as an argument) and with each other (when applied in
131-
-- order). In principle /all/ of them could be included in the block (up
132-
-- to maximum block size).
125+
-- The function is passed the prefix of the mempool that will fit within
126+
-- a valid block; this is a set of transactions that is guaranteed to be
127+
-- consistent with the ledger state (also provided as an argument) and
128+
-- with each other (when applied in order). All of them should be
129+
-- included in the forged block, since the mempool ensures they can fit.
133130
--
134131
-- NOTE: do not refer to the consensus or ledger config in the closure,
135132
-- because they might contain an @EpochInfo Identity@, which will be
@@ -143,28 +140,11 @@ data BlockForging m blk = BlockForging {
143140
-> BlockNo -- Current block number
144141
-> SlotNo -- Current slot number
145142
-> TickedLedgerState blk -- Current ledger state
146-
-> [Validated (GenTx blk)] -- Contents of the mempool
143+
-> [Validated (GenTx blk)] -- Transactions to include
147144
-> IsLeader (BlockProtocol blk) -- Proof we are leader
148145
-> m blk
149146
}
150147

151-
-- | The prefix of transactions to include in the block
152-
--
153-
-- Filters out all transactions that do not fit the maximum size of total
154-
-- transactions in a single block, which is determined by querying the ledger
155-
-- state for the current limit.
156-
takeLargestPrefixThatFits ::
157-
LedgerSupportsMempool blk
158-
=> LedgerConfig blk
159-
-> TickedLedgerState blk
160-
-> [Validated (GenTx blk)]
161-
-> [Validated (GenTx blk)]
162-
takeLargestPrefixThatFits cfg ledger txs =
163-
Measure.take toMeasure capacity txs
164-
where
165-
toMeasure = txMeasure cfg ledger . txForgetValidated
166-
capacity = blockCapacityTxMeasure cfg ledger
167-
168148
data ShouldForge blk =
169149
-- | Before check whether we are a leader in this slot, we tried to update
170150
-- our forge state ('updateForgeState'), but it failed. We will not check

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/API.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,10 @@ data MempoolSnapshot blk = MempoolSnapshot {
334334
-- number greater than the one provided.
335335
, snapshotTxsAfter :: TicketNo -> [(Validated (GenTx blk), TicketNo, ByteSize)]
336336

337+
-- | Get the greatest prefix (oldest to newest) that respects the given
338+
-- block capacity.
339+
, snapshotTake :: TxMeasure blk -> [Validated (GenTx blk)]
340+
337341
-- | Get a specific transaction from the mempool snapshot by its ticket
338342
-- number, if it exists.
339343
, snapshotLookupTx :: TicketNo -> Maybe (Validated (GenTx blk))

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Mempool/Impl/Common.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ snapshotFromIS is = MempoolSnapshot {
429429
, snapshotMempoolSize = implSnapshotGetMempoolSize is
430430
, snapshotSlotNo = isSlotNo is
431431
, snapshotLedgerState = isLedgerState is
432+
, snapshotTake = implSnapshotTake is
432433
}
433434
where
434435
implSnapshotGetTxs :: InternalState blk
@@ -441,6 +442,12 @@ snapshotFromIS is = MempoolSnapshot {
441442
implSnapshotGetTxsAfter IS{isTxs} =
442443
TxSeq.toTuples . snd . TxSeq.splitAfterTicketNo isTxs
443444

445+
implSnapshotTake :: InternalState blk
446+
-> TxMeasure blk
447+
-> [Validated (GenTx blk)]
448+
implSnapshotTake IS{isTxs} =
449+
map TxSeq.txTicketTx . TxSeq.toList . fst . TxSeq.splitAfterTxSize isTxs
450+
444451
implSnapshotGetTx :: InternalState blk
445452
-> TicketNo
446453
-> Maybe (Validated (GenTx blk))

0 commit comments

Comments
 (0)