Skip to content

Commit 2f0571e

Browse files
Expose over-the-wire encoded transaction size (#1211)
# Description This change introduces a new method wireSizeTx for the LedgerSupportsMempool class. It provides actual CBOR encoded transaction size as it is when transmitted over the network, which the difffusion layer could exploit. Also note that: - New code should be properly tested (even if it does not add new features). - The fix for a regression should include a test that reproduces said regression. IntersectMBO/cardano-ledger#4521 IntersectMBO/ouroboros-network#4926
2 parents 35adef5 + 8abf303 commit 2f0571e

File tree

18 files changed

+106
-9
lines changed

18 files changed

+106
-9
lines changed

cabal.project

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ if impl(ghc >= 9.10)
5959
source-repository-package
6060
type: git
6161
location: https://github.com/IntersectMBO/ouroboros-network
62-
tag: d900a38c55e02f5eed8c8d6d6a4671cd8c5acc6a
63-
--sha256: sha256-VVccbWFmd9GlL2N/xNsKtXg2U2asGc4fIX1lLEo+Ar8=
62+
tag: 388cc6906b83f41ac2da192b1fd89ab986b4af74
63+
--sha256: sha256-LUwryrP5jK+/c4lDitJf/oKg/DqLgbIc68bn83FsHI0=
6464
subdir:
6565
cardano-client
6666
cardano-ping
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!--
2+
A new scriv changelog fragment.
3+
4+
Uncomment the section that is right (remove the HTML comment wrapper).
5+
-->
6+
7+
<!--
8+
### Patch
9+
10+
- A bullet item for the Patch category.
11+
12+
-->
13+
<!--
14+
### Non-Breaking
15+
16+
- A bullet item for the Non-Breaking category.
17+
18+
-->
19+
### Breaking
20+
21+
- Implement txWireSize of TxLimits instantiations for Byron and Shelley

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

+6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import Ouroboros.Consensus.Ledger.Abstract
7373
import Ouroboros.Consensus.Ledger.SupportsMempool
7474
import Ouroboros.Consensus.Util (ShowProxy (..))
7575
import Ouroboros.Consensus.Util.Condense
76+
import Ouroboros.Network.SizeInBytes as Network
7677

7778
{-------------------------------------------------------------------------------
7879
Transactions
@@ -127,6 +128,11 @@ instance LedgerSupportsMempool ByronBlock where
127128
instance TxLimits ByronBlock where
128129
type TxMeasure ByronBlock = IgnoringOverflow ByteSize32
129130

131+
txWireSize = fromIntegral
132+
. Strict.length
133+
. CC.mempoolPayloadRecoverBytes
134+
. toMempoolPayload
135+
130136
blockCapacityTxMeasure _cfg st =
131137
IgnoringOverflow
132138
$ ByteSize32

ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Ledger/Mempool.hs

+9-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ module Ouroboros.Consensus.Shelley.Ledger.Mempool (
3939
import qualified Cardano.Crypto.Hash as Hash
4040
import qualified Cardano.Ledger.Allegra.Rules as AllegraEra
4141
import Cardano.Ledger.Alonzo.Core (Tx, TxSeq, bodyTxL, eraProtVerLow,
42-
fromTxSeq, ppMaxBBSizeL, ppMaxBlockExUnitsL, sizeTxF)
42+
fromTxSeq, ppMaxBBSizeL, ppMaxBlockExUnitsL, sizeTxF, wireSizeTxF)
4343
import qualified Cardano.Ledger.Alonzo.Rules as AlonzoEra
4444
import Cardano.Ledger.Alonzo.Scripts (ExUnits, ExUnits',
4545
pointWiseExUnits, unWrapExUnits)
@@ -146,6 +146,8 @@ instance (ShelleyCompatible proto era, TxLimits (ShelleyBlock proto era))
146146

147147
reapplyTx = reapplyShelleyTx
148148

149+
wireTxSize (ShelleyTx _ tx) = fromIntegral $ tx ^. wireSizeTxF
150+
149151
txForgetValidated (ShelleyValidatedTx txid vtx) = ShelleyTx txid (SL.extractTx vtx)
150152

151153
mkShelleyTx :: forall era proto. ShelleyBasedEra era => Tx era -> GenTx (ShelleyBlock proto era)
@@ -385,16 +387,19 @@ instance MaxTxSizeUTxO (ConwayEra c) where
385387

386388
instance ShelleyCompatible p (ShelleyEra c) => TxLimits (ShelleyBlock p (ShelleyEra c)) where
387389
type TxMeasure (ShelleyBlock p (ShelleyEra c)) = IgnoringOverflow ByteSize32
390+
txWireSize (ShelleyTx _ tx) = fromIntegral (tx ^. wireSizeTxF)
388391
txMeasure _cfg st tx = runValidation $ txInBlockSize st tx
389392
blockCapacityTxMeasure _cfg = txsMaxBytes
390393

391394
instance ShelleyCompatible p (AllegraEra c) => TxLimits (ShelleyBlock p (AllegraEra c)) where
392395
type TxMeasure (ShelleyBlock p (AllegraEra c)) = IgnoringOverflow ByteSize32
396+
txWireSize (ShelleyTx _ tx) = fromIntegral (tx ^. wireSizeTxF)
393397
txMeasure _cfg st tx = runValidation $ txInBlockSize st tx
394398
blockCapacityTxMeasure _cfg = txsMaxBytes
395399

396400
instance ShelleyCompatible p (MaryEra c) => TxLimits (ShelleyBlock p (MaryEra c)) where
397401
type TxMeasure (ShelleyBlock p (MaryEra c)) = IgnoringOverflow ByteSize32
402+
txWireSize (ShelleyTx _ tx) = fromIntegral (tx ^. wireSizeTxF)
398403
txMeasure _cfg st tx = runValidation $ txInBlockSize st tx
399404
blockCapacityTxMeasure _cfg = txsMaxBytes
400405

@@ -485,6 +490,7 @@ instance ( ShelleyCompatible p (AlonzoEra c)
485490
) => TxLimits (ShelleyBlock p (AlonzoEra c)) where
486491

487492
type TxMeasure (ShelleyBlock p (AlonzoEra c)) = AlonzoMeasure
493+
txWireSize (ShelleyTx _ tx) = fromIntegral (tx ^. wireSizeTxF)
488494
txMeasure _cfg st tx = runValidation $ txMeasureAlonzo st tx
489495
blockCapacityTxMeasure _cfg = blockCapacityAlonzoMeasure
490496

@@ -582,12 +588,14 @@ instance ( ShelleyCompatible p (BabbageEra c)
582588
) => TxLimits (ShelleyBlock p (BabbageEra c)) where
583589

584590
type TxMeasure (ShelleyBlock p (BabbageEra c)) = ConwayMeasure
591+
txWireSize (ShelleyTx _ tx) = fromIntegral (tx ^. wireSizeTxF)
585592
txMeasure _cfg st tx = runValidation $ txMeasureBabbage st tx
586593
blockCapacityTxMeasure _cfg = blockCapacityConwayMeasure
587594

588595
instance ( ShelleyCompatible p (ConwayEra c)
589596
) => TxLimits (ShelleyBlock p (ConwayEra c)) where
590597

591598
type TxMeasure (ShelleyBlock p (ConwayEra c)) = ConwayMeasure
599+
txWireSize (ShelleyTx _ tx) = fromIntegral (tx ^. wireSizeTxF)
592600
txMeasure _cfg st tx = runValidation $ txMeasureConway st tx
593601
blockCapacityTxMeasure _cfg = blockCapacityConwayMeasure

ouroboros-consensus-cardano/src/unstable-byronspec/Ouroboros/Consensus/ByronSpec/Ledger/Mempool.hs

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ instance TxLimits ByronSpecBlock where
5757
type TxMeasure ByronSpecBlock = IgnoringOverflow ByteSize32
5858

5959
-- Dummy values, as these are not used in practice.
60+
txWireSize = const . fromIntegral $ (0 :: Int)
6061
blockCapacityTxMeasure _cfg _st = IgnoringOverflow $ ByteSize32 1
6162

6263
txMeasure _cfg _st _tx = pure $ IgnoringOverflow $ ByteSize32 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!--
2+
A new scriv changelog fragment.
3+
4+
Uncomment the section that is right (remove the HTML comment wrapper).
5+
-->
6+
7+
<!--
8+
### Patch
9+
10+
- A bullet item for the Patch category.
11+
12+
-->
13+
14+
### Non-Breaking
15+
16+
- Provide txWireSize to tx-submission protocol
17+
18+
<!--
19+
### Breaking
20+
21+
- A bullet item for the Breaking category.
22+
23+
-->

ouroboros-consensus-diffusion/ouroboros-consensus-diffusion.cabal

-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ library
9999
serialise ^>=0.2,
100100
si-timers ^>=1.5,
101101
strict-stm ^>=1.5,
102-
strict-mvar ^>=1.5,
103102
text,
104103
time,
105104
transformers,

ouroboros-consensus-diffusion/src/ouroboros-consensus-diffusion/Ouroboros/Consensus/Network/NodeToNode.hs

+1
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,7 @@ mkApps kernel Tracers {..} mkCodecs ByteLimits {..} genChainSyncTimeout lopBucke
748748
(getSharedTxStateVar kernel)
749749
(mapTxSubmissionMempoolReader txForgetValidated
750750
$ getMempoolReader (getMempool kernel))
751+
txWireSize
751752
them $ \api ->
752753
runServer (newTxSubmissionServer api)
753754

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

+3-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ module Ouroboros.Consensus.NodeKernel (
2727
) where
2828

2929

30-
import qualified Control.Concurrent.Class.MonadMVar.Strict as StrictSTM
3130
import qualified Control.Concurrent.Class.MonadSTM as LazySTM
3231
import qualified Control.Concurrent.Class.MonadSTM.Strict as StrictSTM
3332
import Control.DeepSeq (force)
@@ -43,7 +42,6 @@ import Data.Functor ((<&>))
4342
import Data.Hashable (Hashable)
4443
import Data.List.NonEmpty (NonEmpty)
4544
import Data.Map.Strict (Map)
46-
import qualified Data.Map.Strict as Map
4745
import Data.Maybe (isJust, mapMaybe)
4846
import Data.Proxy
4947
import qualified Data.Text as Text
@@ -114,8 +112,8 @@ import Ouroboros.Network.TxSubmission.Inbound
114112
(TxSubmissionMempoolWriter)
115113
import qualified Ouroboros.Network.TxSubmission.Inbound as Inbound
116114
import Ouroboros.Network.TxSubmission.Inbound.Registry
117-
(SharedTxStateVar, TxChannels (..), TxChannelsVar,
118-
decisionLogicThread, newSharedTxStateVar)
115+
(SharedTxStateVar, TxChannelsVar,
116+
decisionLogicThread, newSharedTxStateVar, newTxChannelsVar)
119117
import Ouroboros.Network.TxSubmission.Mempool.Reader
120118
(TxSubmissionMempoolReader)
121119
import qualified Ouroboros.Network.TxSubmission.Mempool.Reader as MempoolReader
@@ -294,7 +292,7 @@ initNodeKernel args@NodeKernelArgs { registry, cfg, tracers
294292
ps_POLICY_PEER_SHARE_STICKY_TIME
295293
ps_POLICY_PEER_SHARE_MAX_PEERS
296294

297-
txChannelsVar <- StrictSTM.newMVar (TxChannels Map.empty)
295+
txChannelsVar <- newTxChannelsVar
298296
sharedTxStateVar <- newSharedTxStateVar
299297

300298
case gnkaGetLoEFragment genesisArgs of

ouroboros-consensus-diffusion/test/consensus-test/Test/Consensus/HardFork/Combinator/A.hs

+1
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ instance LedgerSupportsMempool BlockA where
330330

331331
instance TxLimits BlockA where
332332
type TxMeasure BlockA = IgnoringOverflow ByteSize32
333+
txWireSize = const . fromIntegral $ (0 :: Int)
333334
blockCapacityTxMeasure _cfg _st = IgnoringOverflow $ ByteSize32 $ 100 * 1024 -- arbitrary
334335
txMeasure _cfg _st _tx = pure $ IgnoringOverflow $ ByteSize32 0
335336

ouroboros-consensus-diffusion/test/consensus-test/Test/Consensus/HardFork/Combinator/B.hs

+1
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ instance LedgerSupportsMempool BlockB where
266266

267267
instance TxLimits BlockB where
268268
type TxMeasure BlockB = IgnoringOverflow ByteSize32
269+
txWireSize = const . fromIntegral $ (0 :: Int)
269270
blockCapacityTxMeasure _cfg _st = IgnoringOverflow $ ByteSize32 $ 100 * 1024 -- arbitrary
270271
txMeasure _cfg _st _tx = pure $ IgnoringOverflow $ ByteSize32 0
271272

ouroboros-consensus/bench/mempool-bench/Bench/Consensus/Mempool/TestBlock.hs

+1
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ instance Ledger.LedgerSupportsMempool TestBlock where
151151
instance Ledger.TxLimits TestBlock where
152152
type TxMeasure TestBlock = Ledger.IgnoringOverflow Ledger.ByteSize32
153153

154+
txWireSize = fromIntegral . Ledger.unByteSize32 . txSize
154155
-- We tweaked this in such a way that we test the case in which we exceed the
155156
-- maximum mempool capacity. The value used here depends on 'txInBlockSize'.
156157
blockCapacityTxMeasure _cfg _st =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!--
2+
A new scriv changelog fragment.
3+
4+
Uncomment the section that is right (remove the HTML comment wrapper).
5+
-->
6+
7+
<!--
8+
### Patch
9+
10+
- A bullet item for the Patch category.
11+
12+
-->
13+
<!--
14+
### Non-Breaking
15+
16+
- A bullet item for the Non-Breaking category.
17+
18+
-->
19+
### Breaking
20+
21+
- Added txWireSize method to TxLimits class to provide
22+
a CBOR-encoded transaction size as it is when transmitted
23+
over the network.

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/HardFork/Combinator/Mempool.hs

+6
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ instance CanHardFork xs => LedgerSupportsMempool (HardForkBlock xs) where
119119
instance CanHardFork xs => TxLimits (HardForkBlock xs) where
120120
type TxMeasure (HardForkBlock xs) = HardForkTxMeasure xs
121121

122+
txWireSize =
123+
hcollapse
124+
. hcmap proxySingle (K . txWireSize)
125+
. getOneEraGenTx
126+
. getHardForkGenTx
127+
122128
blockCapacityTxMeasure
123129
HardForkLedgerConfig{..}
124130
(TickedHardForkLedgerState transition hardForkState)

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Ledger/Dual.hs

+1
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ instance Bridge m a => LedgerSupportsMempool (DualBlock m a) where
625625
instance Bridge m a => TxLimits (DualBlock m a) where
626626
type TxMeasure (DualBlock m a) = TxMeasure m
627627

628+
txWireSize = txWireSize . dualGenTxMain
628629
txMeasure DualLedgerConfig{..} TickedDualLedgerState{..} DualGenTx{..} = do
629630
mapExcept (inj +++ id)
630631
$ txMeasure dualLedgerConfigMain tickedDualLedgerStateMain dualGenTxMain

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Ledger/SupportsMempool.hs

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import NoThunks.Class
3737
import Ouroboros.Consensus.Block.Abstract
3838
import Ouroboros.Consensus.Ledger.Abstract
3939
import Ouroboros.Consensus.Ticked
40+
import Ouroboros.Network.SizeInBytes as Network
4041

4142
-- | Generalized transaction
4243
--
@@ -179,6 +180,10 @@ class ( Measure (TxMeasure blk)
179180
-- | The (possibly multi-dimensional) size of a transaction in a block.
180181
type TxMeasure blk
181182

183+
-- | The size of the transaction from the perspective of diffusion layer
184+
--
185+
txWireSize :: GenTx blk -> Network.SizeInBytes
186+
182187
-- | The various sizes (bytes, Plutus script ExUnits, etc) of a tx /when it's
183188
-- in a block/
184189
--

ouroboros-consensus/src/unstable-mock-block/Ouroboros/Consensus/Mock/Ledger/Block.hs

+1
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ instance MockProtocolSpecific c ext
438438
instance TxLimits (SimpleBlock c ext) where
439439
type TxMeasure (SimpleBlock c ext) = IgnoringOverflow ByteSize32
440440

441+
txWireSize = fromIntegral . unByteSize32 . txSize
441442
-- Large value so that the Mempool tests never run out of capacity when they
442443
-- don't override it.
443444
--

ouroboros-consensus/test/consensus-test/Test/Consensus/Mempool/Fairness/TestBlock.hs

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ instance Ledger.LedgerSupportsMempool TestBlock where
9191
instance Ledger.TxLimits TestBlock where
9292
type TxMeasure TestBlock = Ledger.IgnoringOverflow Ledger.ByteSize32
9393

94+
txWireSize = fromIntegral . Ledger.unByteSize32 . txSize . unGenTx
9495
blockCapacityTxMeasure _cfg _st =
9596
-- The tests will override this value. By using 1, @computeMempoolCapacity@
9697
-- can be exactly what each test requests.

0 commit comments

Comments
 (0)