2525module Cardano.Ledger.Alonzo.TxSeq.Internal (
2626 AlonzoTxSeq (.. , AlonzoTxSeq ),
2727 hashAlonzoTxSeq ,
28+ hashAlonzoSegWits ,
2829 alignedValidFlags ,
2930) where
3031
@@ -47,7 +48,7 @@ import Cardano.Ledger.Core
4748import Cardano.Ledger.Shelley.BlockChain (auxDataSeqDecoder )
4849import Control.Monad (unless )
4950import Data.ByteString (ByteString )
50- import Data.ByteString.Builder (shortByteString , toLazyByteString )
51+ import Data.ByteString.Builder (Builder , shortByteString , toLazyByteString )
5152import qualified Data.ByteString.Lazy as BSL
5253import Data.Coerce (coerce )
5354import Data.Maybe.Strict (maybeToStrictMaybe , strictMaybeToMaybe )
@@ -72,12 +73,14 @@ import NoThunks.Class (AllowThunksIn (..), NoThunks)
7273
7374data AlonzoTxSeq era = AlonzoTxSeqRaw
7475 { txSeqTxns :: ! (StrictSeq (Tx era ))
76+ , txSeqHash :: Hash. Hash HASH EraIndependentBlockBody
77+ -- ^ Memoized hash to avoid recomputation. Lazy on purpose.
7578 , txSeqBodyBytes :: BSL. ByteString
76- -- ^ Bytes encoding @Seq ('AlonzoTxBody ' era)@
79+ -- ^ Bytes encoding @Seq ('TxBody ' era)@
7780 , txSeqWitsBytes :: BSL. ByteString
78- -- ^ Bytes encoding @Seq ('TxWitness ' era)@
81+ -- ^ Bytes encoding @Seq ('TxWits ' era)@
7982 , txSeqMetadataBytes :: BSL. ByteString
80- -- ^ Bytes encoding a @Map Int ('AuxiliaryData ')@. Missing indices have
83+ -- ^ Bytes encoding a @'TxAuxData ')@. Missing indices have
8184 -- 'SNothing' for metadata
8285 , txSeqIsValidBytes :: BSL. ByteString
8386 -- ^ Bytes representing a set of integers. These are the indices of
@@ -100,7 +103,7 @@ pattern AlonzoTxSeq ::
100103 StrictSeq (Tx era) ->
101104 AlonzoTxSeq era
102105pattern AlonzoTxSeq xs <-
103- AlonzoTxSeqRaw xs _ _ _ _
106+ AlonzoTxSeqRaw xs _ _ _ _ _
104107 where
105108 AlonzoTxSeq txns =
106109 let version = eraProtVerLow @ era
@@ -110,24 +113,30 @@ pattern AlonzoTxSeq xs <-
110113 metaChunk index m = encodeIndexed <$> strictMaybeToMaybe m
111114 where
112115 encodeIndexed metadata = encCBOR index <> encodePreEncoded metadata
116+ txSeqBodies =
117+ serializeFoldablePreEncoded $ originalBytes . view bodyTxL <$> txns
118+ txSeqWits =
119+ serializeFoldablePreEncoded $ originalBytes . view witsTxL <$> txns
120+ txSeqAuxDatas =
121+ serialize version . encodeFoldableMapEncoder metaChunk $
122+ fmap originalBytes . view auxDataTxL <$> txns
123+ txSeqIsValids =
124+ serialize version $ encCBOR $ nonValidatingIndices txns
113125 in AlonzoTxSeqRaw
114126 { txSeqTxns = txns
115- , txSeqBodyBytes =
116- serializeFoldablePreEncoded $ originalBytes . view bodyTxL <$> txns
117- , txSeqWitsBytes =
118- serializeFoldablePreEncoded $ originalBytes . view witsTxL <$> txns
119- , txSeqMetadataBytes =
120- serialize version . encodeFoldableMapEncoder metaChunk $
121- fmap originalBytes . view auxDataTxL <$> txns
122- , txSeqIsValidBytes =
123- serialize version $ encCBOR $ nonValidatingIndices txns
127+ , txSeqHash = hashAlonzoSegWits txSeqBodies txSeqWits txSeqAuxDatas txSeqIsValids
128+ , txSeqBodyBytes = txSeqBodies
129+ , txSeqWitsBytes = txSeqWits
130+ , txSeqMetadataBytes = txSeqAuxDatas
131+ , txSeqIsValidBytes = txSeqIsValids
124132 }
125133
126134{-# COMPLETE AlonzoTxSeq #-}
127135
128136deriving via
129137 AllowThunksIn
130- '[ " txSeqBodyBytes"
138+ '[ " txSeqHash"
139+ , " txSeqBodyBytes"
131140 , " txSeqWitsBytes"
132141 , " txSeqMetadataBytes"
133142 , " txSeqIsValidBytes"
@@ -145,7 +154,7 @@ deriving stock instance Eq (Tx era) => Eq (AlonzoTxSeq era)
145154--------------------------------------------------------------------------------
146155
147156instance Era era => EncCBORGroup (AlonzoTxSeq era ) where
148- encCBORGroup (AlonzoTxSeqRaw _ bodyBytes witsBytes metadataBytes invalidBytes) =
157+ encCBORGroup (AlonzoTxSeqRaw _ _ bodyBytes witsBytes metadataBytes invalidBytes) =
149158 encodePreEncoded $
150159 BSL. toStrict $
151160 bodyBytes <> witsBytes <> metadataBytes <> invalidBytes
@@ -162,21 +171,32 @@ hashAlonzoTxSeq ::
162171 forall era .
163172 AlonzoTxSeq era ->
164173 Hash HASH EraIndependentBlockBody
165- hashAlonzoTxSeq (AlonzoTxSeqRaw _ bodies ws md vs) =
166- coerce $
167- hashStrict $
168- BSL. toStrict $
169- toLazyByteString $
170- mconcat
171- [ hashPart bodies
172- , hashPart ws
173- , hashPart md
174- , hashPart vs
175- ]
174+ hashAlonzoTxSeq = txSeqHash
175+
176+ hashAlonzoSegWits ::
177+ BSL. ByteString ->
178+ -- | Bytes for transaction bodies
179+ BSL. ByteString ->
180+ -- | Bytes for transaction witnesses
181+ BSL. ByteString ->
182+ -- | Bytes for transaction auxiliary datas
183+ BSL. ByteString ->
184+ -- | Bytes for transaction isValid flags
185+ Hash HASH EraIndependentBlockBody
186+ hashAlonzoSegWits txSeqBodies txSeqWits txAuxData txSeqIsValids =
187+ coerce . hashLazy . toLazyByteString $
188+ hashPart txSeqBodies
189+ <> hashPart txSeqWits
190+ <> hashPart txAuxData
191+ <> hashPart txSeqIsValids
176192 where
177- hashStrict :: ByteString -> Hash HASH ByteString
178- hashStrict = Hash. hashWith id
179- hashPart = shortByteString . Hash. hashToBytesShort . hashStrict . BSL. toStrict
193+ hashLazy :: BSL. ByteString -> Hash HASH ByteString
194+ hashLazy = Hash. hashWith id . BSL. toStrict
195+ {-# INLINE hashLazy #-}
196+ hashPart :: BSL. ByteString -> Builder
197+ hashPart = shortByteString . Hash. hashToBytesShort . hashLazy
198+ {-# INLINE hashPart #-}
199+ {-# INLINE hashAlonzoSegWits #-}
180200
181201instance
182202 ( AlonzoEraTx era
@@ -198,24 +218,19 @@ instance
198218
199219 (isValIdxs, isValAnn) <- withSlice decCBOR
200220 let validFlags = alignedValidFlags bodiesLength isValIdxs
201- unless
202- (bodiesLength == witsLength)
203- ( fail $
204- " different number of transaction bodies ("
205- <> show bodiesLength
206- <> " ) and witness sets ("
207- <> show witsLength
208- <> " )"
209- )
210- unless
211- (all inRange isValIdxs)
212- ( fail
213- ( " Some IsValid index is not in the range: 0 .. "
214- ++ show (bodiesLength - 1 )
215- ++ " , "
216- ++ show isValIdxs
217- )
218- )
221+ unless (bodiesLength == witsLength) $
222+ fail $
223+ " different number of transaction bodies ("
224+ <> show bodiesLength
225+ <> " ) and witness sets ("
226+ <> show witsLength
227+ <> " )"
228+ unless (all inRange isValIdxs) $
229+ fail $
230+ " Some IsValid index is not in the range: 0 .. "
231+ ++ show (bodiesLength - 1 )
232+ ++ " , "
233+ ++ show isValIdxs
219234
220235 let txns =
221236 sequenceA $
@@ -224,6 +239,7 @@ instance
224239 pure $
225240 AlonzoTxSeqRaw
226241 <$> txns
242+ <*> (hashAlonzoSegWits <$> bodiesAnn <*> witsAnn <*> auxDataAnn <*> isValAnn)
227243 <*> bodiesAnn
228244 <*> witsAnn
229245 <*> auxDataAnn
0 commit comments