Skip to content

Commit e0d4207

Browse files
committed
Fix set validator
1 parent 581ac97 commit e0d4207

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

  • eras/conway/impl/cddl/lib/Cardano/Ledger/Conway
  • libs/cardano-ledger-core/cddl/Cardano/Ledger/Huddle

eras/conway/impl/cddl/lib/Cardano/Ledger/Conway/HuddleSpec.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ import Cardano.Ledger.Huddle.Gen (
8989
antiChoose,
9090
antiVectorOfUnique,
9191
arbitrary,
92+
canonicalizeTerm,
9293
faultyNum,
9394
genArrayTerm,
9495
genMapTerm,
@@ -749,7 +750,8 @@ mkMaybeTaggedSet pname n = binding $ \x ->
749750
let
750751
validateInner t = do
751752
elems <- validateArrayTerm t
752-
unless (elems == nub elems) $ fail "not all elements are unique"
753+
let canon = canonicalizeTerm <$> elems
754+
unless (canon == nub canon) $ fail "not all elements are unique"
753755
traverse_ (validateFromGRef ref) elems
754756
case term_ of
755757
TTagged t x | t == 258 -> validateInner x

libs/cardano-ledger-core/cddl/Cardano/Ledger/Huddle/Gen.hs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{-# LANGUAGE AllowAmbiguousTypes #-}
22
{-# LANGUAGE KindSignatures #-}
3+
{-# LANGUAGE LambdaCase #-}
34
{-# LANGUAGE RankNTypes #-}
45
{-# LANGUAGE ScopedTypeVariables #-}
56
{-# LANGUAGE TypeApplications #-}
@@ -23,6 +24,7 @@ module Cardano.Ledger.Huddle.Gen (
2324
genBytesTerm,
2425
genStringTerm,
2526
genMapTerm,
27+
canonicalizeTerm,
2628
unwrapSingleOrError,
2729

2830
-- * Term validators
@@ -53,10 +55,11 @@ import Codec.CBOR.Cuddle.CBOR.Gen (generateFromGRef, generateFromName)
5355
import Codec.CBOR.Cuddle.CBOR.Validator (validateFromGRef, validateFromName)
5456
import Codec.CBOR.Cuddle.CDDL (Name (..))
5557
import Codec.CBOR.Cuddle.CDDL.CBORGenerator as CBORGen
56-
import Control.Monad.Reader (asks)
5758
import Codec.CBOR.Cuddle.CDDL.CTree (nintMin, uintMax)
59+
import Control.Monad.Reader (asks)
5860
import Data.ByteString (ByteString)
5961
import qualified Data.ByteString.Lazy as LBS
62+
import Data.List (sortOn)
6063
import Data.Proxy (Proxy (..))
6164
import Data.Text (Text)
6265
import qualified Data.Text as T
@@ -65,6 +68,7 @@ import GHC.TypeLits (symbolVal)
6568
import Test.AntiGen as AntiGen
6669
import qualified Test.QuickCheck as QC
6770
import Test.QuickCheck.GenT as GenT
71+
import Data.Bifunctor (Bifunctor(..))
6872

6973
-- | A function for generating a term from a rule. The @HuddleRule@ constraint
7074
-- ensures that the rule is actually defined in that era.
@@ -122,6 +126,34 @@ ifTwiddle yes no = do
122126
twiddle <- asks (gcTwiddle . geConfig)
123127
if twiddle then yes else no
124128

129+
-- | Fold each Term to its canonical CBOR form: definite-length variants,
130+
-- strict bytestrings/text, sorted map keys, and Int promoted to Integer.
131+
-- Two Terms that round-trip to the same Haskell value should compare equal
132+
-- after canonicalization.
133+
canonicalizeTerm :: Term -> Term
134+
canonicalizeTerm = \case
135+
TInt n -> TInteger (toInteger n)
136+
TInteger n -> TInteger n
137+
TBytes bs -> TBytes bs
138+
TBytesI bs -> TBytes (LBS.toStrict bs)
139+
TString t -> TString t
140+
TStringI t -> TString (LT.toStrict t)
141+
TList xs -> TList (canonicalizeTerm <$> xs)
142+
TListI xs -> TList (canonicalizeTerm <$> xs)
143+
TMap kvs -> TMap (canonicalizeKVs kvs)
144+
TMapI kvs -> TMap (canonicalizeKVs kvs)
145+
TTagged tag t -> TTagged tag (canonicalizeTerm t)
146+
TBool b -> TBool b
147+
TNull -> TNull
148+
TSimple w -> TSimple w
149+
THalf f -> THalf f
150+
TFloat f -> TFloat f
151+
TDouble d -> TDouble d
152+
where
153+
canonicalizeKVs =
154+
sortOn fst
155+
. fmap (bimap canonicalizeTerm canonicalizeTerm)
156+
125157
-- Term validators
126158

127159
validateInt :: Term -> CBORValidator Integer

0 commit comments

Comments
 (0)