From 43015e4401a267f72e8cfb788733e0457ae00b35 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 10 Jun 2026 20:41:20 +0200 Subject: [PATCH 01/17] Add LeiosCert to DijkstraBlockBody This depends on new package cardano-crypto-leios from cardano-base --- cabal.project | 11 +++++ .../impl/cardano-ledger-dijkstra.cabal | 4 ++ .../Ledger/Dijkstra/BlockBody/Internal.hs | 48 +++++++++++++------ .../Test/Cardano/Ledger/Dijkstra/Arbitrary.hs | 24 ++++++++-- .../Ledger/Dijkstra/Binary/Annotator.hs | 6 ++- .../Test/Cardano/Ledger/Dijkstra/TreeDiff.hs | 12 +++++ 6 files changed, 86 insertions(+), 19 deletions(-) diff --git a/cabal.project b/cabal.project index 66401f165f0..9a25066fbad 100644 --- a/cabal.project +++ b/cabal.project @@ -142,3 +142,14 @@ if impl(ghc >=9.14) , serialise:containers , serialise:time -- cabal-allow-newer end + +-- Points to cardano-base/ch1bo/cardano-crypto-leios +source-repository-package + type: git + location: https://github.com/IntersectMBO/cardano-base + tag: fea246668b7f788a0f092408c2526322df5ca668 + --sha256: sha256-a/3SniA8QwPO6WlHypcUUevLawYNSN2zQWXhjrPkCd8= + subdir: + cardano-base + cardano-crypto-class + cardano-crypto-leios diff --git a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal index 7f2e405cf16..caa230bc1f5 100644 --- a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal +++ b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal @@ -107,6 +107,7 @@ library bytestring, cardano-base >=0.1.4, cardano-crypto-class, + cardano-crypto-leios, cardano-data ^>=1.3, cardano-ledger-allegra, cardano-ledger-alonzo ^>=1.16, @@ -178,6 +179,8 @@ library testlib base, bytestring, cardano-base, + cardano-crypto-class, + cardano-crypto-leios:{cardano-crypto-leios, testlib}, cardano-data, cardano-ledger-allegra:{cardano-ledger-allegra, testlib}, cardano-ledger-alonzo:{cardano-ledger-alonzo, testlib}, @@ -191,6 +194,7 @@ library testlib cardano-strict-containers, containers, generic-random, + hedgehog-quickcheck, microlens, plutus-ledger-api, small-steps, diff --git a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs index 945172694b0..4393a46820e 100644 --- a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs +++ b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs @@ -7,7 +7,6 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-} -{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} @@ -38,6 +37,7 @@ module Cardano.Ledger.Dijkstra.BlockBody.Internal ( validatePerasCert, ) where +import Cardano.Crypto.Leios (LeiosCert, decodeLeiosCert, encodeLeiosCert) import Cardano.Ledger.Alonzo.Tx (AlonzoEraTx (..), IsValid (..)) import Cardano.Ledger.BaseTypes (Nonce, ProtVer (..), maybeToStrictMaybe) import Cardano.Ledger.Binary ( @@ -53,6 +53,9 @@ import Cardano.Ledger.Binary ( encCBOR, encodeListLen, encodeNullStrictMaybe, + encodeStrictMaybe, + fromPlainDecoder, + fromPlainEncoding, serialize', ) import Cardano.Ledger.Core @@ -100,12 +103,16 @@ import NoThunks.Class (NoThunks) data DijkstraBlockBodyRaw era = DijkstraBlockBodyRaw { dbbrTxs :: !(StrictSeq (Tx TopTx era)) + , dbbrLeiosCert :: !(StrictMaybe LeiosCert) + -- ^ Optional Leios certificate , dbbrPerasCert :: !(StrictMaybe PerasCert) -- ^ Optional Peras certificate } deriving (Generic) -instance (NFData (Tx TopTx era), NFData PerasCert) => NFData (DijkstraBlockBodyRaw era) +instance + (NFData (Tx TopTx era), NFData LeiosCert, NFData PerasCert) => + NFData (DijkstraBlockBodyRaw era) type instance MemoHashIndex (DijkstraBlockBodyRaw era) = EraIndependentBlockBody @@ -118,7 +125,9 @@ instance EraBlockBody DijkstraEra where blockBodySize (ProtVer v _) = BS.length . serialize' v . encCBOR mkBasicBlockBodyDijkstra :: forall era. AlonzoEraTx era => DijkstraBlockBody era -mkBasicBlockBodyDijkstra = mkMemoized (eraProtVerLow @era) $ DijkstraBlockBodyRaw mempty SNothing +mkBasicBlockBodyDijkstra = + mkMemoized (eraProtVerLow @era) $ + DijkstraBlockBodyRaw mempty SNothing SNothing {-# INLINEABLE mkBasicBlockBodyDijkstra #-} -- | Dijkstra-specific extensions to 'EraBlockBody' @@ -153,13 +162,17 @@ instance Memoized (DijkstraBlockBody era) where pattern DijkstraBlockBody :: AlonzoEraTx era => StrictSeq (Tx TopTx era) -> + StrictMaybe LeiosCert -> StrictMaybe PerasCert -> DijkstraBlockBody era -pattern DijkstraBlockBody txs perasCert <- (getMemoRawType -> DijkstraBlockBodyRaw txs perasCert) +pattern DijkstraBlockBody txs mbLeiosCert mbPerasCert <- + ( getMemoRawType -> + DijkstraBlockBodyRaw txs mbLeiosCert mbPerasCert + ) where - DijkstraBlockBody txs perasCert = + DijkstraBlockBody txs leiosCert perasCert = mkMemoizedEra @DijkstraEra $ - DijkstraBlockBodyRaw txs perasCert + DijkstraBlockBodyRaw txs leiosCert perasCert {-# COMPLETE DijkstraBlockBody #-} @@ -173,11 +186,12 @@ instance ) => EncCBOR (DijkstraBlockBodyRaw era) where - encCBOR (DijkstraBlockBodyRaw txs perasCert) = - encodeListLen 3 + encCBOR (DijkstraBlockBodyRaw txs mbLeiosCert mbPerasCert) = + encodeListLen 4 <> encodeNullStrictMaybe encCBOR invalidIndices <> encCBOR txs - <> encodeNullStrictMaybe encCBOR perasCert + <> encodeNullStrictMaybe (fromPlainEncoding . encodeLeiosCert) mbLeiosCert + <> encodeNullStrictMaybe encCBOR mbPerasCert where invalidIndices = maybeToStrictMaybe . NonEmptySet.fromFoldable $ @@ -192,7 +206,7 @@ instance ) => DecCBOR (Annotator (DijkstraBlockBodyRaw era)) where - decCBOR = decodeRecordNamed "DijkstraBlockBodyRaw" (const 3) $ do + decCBOR = decodeRecordNamed "DijkstraBlockBodyRaw" (const 4) $ do let decodeInvalidTxs = decodeNonEmptySetLikeEnforceNoDuplicates @@ -201,7 +215,8 @@ instance (decCBOR @Word16) invalidTxs :: IntSet <- fold <$> decodeNullMaybe decodeInvalidTxs txs <- decodeSeq (decodeDijkstraTopTx @era False) - perasCert <- decodeNullStrictMaybe decCBOR + mbLeiosCert <- decodeNullStrictMaybe (fromPlainDecoder decodeLeiosCert) + mbPerasCert <- decodeNullStrictMaybe decCBOR let txsLength = Seq.length txs inRange x = 0 <= x && x < txsLength forM_ (IntSet.toList invalidTxs) $ \i -> @@ -214,7 +229,8 @@ instance pure $ DijkstraBlockBodyRaw <$> sequenceA (StrictSeq.forceToStrict txsWithIsValid) - <*> pure perasCert + <*> pure mbLeiosCert + <*> pure mbPerasCert deriving via Mem (DijkstraBlockBodyRaw era) @@ -228,8 +244,12 @@ deriving via DecCBOR (Annotator (DijkstraBlockBody era)) instance (AlonzoEraTx era, EncCBOR (Tx TopTx era)) => EncCBORGroup (DijkstraBlockBody era) where - encCBORGroup (DijkstraBlockBody txs perasCert) = do - encodeListLen 2 <> encCBOR txs <> encCBOR perasCert + encCBORGroup (DijkstraBlockBody txs leiosCert perasCert) = do + -- REVIEW: Is this really 3 if the EncCBOR of the body is 4? + encodeListLen 3 + <> encCBOR txs + <> encodeStrictMaybe (fromPlainEncoding . encodeLeiosCert) leiosCert + <> encCBOR perasCert listLen _ = 1 -------------------------------------------------------------------------------- diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs index 8ddab23f929..d4036970015 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs @@ -16,12 +16,15 @@ module Test.Cardano.Ledger.Dijkstra.Arbitrary (genNonEmptyAccountBalanceIntervals, genSmallDijkstraBlockBody) where +import Cardano.Crypto.Leios ( + LeiosCert (..), + ) import Cardano.Ledger.Allegra.Scripts ( pattern RequireTimeExpire, pattern RequireTimeStart, ) import Cardano.Ledger.Alonzo.Plutus.Context (ContextError) -import Cardano.Ledger.BaseTypes (StrictMaybe) +import Cardano.Ledger.BaseTypes (StrictMaybe (..)) import qualified Cardano.Ledger.Conway.Rules as Conway import Cardano.Ledger.Dijkstra (ApplyTxError (DijkstraApplyTxError), DijkstraEra) import Cardano.Ledger.Dijkstra.BlockBody (PerasCert (..)) @@ -43,10 +46,12 @@ import qualified Data.OMap.Strict as OMap import qualified Data.Sequence.Strict as SSeq import Data.Typeable (Typeable) import Generic.Random (genericArbitraryU) +import Test.Cardano.Crypto.Leios.Gen (genLeiosCert) import Test.Cardano.Ledger.Allegra.Arbitrary (maxTimelockDepth) import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Conway.Arbitrary () import Test.Cardano.Ledger.Shelley.Arbitrary (sizedNativeScriptGens) +import Test.QuickCheck.Hedgehog (hedgehog) instance Arbitrary (DijkstraPParams Identity DijkstraEra) where arbitrary = genericArbitraryU @@ -294,6 +299,9 @@ instance instance Arbitrary PerasCert where arbitrary = PerasCert <$> arbitrary +instance Arbitrary LeiosCert where + arbitrary = hedgehog genLeiosCert + instance ( EraBlockBody era , AlonzoEraTx era @@ -302,14 +310,24 @@ instance ) => Arbitrary (DijkstraBlockBody era) where - arbitrary = DijkstraBlockBody <$> arbitrary <*> arbitrary + arbitrary = + DijkstraBlockBody + <$> arbitrary + <*> arbitrary + <*> arbitrary genSmallDijkstraBlockBody :: ( AlonzoEraTx era , Arbitrary (Tx TopTx era) ) => Gen (DijkstraBlockBody era) -genSmallDijkstraBlockBody = DijkstraBlockBody <$> genFewTxs <*> arbitrary +genSmallDijkstraBlockBody = + DijkstraBlockBody + <$> genFewTxs + -- REVIEW: What is this function used for exactly? A leios cert body would + -- be even smaller (no txs allowed and cert size ~100B). + <*> pure SNothing + <*> arbitrary where genFewTxs = sized $ \sz -> do numTxs <- diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs index 48558be1b56..de716d618ee 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs @@ -16,6 +16,7 @@ module Test.Cardano.Ledger.Dijkstra.Binary.Annotator ( ) where import Cardano.Base.Typeable (TypeName (TypeName)) +import Cardano.Crypto.Leios (decodeLeiosCert) import Cardano.Ledger.Allegra.Scripts (invalidBeforeL, invalidHereAfterL) import Cardano.Ledger.BaseTypes import Cardano.Ledger.Binary @@ -243,7 +244,8 @@ instance DecCBOR (DijkstraBlockBodyRaw DijkstraEra) where (decCBOR @Word16) invalidTxs :: IntSet <- fold <$> decodeNullMaybe decodeInvalidTxs txs <- decodeSeq (decodeDijkstraTopTx @DijkstraEra False) - perasCert <- decodeNullStrictMaybe decCBOR + mbLeiosCert <- decodeNullStrictMaybe (fromPlainDecoder decodeLeiosCert) + mbPerasCert <- decodeNullStrictMaybe decCBOR let txsLength = Seq.length txs inRange x = 0 <= x && x <= txsLength - 1 @@ -253,7 +255,7 @@ instance DecCBOR (DijkstraBlockBodyRaw DijkstraEra) where let validityFlags = alignedValidFlags txsLength invalidTxs txsWithIsValid = Seq.zipWith (set isValidTxL) validityFlags (coerce <$> txs) - pure $ DijkstraBlockBodyRaw (StrictSeq.forceToStrict txsWithIsValid) perasCert + pure $ DijkstraBlockBodyRaw (StrictSeq.forceToStrict txsWithIsValid) mbLeiosCert mbPerasCert instance DecCBOR (DijkstraBlockBody DijkstraEra) where decCBOR = MkDijkstraBlockBody <$> decodeMemoized decCBOR diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs index a7b114e709c..444d1df8a30 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs @@ -16,6 +16,8 @@ module Test.Cardano.Ledger.Dijkstra.TreeDiff ( module Test.Cardano.Ledger.Conway.TreeDiff, ) where +import Cardano.Crypto.DSIGN (rawSerialiseSigDSIGN) +import Cardano.Crypto.Leios (LeiosCert (..), bitFieldToBytes) import Cardano.Ledger.Alonzo.Plutus.Context (ContextError) import Cardano.Ledger.BaseTypes (StrictMaybe) import qualified Cardano.Ledger.Conway.Rules as Conway @@ -129,6 +131,16 @@ instance ToExpr (TxBody l DijkstraEra) instance ToExpr PerasCert +-- Manual ToExpr to avoid an orphan 'ToExpr (SigDSIGN BLS12381MinSigDSIGN)': +-- show the BLS signature as its raw byte representation. +instance ToExpr LeiosCert where + toExpr cert = + Rec "LeiosCert" $ + OMap.fromList + [ ("signers", toExpr (bitFieldToBytes $ signers cert)) + , ("aggregatedSignature", toExpr (rawSerialiseSigDSIGN $ aggregatedSignature cert)) + ] + instance ToExpr (Tx TopTx era) => ToExpr (DijkstraBlockBodyRaw era) instance (AlonzoEraTx era, ToExpr (Tx TopTx era), ToExpr PerasCert) => ToExpr (DijkstraBlockBody era) From a60e637bc02f5f20de355f0d29cea585c96cd7c3 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Tue, 16 Jun 2026 20:05:02 +0200 Subject: [PATCH 02/17] Update huddle for leios_certificate --- .../cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs b/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs index 40967440823..be5b067397d 100644 --- a/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs +++ b/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs @@ -54,6 +54,7 @@ import Cardano.Ledger.Huddle.Gen qualified as Gen import Codec.CBOR.Term (Term (..)) import Control.Monad (unless, zipWithM) import Data.Foldable (traverse_) +import Data.Function ((&)) import Data.List (nub) import Data.Maybe (mapMaybe) import Data.Proxy (Proxy (..)) @@ -958,6 +959,17 @@ instance HuddleRule "block" DijkstraEra where instance HuddleRule "peras_certificate" DijkstraEra where huddleRuleNamed pname _era = pname =.= VBytes / VNil +instance HuddleRule "leios_certificate" DijkstraEra where + huddleRuleNamed pname era = + pname + =.= arr + [ "signers" ==> VBytes & comment "bitfield" + , "aggregated_signature" ==> huddleRule @"leios_signature" era + ] + +instance HuddleRule "leios_signature" DijkstraEra where + huddleRuleNamed pname _era = pname =.= VBytes `sized` (48 :: Word64) + instance HuddleRule "invalid_transactions" DijkstraEra where huddleRuleNamed pname era = pname =.= huddleRule1 @"nonempty_set" era (huddleRule @"transaction_index" era) @@ -971,6 +983,7 @@ instance HuddleRule "block_body" DijkstraEra where =.= arr [ "invalid_transactions" ==> huddleRule @"invalid_transactions" era / VNil , "transactions" ==> arr [0 <+ a (huddleRule @"transaction" era)] + , "leios_certificate" ==> huddleRule @"leios_certificate" era , "peras_certificate" ==> huddleRule @"peras_certificate" era ] From c44d63b5e2ad2f59ee045fda370e56beaeea0d20 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 17 Jun 2026 07:40:27 +0200 Subject: [PATCH 03/17] Fix EncCBORGroup instance of DijkstraBlockBody --- .../src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs index 4393a46820e..595d13c3401 100644 --- a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs +++ b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs @@ -245,11 +245,15 @@ deriving via instance (AlonzoEraTx era, EncCBOR (Tx TopTx era)) => EncCBORGroup (DijkstraBlockBody era) where encCBORGroup (DijkstraBlockBody txs leiosCert perasCert) = do - -- REVIEW: Is this really 3 if the EncCBOR of the body is 4? - encodeListLen 3 + encodeListLen 4 + <> encodeNullStrictMaybe encCBOR invalidIndices <> encCBOR txs <> encodeStrictMaybe (fromPlainEncoding . encodeLeiosCert) leiosCert <> encCBOR perasCert + where + invalidIndices = + maybeToStrictMaybe . NonEmptySet.fromFoldable $ + StrictSeq.findIndicesL (\tx -> tx ^. isValidTxL == IsValid False) txs listLen _ = 1 -------------------------------------------------------------------------------- From b514d53441d618c5d063f691becd17e692cfca2a Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 17 Jun 2026 08:22:33 +0200 Subject: [PATCH 04/17] Add TxsRB/CertRB distinction in CDDL tests --- .../Ledger/Dijkstra/Binary/CddlSpec.hs | 8 ++++-- .../Test/Cardano/Ledger/Dijkstra/Arbitrary.hs | 27 +++++++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/eras/dijkstra/impl/test/Test/Cardano/Ledger/Dijkstra/Binary/CddlSpec.hs b/eras/dijkstra/impl/test/Test/Cardano/Ledger/Dijkstra/Binary/CddlSpec.hs index ff350cf3e24..29fe2437c3c 100644 --- a/eras/dijkstra/impl/test/Test/Cardano/Ledger/Dijkstra/Binary/CddlSpec.hs +++ b/eras/dijkstra/impl/test/Test/Cardano/Ledger/Dijkstra/Binary/CddlSpec.hs @@ -37,7 +37,8 @@ import Test.Cardano.Ledger.Core.Binary ( ) import Test.Cardano.Ledger.Dijkstra.Arbitrary ( genNonEmptyAccountBalanceIntervals, - genSmallDijkstraBlockBody, + genSmallDijkstraCertBlockBody, + genSmallDijkstraTxsBlockBody, ) import Test.Cardano.Ledger.Dijkstra.Binary.Annotator () @@ -46,7 +47,10 @@ spec = do describe "CDDL" $ do let v = eraProtVerHigh @DijkstraEra describe "Huddle" $ specWithHuddle dijkstraCDDL . noTwiddle $ do - fullAnnGenCddlSpec @(BlockBody DijkstraEra) genSmallDijkstraBlockBody v "block_body" + describe "TxsRB" $ + fullAnnGenCddlSpec @(BlockBody DijkstraEra) genSmallDijkstraTxsBlockBody v "block_body" + describe "CertRB" $ + fullAnnGenCddlSpec @(BlockBody DijkstraEra) genSmallDijkstraCertBlockBody v "block_body" fullCddlSpec @(AccountBalanceInterval DijkstraEra) v "account_balance_interval" fullGenCddlSpec @(AccountBalanceIntervals DijkstraEra) genNonEmptyAccountBalanceIntervals diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs index d4036970015..71a5185f3c6 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs @@ -14,7 +14,11 @@ {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -module Test.Cardano.Ledger.Dijkstra.Arbitrary (genNonEmptyAccountBalanceIntervals, genSmallDijkstraBlockBody) where +module Test.Cardano.Ledger.Dijkstra.Arbitrary ( + genNonEmptyAccountBalanceIntervals, + genSmallDijkstraTxsBlockBody, + genSmallDijkstraCertBlockBody, +) where import Cardano.Crypto.Leios ( LeiosCert (..), @@ -316,16 +320,17 @@ instance <*> arbitrary <*> arbitrary -genSmallDijkstraBlockBody :: +-- | Generate the "TxsRB" form of a Dijkstra block body: a few transactions are +-- present and no Leios certificate is attached. Transaction count and per-tx +-- size are kept small so the round-trip is fast under shrinking. +genSmallDijkstraTxsBlockBody :: ( AlonzoEraTx era , Arbitrary (Tx TopTx era) ) => Gen (DijkstraBlockBody era) -genSmallDijkstraBlockBody = +genSmallDijkstraTxsBlockBody = DijkstraBlockBody <$> genFewTxs - -- REVIEW: What is this function used for exactly? A leios cert body would - -- be even smaller (no txs allowed and cert size ~100B). <*> pure SNothing <*> arbitrary where @@ -337,6 +342,18 @@ genSmallDijkstraBlockBody = ] SSeq.fromList <$> vectorOf numTxs (scale (`div` numTxs) arbitrary) +-- | Generate the "CertRB" form of a Dijsktra block body: a Leios certificate is +-- present and the transaction sequence is empty (per CIP-164, a CertRB never +-- carries Dijkstra-era transactions). The Peras certificate is also omitted so +-- the wire form is minimal. +genSmallDijkstraCertBlockBody :: + AlonzoEraTx era => + Gen (DijkstraBlockBody era) +genSmallDijkstraCertBlockBody = + DijkstraBlockBody mempty + <$> (SJust <$> arbitrary) + <*> pure SNothing + deriving newtype instance Arbitrary (ApplyTxError DijkstraEra) instance Arbitrary (DijkstraMempoolPredFailure DijkstraEra) where From a24a2d69b6251d41bad96e53dbd40aabfe1bb25c Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 17 Jun 2026 09:17:21 +0200 Subject: [PATCH 05/17] Generate structurally valid leios signatures in CDDL tests --- .../impl/cardano-ledger-dijkstra.cabal | 2 ++ eras/dijkstra/impl/cddl/data/dijkstra.cddl | 12 ++++++++-- .../lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs | 22 ++++++++++++++----- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal index caa230bc1f5..7492593a4a4 100644 --- a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal +++ b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal @@ -219,11 +219,13 @@ library cddl build-depends: antigen, base, + cardano-crypto-leios:{cardano-crypto-leios, testlib}, cardano-ledger-conway:cddl, cardano-ledger-core:cddl, cardano-ledger-dijkstra, cborg, heredoc, + hedgehog-quickcheck, text, executable generate-cddl diff --git a/eras/dijkstra/impl/cddl/data/dijkstra.cddl b/eras/dijkstra/impl/cddl/data/dijkstra.cddl index d4c2b63b5af..9a44a456d41 100644 --- a/eras/dijkstra/impl/cddl/data/dijkstra.cddl +++ b/eras/dijkstra/impl/cddl/data/dijkstra.cddl @@ -97,7 +97,8 @@ major_protocol_version = 0 .. 13 block_body = [ invalid_transactions : invalid_transactions/ nil , transactions : [* transaction] - , peras_certificate : peras_certificate + , leios_certificate : leios_certificate/ nil + , peras_certificate : peras_certificate/ nil ] invalid_transactions = nonempty_set @@ -888,5 +889,12 @@ auxiliary_data_map = } ) -peras_certificate = bytes/ nil +leios_certificate = + [ signers : bytes ;bitfield + , aggregated_signature : leios_signature + ] + +leios_signature = bytes .size 48 + +peras_certificate = bytes diff --git a/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs b/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs index be5b067397d..49246bea430 100644 --- a/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs +++ b/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs @@ -32,6 +32,7 @@ module Cardano.Ledger.Dijkstra.HuddleSpec ( auxiliaryDataMapRule, ) where +import Cardano.Crypto.Leios (leiosSignatureSize, leiosSignatureToBytes) import Cardano.Ledger.Conway.HuddleSpec hiding () import Cardano.Ledger.Dijkstra (DijkstraEra) import Cardano.Ledger.Huddle.Gen ( @@ -62,6 +63,8 @@ import Data.Text () import Data.Text qualified as T import Data.Word (Word16, Word64) import Test.AntiGen (withAnnotation, (|!)) +import Test.Cardano.Crypto.Leios.Gen (genLeiosSignature) +import Test.QuickCheck.Hedgehog (hedgehog) import Text.Heredoc import Prelude hiding ((/)) @@ -957,7 +960,7 @@ instance HuddleRule "block" DijkstraEra where ] instance HuddleRule "peras_certificate" DijkstraEra where - huddleRuleNamed pname _era = pname =.= VBytes / VNil + huddleRuleNamed pname _era = pname =.= VBytes instance HuddleRule "leios_certificate" DijkstraEra where huddleRuleNamed pname era = @@ -968,7 +971,13 @@ instance HuddleRule "leios_certificate" DijkstraEra where ] instance HuddleRule "leios_signature" DijkstraEra where - huddleRuleNamed pname _era = pname =.= VBytes `sized` (48 :: Word64) + huddleRuleNamed pname _era = + withCBORGen leiosSignatureGen $ + pname =.= VBytes `sized` leiosSignatureSize + where + leiosSignatureGen = do + sig <- liftGen (hedgehog genLeiosSignature) + pure $ SingleTerm $ TBytes (leiosSignatureToBytes sig) instance HuddleRule "invalid_transactions" DijkstraEra where huddleRuleNamed pname era = pname =.= huddleRule1 @"nonempty_set" era (huddleRule @"transaction_index" era) @@ -983,8 +992,8 @@ instance HuddleRule "block_body" DijkstraEra where =.= arr [ "invalid_transactions" ==> huddleRule @"invalid_transactions" era / VNil , "transactions" ==> arr [0 <+ a (huddleRule @"transaction" era)] - , "leios_certificate" ==> huddleRule @"leios_certificate" era - , "peras_certificate" ==> huddleRule @"peras_certificate" era + , "leios_certificate" ==> huddleRule @"leios_certificate" era / VNil + , "peras_certificate" ==> huddleRule @"peras_certificate" era / VNil ] blockBodyGen :: CBORGen RuleTerm @@ -1021,8 +1030,11 @@ blockBodyGen = do then pure TNull else genArrayTerm $ TInteger . toInteger <$> invalidIxIxs txsTerm <- withAntiGen (withAnnotation "transactions") $ genArrayTerm txs + -- NOTE: This would not be a valid block because txs are not allowed when a + -- leios cert is also included + leiosCertTerm <- generateFromName "leios_certificate" perasCertTerm <- generateFromName "peras_certificate" - SingleTerm <$> genArrayTerm [invalidTxIxsTerm, txsTerm, perasCertTerm] + SingleTerm <$> genArrayTerm [invalidTxIxsTerm, txsTerm, leiosCertTerm, perasCertTerm] instance HuddleRule "auxiliary_scripts" DijkstraEra where huddleRuleNamed = auxiliaryScriptsRule From 3bbb6ac541d8a8dd0da829e05db3064d4d1fc6c5 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 17 Jun 2026 09:17:53 +0200 Subject: [PATCH 06/17] Fix another DijkstraBlockBody decoder --- .../impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs | 2 ++ .../testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs | 2 +- .../src/Cardano/Ledger/Binary/Decoding/Decoder.hs | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs index 595d13c3401..c32e448fe78 100644 --- a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs +++ b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs @@ -213,10 +213,12 @@ instance (IntSet.insert . fromIntegral @Word16 @Int) (\x -> (IntSet.size x, x)) (decCBOR @Word16) + invalidTxs :: IntSet <- fold <$> decodeNullMaybe decodeInvalidTxs txs <- decodeSeq (decodeDijkstraTopTx @era False) mbLeiosCert <- decodeNullStrictMaybe (fromPlainDecoder decodeLeiosCert) mbPerasCert <- decodeNullStrictMaybe decCBOR + let txsLength = Seq.length txs inRange x = 0 <= x && x < txsLength forM_ (IntSet.toList invalidTxs) $ \i -> diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs index de716d618ee..4dcab699e7c 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Binary/Annotator.hs @@ -235,7 +235,7 @@ decodeDijkstraTopTx allowIsValid = pure (DijkstraTx body wits (IsValid True) aux, isValidFlagSupplied) instance DecCBOR (DijkstraBlockBodyRaw DijkstraEra) where - decCBOR = decodeRecordNamed "DijkstraBlockBodyRaw" (const 3) $ do + decCBOR = decodeRecordNamed "DijkstraBlockBodyRaw" (const 4) $ do let decodeInvalidTxs = decodeNonEmptySetLikeEnforceNoDuplicates diff --git a/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Decoding/Decoder.hs b/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Decoding/Decoder.hs index 2060f03aac5..d64cb5fca6e 100644 --- a/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Decoding/Decoder.hs +++ b/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Decoding/Decoder.hs @@ -633,6 +633,8 @@ decodeRecordNamedT :: m (Decoder s) a decodeRecordNamedT name getRecordSize decoder = decodeListLikeT name decoder $ \result n -> + -- REVIEW: Is n really the requested/expected? It's the one we decode and + -- thus n is rather the actual/found. lift $ matchSize ("Record " <> name) n (getRecordSize result) {-# INLINE decodeRecordNamedT #-} From 7541ac9a147e3d3435a4a2d85e22aa1470296731 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 17 Jun 2026 15:41:37 +0200 Subject: [PATCH 07/17] Run cabal-format --- cabal.project | 2 +- eras/dijkstra/impl/cardano-ledger-dijkstra.cabal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cabal.project b/cabal.project index 9a25066fbad..cbd365c5877 100644 --- a/cabal.project +++ b/cabal.project @@ -141,8 +141,8 @@ if impl(ghc >=9.14) , serialise:base , serialise:containers , serialise:time --- cabal-allow-newer end +-- cabal-allow-newer end -- Points to cardano-base/ch1bo/cardano-crypto-leios source-repository-package type: git diff --git a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal index 7492593a4a4..3f50f254f67 100644 --- a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal +++ b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal @@ -224,8 +224,8 @@ library cddl cardano-ledger-core:cddl, cardano-ledger-dijkstra, cborg, - heredoc, hedgehog-quickcheck, + heredoc, text, executable generate-cddl From 233bc9d98eb8451225ca1e891fe3e0e2eeb015ab Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 17 Jun 2026 15:46:09 +0200 Subject: [PATCH 08/17] Fix EncCBORGroup to also encode Nothing -> nil --- .../impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs index c32e448fe78..62c797b0b34 100644 --- a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs +++ b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs @@ -53,7 +53,6 @@ import Cardano.Ledger.Binary ( encCBOR, encodeListLen, encodeNullStrictMaybe, - encodeStrictMaybe, fromPlainDecoder, fromPlainEncoding, serialize', @@ -246,12 +245,12 @@ deriving via DecCBOR (Annotator (DijkstraBlockBody era)) instance (AlonzoEraTx era, EncCBOR (Tx TopTx era)) => EncCBORGroup (DijkstraBlockBody era) where - encCBORGroup (DijkstraBlockBody txs leiosCert perasCert) = do + encCBORGroup (DijkstraBlockBody txs mbLeiosCert mbPerasCert) = do encodeListLen 4 <> encodeNullStrictMaybe encCBOR invalidIndices <> encCBOR txs - <> encodeStrictMaybe (fromPlainEncoding . encodeLeiosCert) leiosCert - <> encCBOR perasCert + <> encodeNullStrictMaybe (fromPlainEncoding . encodeLeiosCert) mbLeiosCert + <> encodeNullStrictMaybe encCBOR mbPerasCert where invalidIndices = maybeToStrictMaybe . NonEmptySet.fromFoldable $ From fee7db885dec08bf163a313427400a3d6852e14b Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 17 Jun 2026 15:47:09 +0200 Subject: [PATCH 09/17] Fix a typo --- .../impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs index 71a5185f3c6..7614983bfad 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs @@ -342,7 +342,7 @@ genSmallDijkstraTxsBlockBody = ] SSeq.fromList <$> vectorOf numTxs (scale (`div` numTxs) arbitrary) --- | Generate the "CertRB" form of a Dijsktra block body: a Leios certificate is +-- | Generate the "CertRB" form of a Dijkstra block body: a Leios certificate is -- present and the transaction sequence is empty (per CIP-164, a CertRB never -- carries Dijkstra-era transactions). The Peras certificate is also omitted so -- the wire form is minimal. From 63b3f0573cbe6a155d0f795e4c3fe10dca7f763a Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Wed, 17 Jun 2026 16:48:31 +0200 Subject: [PATCH 10/17] Add leiosCertBlockBodyL to DijkstraEraBlockBody --- .../impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs index 62c797b0b34..0bad83eb094 100644 --- a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs +++ b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs @@ -131,10 +131,15 @@ mkBasicBlockBodyDijkstra = -- | Dijkstra-specific extensions to 'EraBlockBody' class EraBlockBody era => DijkstraEraBlockBody era where + leiosCertBlockBodyL :: Lens' (BlockBody era) (StrictMaybe LeiosCert) + -- ^ Lens to access the optional Leios certificate in the block body + perasCertBlockBodyL :: Lens' (BlockBody era) (StrictMaybe PerasCert) -- ^ Lens to access the optional Peras certificate in the block body instance DijkstraEraBlockBody DijkstraEra where + leiosCertBlockBodyL = lensMemoRawType @DijkstraEra dbbrLeiosCert (\bb c -> bb {dbbrLeiosCert = c}) + perasCertBlockBodyL = lensMemoRawType @DijkstraEra dbbrPerasCert (\bb c -> bb {dbbrPerasCert = c}) deriving instance (Typeable era, NoThunks (Tx TopTx era)) => NoThunks (DijkstraBlockBodyRaw era) From 20a7204a7b9d99c2d4f1885a3505c64be304aa6c Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Thu, 18 Jun 2026 21:42:24 +0200 Subject: [PATCH 11/17] Use byteArrayFromByteString --- libs/cardano-ledger-core/cardano-ledger-core.cabal | 2 +- .../src/Cardano/Ledger/Keys/Bootstrap.hs | 6 +++--- libs/cardano-ledger-core/src/Cardano/Ledger/Tools.hs | 4 ++-- .../test/Test/Cardano/Ledger/AddressSpec.hs | 4 ++-- .../testlib/Test/Cardano/Protocol/Crypto/VRF/Fake.hs | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libs/cardano-ledger-core/cardano-ledger-core.cabal b/libs/cardano-ledger-core/cardano-ledger-core.cabal index 9d76232ce7a..e2d82c1bf19 100644 --- a/libs/cardano-ledger-core/cardano-ledger-core.cabal +++ b/libs/cardano-ledger-core/cardano-ledger-core.cabal @@ -117,7 +117,7 @@ library base64-bytestring, binary, bytestring >=0.10 && <0.11.3 || >=0.11.4, - cardano-base >=0.1.2, + cardano-base >=0.1.6, cardano-crypto, cardano-crypto-class >=2.4 && <2.6, cardano-crypto-wrapper, diff --git a/libs/cardano-ledger-core/src/Cardano/Ledger/Keys/Bootstrap.hs b/libs/cardano-ledger-core/src/Cardano/Ledger/Keys/Bootstrap.hs index 0b80b39e6c3..b5961169e66 100644 --- a/libs/cardano-ledger-core/src/Cardano/Ledger/Keys/Bootstrap.hs +++ b/libs/cardano-ledger-core/src/Cardano/Ledger/Keys/Bootstrap.hs @@ -21,7 +21,7 @@ module Cardano.Ledger.Keys.Bootstrap ( verifyBootstrapWit, ) where -import Cardano.Base.Bytes (byteStringToByteArray) +import Cardano.Base.Bytes (byteArrayFromByteString) import qualified Cardano.Chain.Common as Byron import Cardano.Crypto.DSIGN (SignedDSIGN (..)) import qualified Cardano.Crypto.DSIGN as DSIGN @@ -156,7 +156,7 @@ unpackByronVKey -- is the correct one. (32 bytes). If the XPub was constructed correctly, -- we already know that it has this length. Nothing -> error "unpackByronVKey: impossible!" - Just vk -> (VKey vk, ChainCode $ byteStringToByteArray chainCodeBytes) + Just vk -> (VKey vk, ChainCode $ byteArrayFromByteString chainCodeBytes) verifyBootstrapWit :: Hash HASH EraIndependentTxBody -> @@ -179,7 +179,7 @@ makeBootstrapWitness :: Byron.Attributes Byron.AddrAttributes -> BootstrapWitness makeBootstrapWitness txBodyHash byronSigningKey addrAttributes = - BootstrapWitness vk signature cc $ byteStringToByteArray (serialize' addrAttributes) + BootstrapWitness vk signature cc $ byteArrayFromByteString (serialize' addrAttributes) where (vk, cc) = unpackByronVKey $ Byron.toVerification byronSigningKey signature = diff --git a/libs/cardano-ledger-core/src/Cardano/Ledger/Tools.hs b/libs/cardano-ledger-core/src/Cardano/Ledger/Tools.hs index f54d52fbd96..134c8bac6d6 100644 --- a/libs/cardano-ledger-core/src/Cardano/Ledger/Tools.hs +++ b/libs/cardano-ledger-core/src/Cardano/Ledger/Tools.hs @@ -24,7 +24,7 @@ module Cardano.Ledger.Tools ( byteStringToNum, ) where -import Cardano.Base.Bytes (byteStringToByteArray) +import Cardano.Base.Bytes (byteArrayFromByteString) import qualified Cardano.Chain.Common as Byron import Cardano.Crypto.DSIGN.Class (sigSizeDSIGN, verKeySizeDSIGN) import Cardano.Ledger.Address (BootstrapAddress (..), bootstrapKeyHash) @@ -278,7 +278,7 @@ addDummyWitsTx pp tx numKeyWits byronAttrs = Byron.Attributes Byron.AddrAttributes -> BootstrapWitness mkDummyByronKeyWit key = - BootstrapWitness key dummySig chainCode . byteStringToByteArray . serialize' byronProtVer + BootstrapWitness key dummySig chainCode . byteArrayFromByteString . serialize' byronProtVer dummyByronKeyWits = Set.fromList $ zipWith mkDummyByronKeyWit dummyKeys byronAttrs diff --git a/libs/cardano-ledger-core/test/Test/Cardano/Ledger/AddressSpec.hs b/libs/cardano-ledger-core/test/Test/Cardano/Ledger/AddressSpec.hs index e38b54cf0e0..784a38bf03f 100644 --- a/libs/cardano-ledger-core/test/Test/Cardano/Ledger/AddressSpec.hs +++ b/libs/cardano-ledger-core/test/Test/Cardano/Ledger/AddressSpec.hs @@ -10,7 +10,7 @@ module Test.Cardano.Ledger.AddressSpec (spec) where -import Cardano.Base.Bytes (byteStringToByteArray) +import Cardano.Base.Bytes (byteArrayFromByteString) import qualified Cardano.Chain.Common as Byron import qualified Cardano.Crypto.Hash.Class as Hash import Cardano.Ledger.Address @@ -68,7 +68,7 @@ spec = , bwChainCode = chainCode , bwSignature = sig , bwAttributes = - byteStringToByteArray $ serialize' byronProtVer $ Byron.addrAttributes byronAddr + byteArrayFromByteString $ serialize' byronProtVer $ Byron.addrAttributes byronAddr } pure $ coerceKeyRole (bootstrapKeyHash addr) diff --git a/libs/cardano-protocol-tpraos/testlib/Test/Cardano/Protocol/Crypto/VRF/Fake.hs b/libs/cardano-protocol-tpraos/testlib/Test/Cardano/Protocol/Crypto/VRF/Fake.hs index a05f479d8a5..394db8fda5d 100644 --- a/libs/cardano-protocol-tpraos/testlib/Test/Cardano/Protocol/Crypto/VRF/Fake.hs +++ b/libs/cardano-protocol-tpraos/testlib/Test/Cardano/Protocol/Crypto/VRF/Fake.hs @@ -19,7 +19,7 @@ module Test.Cardano.Protocol.Crypto.VRF.Fake ( WithResult (..), ) where -import Cardano.Base.Bytes (byteStringToByteArray, splitsAt) +import Cardano.Base.Bytes (byteArrayFromByteString, splitsAt) import Cardano.Crypto.Hash import Cardano.Crypto.Seed (runMonadRandomWithSeed) import Cardano.Crypto.Util @@ -79,7 +79,7 @@ instance EncCBOR a => SneakilyContainResult (WithResult a) where -- Fill in the word64 as the low 8 bytes of a 16 byte string OutputVRF (toByteArray (BS.word64BE 0 <> BS.word64BE nat)) where - toByteArray = byteStringToByteArray . LBS.toStrict . BS.toLazyByteString + toByteArray = byteArrayFromByteString . LBS.toStrict . BS.toLazyByteString unsneakilyExtractPayload (WithResult p _) = p @@ -153,7 +153,7 @@ instance VRFAlgorithm FakeVRF where | [kb, smb, xs] <- splitsAt [8, 2, 16] bs , let k = readBinaryWord64 kb , let s = readBinaryWord16 smb = - Just $! CertFakeVRF k s (OutputVRF $ byteStringToByteArray xs) + Just $! CertFakeVRF k s (OutputVRF $ byteArrayFromByteString xs) | otherwise = Nothing From 946236571a09855c4b91804f39b4504369126e8e Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Sat, 20 Jun 2026 21:55:25 +0200 Subject: [PATCH 12/17] Use quickcheck to test Leios certs --- eras/dijkstra/impl/cardano-ledger-dijkstra.cabal | 2 -- .../impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs | 3 +-- .../impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs | 3 +-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal index 3f50f254f67..9902ca41af2 100644 --- a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal +++ b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal @@ -194,7 +194,6 @@ library testlib cardano-strict-containers, containers, generic-random, - hedgehog-quickcheck, microlens, plutus-ledger-api, small-steps, @@ -224,7 +223,6 @@ library cddl cardano-ledger-core:cddl, cardano-ledger-dijkstra, cborg, - hedgehog-quickcheck, heredoc, text, diff --git a/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs b/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs index 49246bea430..753b756917c 100644 --- a/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs +++ b/eras/dijkstra/impl/cddl/lib/Cardano/Ledger/Dijkstra/HuddleSpec.hs @@ -64,7 +64,6 @@ import Data.Text qualified as T import Data.Word (Word16, Word64) import Test.AntiGen (withAnnotation, (|!)) import Test.Cardano.Crypto.Leios.Gen (genLeiosSignature) -import Test.QuickCheck.Hedgehog (hedgehog) import Text.Heredoc import Prelude hiding ((/)) @@ -976,7 +975,7 @@ instance HuddleRule "leios_signature" DijkstraEra where pname =.= VBytes `sized` leiosSignatureSize where leiosSignatureGen = do - sig <- liftGen (hedgehog genLeiosSignature) + sig <- liftGen genLeiosSignature pure $ SingleTerm $ TBytes (leiosSignatureToBytes sig) instance HuddleRule "invalid_transactions" DijkstraEra where diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs index 7614983bfad..f4740d0fbd3 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/Arbitrary.hs @@ -55,7 +55,6 @@ import Test.Cardano.Ledger.Allegra.Arbitrary (maxTimelockDepth) import Test.Cardano.Ledger.Common import Test.Cardano.Ledger.Conway.Arbitrary () import Test.Cardano.Ledger.Shelley.Arbitrary (sizedNativeScriptGens) -import Test.QuickCheck.Hedgehog (hedgehog) instance Arbitrary (DijkstraPParams Identity DijkstraEra) where arbitrary = genericArbitraryU @@ -304,7 +303,7 @@ instance Arbitrary PerasCert where arbitrary = PerasCert <$> arbitrary instance Arbitrary LeiosCert where - arbitrary = hedgehog genLeiosCert + arbitrary = genLeiosCert instance ( EraBlockBody era From 267037ad966401fe1332d45e66d24f9cbcb21b0f Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Sun, 21 Jun 2026 20:11:19 +0200 Subject: [PATCH 13/17] Add cardano-ledger-binary encoders/decoders for LeiosCert This follows the pattern of other cardano-base types. --- .../Ledger/Dijkstra/BlockBody/Internal.hs | 22 +++++++++---------- .../cardano-ledger-binary.cabal | 1 + .../src/Cardano/Ledger/Binary/Crypto.hs | 17 ++++++++++++++ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs index 0bad83eb094..4813913a601 100644 --- a/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs +++ b/eras/dijkstra/impl/src/Cardano/Ledger/Dijkstra/BlockBody/Internal.hs @@ -37,9 +37,9 @@ module Cardano.Ledger.Dijkstra.BlockBody.Internal ( validatePerasCert, ) where -import Cardano.Crypto.Leios (LeiosCert, decodeLeiosCert, encodeLeiosCert) +import Cardano.Crypto.Leios (LeiosCert) import Cardano.Ledger.Alonzo.Tx (AlonzoEraTx (..), IsValid (..)) -import Cardano.Ledger.BaseTypes (Nonce, ProtVer (..), maybeToStrictMaybe) +import Cardano.Ledger.BaseTypes (Nonce, ProtVer (..)) import Cardano.Ledger.Binary ( Annotator (..), DecCBOR (..), @@ -52,11 +52,11 @@ import Cardano.Ledger.Binary ( decodeSeq, encCBOR, encodeListLen, + encodeNullMaybe, encodeNullStrictMaybe, - fromPlainDecoder, - fromPlainEncoding, serialize', ) +import Cardano.Ledger.Binary.Crypto (decodeLeiosCert, encodeLeiosCert) import Cardano.Ledger.Core import Cardano.Ledger.Dijkstra.Era import Cardano.Ledger.Dijkstra.Tx (DijkstraTx, Tx (..), decodeDijkstraTopTx) @@ -192,13 +192,13 @@ instance where encCBOR (DijkstraBlockBodyRaw txs mbLeiosCert mbPerasCert) = encodeListLen 4 - <> encodeNullStrictMaybe encCBOR invalidIndices + <> encodeNullMaybe encCBOR invalidIndices <> encCBOR txs - <> encodeNullStrictMaybe (fromPlainEncoding . encodeLeiosCert) mbLeiosCert + <> encodeNullStrictMaybe encodeLeiosCert mbLeiosCert <> encodeNullStrictMaybe encCBOR mbPerasCert where invalidIndices = - maybeToStrictMaybe . NonEmptySet.fromFoldable $ + NonEmptySet.fromFoldable $ StrictSeq.findIndicesL (\tx -> tx ^. isValidTxL == IsValid False) txs instance @@ -220,7 +220,7 @@ instance invalidTxs :: IntSet <- fold <$> decodeNullMaybe decodeInvalidTxs txs <- decodeSeq (decodeDijkstraTopTx @era False) - mbLeiosCert <- decodeNullStrictMaybe (fromPlainDecoder decodeLeiosCert) + mbLeiosCert <- decodeNullStrictMaybe decodeLeiosCert mbPerasCert <- decodeNullStrictMaybe decCBOR let txsLength = Seq.length txs @@ -252,13 +252,13 @@ deriving via instance (AlonzoEraTx era, EncCBOR (Tx TopTx era)) => EncCBORGroup (DijkstraBlockBody era) where encCBORGroup (DijkstraBlockBody txs mbLeiosCert mbPerasCert) = do encodeListLen 4 - <> encodeNullStrictMaybe encCBOR invalidIndices + <> encodeNullMaybe encCBOR invalidIndices <> encCBOR txs - <> encodeNullStrictMaybe (fromPlainEncoding . encodeLeiosCert) mbLeiosCert + <> encodeNullStrictMaybe encodeLeiosCert mbLeiosCert <> encodeNullStrictMaybe encCBOR mbPerasCert where invalidIndices = - maybeToStrictMaybe . NonEmptySet.fromFoldable $ + NonEmptySet.fromFoldable $ StrictSeq.findIndicesL (\tx -> tx ^. isValidTxL == IsValid False) txs listLen _ = 1 diff --git a/libs/cardano-ledger-binary/cardano-ledger-binary.cabal b/libs/cardano-ledger-binary/cardano-ledger-binary.cabal index b984a451330..87b40ab0604 100644 --- a/libs/cardano-ledger-binary/cardano-ledger-binary.cabal +++ b/libs/cardano-ledger-binary/cardano-ledger-binary.cabal @@ -58,6 +58,7 @@ library cardano-base >=0.1.2, cardano-binary >=1.7.3, cardano-crypto-class >=2.3 && <2.6, + cardano-crypto-leios, cardano-crypto-praos >=2.2.2, cardano-slotting >=0.2, cardano-strict-containers >=0.1.2, diff --git a/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Crypto.hs b/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Crypto.hs index 829eb6b9a93..737051a63bd 100644 --- a/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Crypto.hs +++ b/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Crypto.hs @@ -26,10 +26,15 @@ module Cardano.Ledger.Binary.Crypto ( decodeSignKeyVRF, encodeCertVRF, decodeCertVRF, + + -- * Leios + encodeLeiosCert, + decodeLeiosCert, ) where import qualified Cardano.Crypto.DSIGN.Class as C import qualified Cardano.Crypto.KES.Class as C +import qualified Cardano.Crypto.Leios as C import qualified Cardano.Crypto.VRF.Class as C import Cardano.Ledger.Binary.Decoding.Decoder (Decoder, fromPlainDecoder) import Cardano.Ledger.Binary.Encoding.Encoder (Encoding, fromPlainEncoding) @@ -125,3 +130,15 @@ encodeCertVRF = fromPlainEncoding . C.encodeCertVRF decodeCertVRF :: C.VRFAlgorithm v => Decoder s (C.CertVRF v) decodeCertVRF = fromPlainDecoder C.decodeCertVRF {-# INLINE decodeCertVRF #-} + +-------------------------------------------------------------------------------- +-- Leios +-------------------------------------------------------------------------------- + +encodeLeiosCert :: C.LeiosCert -> Encoding +encodeLeiosCert = fromPlainEncoding . C.encodeLeiosCert +{-# INLINE encodeLeiosCert #-} + +decodeLeiosCert :: Decoder s C.LeiosCert +decodeLeiosCert = fromPlainDecoder C.decodeLeiosCert +{-# INLINE decodeLeiosCert #-} From fa38c64b99a4051af8e99da2dc209b8ff6405e58 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Sun, 21 Jun 2026 20:12:24 +0200 Subject: [PATCH 14/17] Adapt TreeDiff usage of LeiosCert to new exports Not sure if this is better, but the upstream module has a smaller API surface now. --- .../Test/Cardano/Ledger/Dijkstra/TreeDiff.hs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs index 444d1df8a30..994a48ea6be 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs @@ -5,6 +5,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} @@ -17,9 +18,10 @@ module Test.Cardano.Ledger.Dijkstra.TreeDiff ( ) where import Cardano.Crypto.DSIGN (rawSerialiseSigDSIGN) -import Cardano.Crypto.Leios (LeiosCert (..), bitFieldToBytes) +import Cardano.Crypto.Leios (LeiosCert (..), encodeBitField) import Cardano.Ledger.Alonzo.Plutus.Context (ContextError) import Cardano.Ledger.BaseTypes (StrictMaybe) +import Cardano.Ledger.Binary.Plain (serialize) import qualified Cardano.Ledger.Conway.Rules as Conway import Cardano.Ledger.Dijkstra (DijkstraEra) import Cardano.Ledger.Dijkstra.BlockBody (PerasCert) @@ -132,13 +134,15 @@ instance ToExpr (TxBody l DijkstraEra) instance ToExpr PerasCert -- Manual ToExpr to avoid an orphan 'ToExpr (SigDSIGN BLS12381MinSigDSIGN)': --- show the BLS signature as its raw byte representation. +-- show the BLS signature as its raw byte representation, and the bitfield +-- as its CBOR encoding (since the wire-format bytes aren't separately +-- observable through the public API). instance ToExpr LeiosCert where - toExpr cert = + toExpr LeiosCert {leiosCertSigners, leiosCertSignature} = Rec "LeiosCert" $ OMap.fromList - [ ("signers", toExpr (bitFieldToBytes $ signers cert)) - , ("aggregatedSignature", toExpr (rawSerialiseSigDSIGN $ aggregatedSignature cert)) + [ ("signers", toExpr (serialize (encodeBitField leiosCertSigners))) + , ("aggregatedSignature", toExpr (rawSerialiseSigDSIGN leiosCertSignature)) ] instance ToExpr (Tx TopTx era) => ToExpr (DijkstraBlockBodyRaw era) From 13636040b5c8941e0099b01235ace7836ec22aec Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Mon, 29 Jun 2026 11:13:17 +0200 Subject: [PATCH 15/17] Drop REVIEW note in Decoder --- .../src/Cardano/Ledger/Binary/Decoding/Decoder.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Decoding/Decoder.hs b/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Decoding/Decoder.hs index d64cb5fca6e..2060f03aac5 100644 --- a/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Decoding/Decoder.hs +++ b/libs/cardano-ledger-binary/src/Cardano/Ledger/Binary/Decoding/Decoder.hs @@ -633,8 +633,6 @@ decodeRecordNamedT :: m (Decoder s) a decodeRecordNamedT name getRecordSize decoder = decodeListLikeT name decoder $ \result n -> - -- REVIEW: Is n really the requested/expected? It's the one we decode and - -- thus n is rather the actual/found. lift $ matchSize ("Record " <> name) n (getRecordSize result) {-# INLINE decodeRecordNamedT #-} From 4543e086376e03fd96a589af66780489e6863ee6 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Mon, 29 Jun 2026 14:58:18 +0200 Subject: [PATCH 16/17] Use cardano-crypto-leios from CHaP --- cabal.project | 13 +------------ eras/dijkstra/impl/cardano-ledger-dijkstra.cabal | 2 +- flake.lock | 6 +++--- .../cardano-ledger-binary.cabal | 2 +- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/cabal.project b/cabal.project index cbd365c5877..0c978194598 100644 --- a/cabal.project +++ b/cabal.project @@ -28,7 +28,7 @@ source-repository-package -- see CONTRIBUTING.md#to-update-the-referenced-agda-ledger-spec index-state: , hackage.haskell.org 2026-05-26T19:31:06Z - , cardano-haskell-packages 2026-05-26T09:41:58Z + , cardano-haskell-packages 2026-06-29T12:05:19Z packages: -- == Byron era == @@ -141,15 +141,4 @@ if impl(ghc >=9.14) , serialise:base , serialise:containers , serialise:time - -- cabal-allow-newer end --- Points to cardano-base/ch1bo/cardano-crypto-leios -source-repository-package - type: git - location: https://github.com/IntersectMBO/cardano-base - tag: fea246668b7f788a0f092408c2526322df5ca668 - --sha256: sha256-a/3SniA8QwPO6WlHypcUUevLawYNSN2zQWXhjrPkCd8= - subdir: - cardano-base - cardano-crypto-class - cardano-crypto-leios diff --git a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal index 9902ca41af2..bf9119959e8 100644 --- a/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal +++ b/eras/dijkstra/impl/cardano-ledger-dijkstra.cabal @@ -107,7 +107,7 @@ library bytestring, cardano-base >=0.1.4, cardano-crypto-class, - cardano-crypto-leios, + cardano-crypto-leios >=0.1, cardano-data ^>=1.3, cardano-ledger-allegra, cardano-ledger-alonzo ^>=1.16, diff --git a/flake.lock b/flake.lock index 7b4a3e816ae..cc66bb2e70a 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "CHaP": { "flake": false, "locked": { - "lastModified": 1779802675, - "narHash": "sha256-LQN0f9GBBmYMo9tQ/11EvU5tAEOhGtQnU2UP3S78cqg=", + "lastModified": 1782738553, + "narHash": "sha256-lwXCvNoquwMkPoFZPwtxEknlEEr207VYBnm6eVRWwbo=", "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "b8c7b848cdb6d08e414c37d026c300200f8c1b5b", + "rev": "99731455c206f5f013833e50c4879ae5c3ede2eb", "type": "github" }, "original": { diff --git a/libs/cardano-ledger-binary/cardano-ledger-binary.cabal b/libs/cardano-ledger-binary/cardano-ledger-binary.cabal index 87b40ab0604..28db332df80 100644 --- a/libs/cardano-ledger-binary/cardano-ledger-binary.cabal +++ b/libs/cardano-ledger-binary/cardano-ledger-binary.cabal @@ -58,7 +58,7 @@ library cardano-base >=0.1.2, cardano-binary >=1.7.3, cardano-crypto-class >=2.3 && <2.6, - cardano-crypto-leios, + cardano-crypto-leios >=0.1, cardano-crypto-praos >=2.2.2, cardano-slotting >=0.2, cardano-strict-containers >=0.1.2, From 7b69ca5373531f53b4ce58da9f655388e3c5fb08 Mon Sep 17 00:00:00 2001 From: Sebastian Nagel Date: Mon, 29 Jun 2026 21:10:26 +0200 Subject: [PATCH 17/17] Use HexBytes in LeiosCert TreeDiff Also fix hlint issues in the module --- .../Test/Cardano/Ledger/Dijkstra/TreeDiff.hs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs index 994a48ea6be..34b4926f5c5 100644 --- a/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs +++ b/eras/dijkstra/impl/testlib/Test/Cardano/Ledger/Dijkstra/TreeDiff.hs @@ -21,7 +21,7 @@ import Cardano.Crypto.DSIGN (rawSerialiseSigDSIGN) import Cardano.Crypto.Leios (LeiosCert (..), encodeBitField) import Cardano.Ledger.Alonzo.Plutus.Context (ContextError) import Cardano.Ledger.BaseTypes (StrictMaybe) -import Cardano.Ledger.Binary.Plain (serialize) +import Cardano.Ledger.Binary.Plain (serialize') import qualified Cardano.Ledger.Conway.Rules as Conway import Cardano.Ledger.Dijkstra (DijkstraEra) import Cardano.Ledger.Dijkstra.BlockBody (PerasCert) @@ -60,7 +60,7 @@ import Control.State.Transition (STS (..)) import Data.Functor.Identity (Identity) import qualified Data.TreeDiff.OMap as OMap import Test.Cardano.Ledger.Conway.TreeDiff (Expr (..), ToExpr) -import Test.Cardano.Ledger.TreeDiff (ToExpr (..)) +import Test.Cardano.Ledger.TreeDiff (HexBytes (..), ToExpr (..)) instance (forall a b. (ToExpr a, ToExpr b) => ToExpr (f a b)) => @@ -78,7 +78,7 @@ instance ToExpr (DijkstraPParams StrictMaybe DijkstraEra) instance ToExpr (DijkstraTxBodyRaw l DijkstraEra) where toExpr = \case - txBody@(DijkstraTxBodyRaw _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) -> + txBody@(DijkstraTxBodyRaw {}) -> let DijkstraTxBodyRaw {..} = txBody in Rec "DijkstraTxBodyRaw" $ OMap.fromList @@ -105,7 +105,7 @@ instance ToExpr (DijkstraTxBodyRaw l DijkstraEra) where , ("dtbrDirectDeposits", toExpr dtbrDirectDeposits) , ("dtbrAccountBalanceIntervals", toExpr dtbrAccountBalanceIntervals) ] - txBody@(DijkstraSubTxBodyRaw _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) -> + txBody@(DijkstraSubTxBodyRaw {}) -> let DijkstraSubTxBodyRaw {..} = txBody in Rec "DijkstraSubTxBodyRaw" $ OMap.fromList @@ -141,8 +141,8 @@ instance ToExpr LeiosCert where toExpr LeiosCert {leiosCertSigners, leiosCertSignature} = Rec "LeiosCert" $ OMap.fromList - [ ("signers", toExpr (serialize (encodeBitField leiosCertSigners))) - , ("aggregatedSignature", toExpr (rawSerialiseSigDSIGN leiosCertSignature)) + [ ("leiosCertSigners", toExpr . HexBytes . serialize' $ encodeBitField leiosCertSigners) + , ("leiosCertSignature", toExpr . HexBytes $ rawSerialiseSigDSIGN leiosCertSignature) ] instance ToExpr (Tx TopTx era) => ToExpr (DijkstraBlockBodyRaw era) @@ -151,7 +151,7 @@ instance (AlonzoEraTx era, ToExpr (Tx TopTx era), ToExpr PerasCert) => ToExpr (D instance ToExpr (DijkstraTx l DijkstraEra) where toExpr = \case - txBody@(DijkstraTx _ _ _ _) -> + txBody@(DijkstraTx {}) -> let DijkstraTx {..} = txBody in Rec "DijkstraTx" $ OMap.fromList @@ -160,7 +160,7 @@ instance ToExpr (DijkstraTx l DijkstraEra) where , ("dtIsValid", toExpr dtIsValid) , ("dtAuxData", toExpr dtAuxData) ] - txBody@(DijkstraSubTx _ _ _) -> + txBody@(DijkstraSubTx {}) -> let DijkstraSubTx {..} = txBody in Rec "DijkstraSubTx" $ OMap.fromList