Skip to content

Commit 110505f

Browse files
committed
Memoize ShelleyTxSeq hash computation
1 parent 1691eb1 commit 110505f

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

eras/shelley/impl/src/Cardano/Ledger/Shelley/BlockChain.hs

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module Cardano.Ledger.Shelley.BlockChain (
2121
auxDataSeqDecoder,
2222
txSeqTxns,
2323
bbHash,
24+
hashShelleySegWits,
2425
bBodySize,
2526
slotToNonce,
2627
--
@@ -55,6 +56,7 @@ import Cardano.Ledger.Shelley.Tx (ShelleyTx (..))
5556
import Cardano.Ledger.Slot (SlotNo (..))
5657
import Control.Monad (unless)
5758
import Data.ByteString (ByteString)
59+
import Data.ByteString.Builder (Builder, shortByteString, toLazyByteString)
5860
import qualified Data.ByteString.Lazy as BSL
5961
import Data.Coerce (coerce)
6062
import Data.IntMap (IntMap)
@@ -72,23 +74,29 @@ import NoThunks.Class (AllowThunksIn (..), NoThunks (..))
7274

7375
data ShelleyTxSeq era = TxSeq'
7476
{ txSeqTxns' :: !(StrictSeq (ShelleyTx era))
77+
, txSeqHash :: Hash.Hash HASH EraIndependentBlockBody
78+
-- ^ Memoized hash to avoid recomputation. Lazy on purpose.
7579
, txSeqBodyBytes :: BSL.ByteString
80+
-- ^ Bytes encoding @Seq ('TxBody' era)@
7681
, txSeqWitsBytes :: BSL.ByteString
82+
-- ^ Bytes encoding @Seq ('TxWits' era)@
7783
, txSeqMetadataBytes :: BSL.ByteString
78-
-- bytes representing a (Map index metadata). Missing indices have SNothing for metadata
84+
-- ^ Bytes encoding a @Seq ('TxAuxData' era)@. Missing indices have
85+
-- 'SNothing' for metadata
7986
}
8087
deriving (Generic)
8188

8289
instance EraSegWits ShelleyEra where
8390
type TxSeq ShelleyEra = ShelleyTxSeq ShelleyEra
8491
fromTxSeq = txSeqTxns
8592
toTxSeq = ShelleyTxSeq
86-
hashTxSeq = bbHash
93+
hashTxSeq = txSeqHash
8794
numSegComponents = 3
8895

8996
deriving via
9097
AllowThunksIn
91-
'[ "txSeqBodyBytes"
98+
'[ "txSeqHash"
99+
, "txSeqBodyBytes"
92100
, "txSeqWitsBytes"
93101
, "txSeqMetadataBytes"
94102
]
@@ -131,7 +139,7 @@ pattern ShelleyTxSeq ::
131139
StrictSeq (Tx era) ->
132140
ShelleyTxSeq era
133141
pattern ShelleyTxSeq xs <-
134-
TxSeq' xs _ _ _
142+
TxSeq' xs _ _ _ _
135143
where
136144
ShelleyTxSeq txns =
137145
let version = eraProtVerLow @era
@@ -141,29 +149,32 @@ pattern ShelleyTxSeq xs <-
141149
metaChunk index m = encodePair <$> strictMaybeToMaybe m
142150
where
143151
encodePair metadata = encCBOR index <> encodePreEncoded metadata
152+
txSeqBodies = serializeFoldable $ coreBodyBytes @era <$> txns
153+
txSeqWits = serializeFoldable $ coreWitnessBytes @era <$> txns
154+
txSeqAuxDatas =
155+
serialize version . encodeFoldableMapEncoder metaChunk $ coreAuxDataBytes @era <$> txns
144156
in TxSeq'
145157
{ txSeqTxns' = txns
158+
, txSeqHash = hashShelleySegWits txSeqBodies txSeqWits txSeqAuxDatas
146159
, -- bytes encoding "Seq (TxBody era)"
147-
txSeqBodyBytes = serializeFoldable $ coreBodyBytes @era <$> txns
160+
txSeqBodyBytes = txSeqBodies
148161
, -- bytes encoding "Seq (TxWits era)"
149-
txSeqWitsBytes = serializeFoldable $ coreWitnessBytes @era <$> txns
162+
txSeqWitsBytes = txSeqWits
150163
, -- bytes encoding a "Map Int TxAuxData"
151-
txSeqMetadataBytes =
152-
serialize version . encodeFoldableMapEncoder metaChunk $
153-
coreAuxDataBytes @era <$> txns
164+
txSeqMetadataBytes = txSeqAuxDatas
154165
}
155166

156167
{-# COMPLETE ShelleyTxSeq #-}
157168

158169
txSeqTxns :: ShelleyTxSeq era -> StrictSeq (ShelleyTx era)
159-
txSeqTxns (TxSeq' ts _ _ _) = ts
170+
txSeqTxns (TxSeq' ts _ _ _ _) = ts
160171

161172
instance
162173
forall era.
163174
Era era =>
164175
EncCBORGroup (ShelleyTxSeq era)
165176
where
166-
encCBORGroup (TxSeq' _ bodyBytes witsBytes metadataBytes) =
177+
encCBORGroup (TxSeq' _ _ bodyBytes witsBytes metadataBytes) =
167178
encodePreEncoded $
168179
BSL.toStrict $
169180
bodyBytes <> witsBytes <> metadataBytes
@@ -176,17 +187,27 @@ instance
176187

177188
-- | Hash a given block body
178189
bbHash :: ShelleyTxSeq era -> Hash HASH EraIndependentBlockBody
179-
bbHash (TxSeq' _ bodies wits md) =
180-
coerce $
181-
hashStrict
182-
( hashPart bodies
183-
<> hashPart wits
184-
<> hashPart md
185-
)
190+
bbHash = txSeqHash
191+
192+
hashShelleySegWits ::
193+
BSL.ByteString ->
194+
-- | Bytes for transaction bodies
195+
BSL.ByteString ->
196+
-- | Bytes for transaction witnesses
197+
BSL.ByteString ->
198+
-- | Bytes for transaction auxiliary datas
199+
Hash HASH EraIndependentBlockBody
200+
hashShelleySegWits bodies wits md =
201+
coerce . hashLazy . toLazyByteString $
202+
hashPart bodies <> hashPart wits <> hashPart md
186203
where
187-
hashStrict :: ByteString -> Hash HASH ByteString
188-
hashStrict = Hash.hashWith id
189-
hashPart = Hash.hashToBytes . hashStrict . BSL.toStrict
204+
hashLazy :: BSL.ByteString -> Hash HASH ByteString
205+
hashLazy = Hash.hashWith id . BSL.toStrict
206+
{-# INLINE hashLazy #-}
207+
hashPart :: BSL.ByteString -> Builder
208+
hashPart = shortByteString . Hash.hashToBytesShort . hashLazy
209+
{-# INLINE hashPart #-}
210+
{-# INLINE hashShelleySegWits #-}
190211

191212
auxDataSeqDecoder ::
192213
Int -> IntMap a -> Decoder s (Seq (Maybe a))
@@ -246,7 +267,8 @@ instance
246267
sequenceA $
247268
StrictSeq.forceToStrict $
248269
Seq.zipWith3 segWitAnnTx bodies wits metadata
249-
pure $ TxSeq' <$> txns <*> bodiesAnn <*> witsAnn <*> metadataAnn
270+
hashAnn = hashShelleySegWits <$> bodiesAnn <*> witsAnn <*> metadataAnn
271+
pure $ TxSeq' <$> txns <*> hashAnn <*> bodiesAnn <*> witsAnn <*> metadataAnn
250272

251273
slotToNonce :: SlotNo -> Nonce
252274
slotToNonce (SlotNo s) = mkNonceFromNumber s

eras/shelley/impl/testlib/Test/Cardano/Ledger/Shelley/Binary/Annotator.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ instance
6666
let txs =
6767
StrictSeq.forceToStrict $
6868
Seq.zipWith3 ShelleyTx bodies wits (maybeToStrictMaybe <$> auxData)
69-
pure $ TxSeq' txs bodiesBytes witsBytes auxDataBytes
69+
hash = hashShelleySegWits bodiesBytes witsBytes auxDataBytes
70+
pure $ TxSeq' txs hash bodiesBytes witsBytes auxDataBytes
7071

7172
deriving newtype instance DecCBOR (TxBody ShelleyEra)
7273

0 commit comments

Comments
 (0)