Skip to content

Commit

Permalink
Add Hashable instances for UPLC Term and related types (#5629)
Browse files Browse the repository at this point in the history
  • Loading branch information
zliu41 authored Nov 12, 2023
1 parent 9084737 commit 3bdff9a
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 5 deletions.
3 changes: 3 additions & 0 deletions plutus-core/changelog.d/20231111_160632_unsafeFixIO_hash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Added

- `Hashable` instances for `Data`, UPLC `Term` and related types.
4 changes: 4 additions & 0 deletions plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G1.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import Text.PrettyBy (PrettyBy)
import Control.DeepSeq (NFData, rnf, rwhnf)
import Data.ByteString (ByteString, length)
import Data.Coerce (coerce)
import Data.Hashable
import Data.Proxy (Proxy (..))
import Flat
import Prettyprinter
Expand Down Expand Up @@ -65,6 +66,9 @@ instance Flat Element where
instance NFData Element where
rnf (Element x) = rwhnf x -- Just to be on the safe side.

instance Hashable Element where
hashWithSalt salt = hashWithSalt salt . compress

-- | Add two G1 group elements
{-# INLINE add #-}
add :: Element -> Element -> Element
Expand Down
4 changes: 4 additions & 0 deletions plutus-core/plutus-core/src/PlutusCore/Crypto/BLS12_381/G2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import Text.PrettyBy (PrettyBy)
import Control.DeepSeq (NFData, rnf, rwhnf)
import Data.ByteString (ByteString, length)
import Data.Coerce (coerce)
import Data.Hashable
import Data.Proxy (Proxy (..))
import Flat
import Prettyprinter
Expand All @@ -51,6 +52,9 @@ instance Flat Element where
instance NFData Element where
rnf (Element x) = rwhnf x -- Just to be on the safe side.

instance Hashable Element where
hashWithSalt salt = hashWithSalt salt . compress

-- | Add two G2 group elements
{-# INLINE add #-}
add :: Element -> Element -> Element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Text.PrettyBy (PrettyBy, prettyBy)

import Control.DeepSeq (NFData, rnf)
import Data.Coerce (coerce)
import Data.Hashable
import Flat
import Prettyprinter

Expand Down Expand Up @@ -49,6 +50,9 @@ instance Flat MlResult where
instance NFData MlResult where
rnf _ = ()

instance Hashable MlResult where
hashWithSalt salt = const salt

millerLoop :: G1.Element -> G2.Element -> MlResult
millerLoop = coerce BlstBindings.millerLoop

Expand Down
3 changes: 2 additions & 1 deletion plutus-core/plutus-core/src/PlutusCore/Data.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Data.ByteString qualified as BS
import Data.ByteString.Base64 qualified as Base64
import Data.ByteString.Lazy qualified as BSL
import Data.Data qualified
import Data.Hashable
import Data.Text.Encoding qualified as Text
import Data.Word (Word64, Word8)
import GHC.Generics
Expand All @@ -44,7 +45,7 @@ data Data =
| I Integer
| B BS.ByteString
deriving stock (Show, Eq, Ord, Generic, Data.Data.Data)
deriving anyclass (NFData, NoThunks)
deriving anyclass (Hashable, NFData, NoThunks)

instance Pretty Data where
pretty = \case
Expand Down
9 changes: 5 additions & 4 deletions plutus-core/plutus-core/src/PlutusCore/DeBruijn/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import Control.Monad.Reader
import Control.Monad.State

import Data.Bimap qualified as BM
import Data.Hashable
import Data.Map qualified as M
import Data.Text qualified as T
import Data.Word
Expand Down Expand Up @@ -102,7 +103,7 @@ the Num and write `DeBruijn (Index -1)`. This can be revisited when we implement
-}
newtype Index = Index Word64
deriving stock (Generic)
deriving newtype (Show, Num, Enum, Real, Integral, Eq, Ord, Pretty, NFData, Read)
deriving newtype (Show, Num, Enum, Real, Integral, Eq, Ord, Hashable, Pretty, NFData, Read)

-- | The LamAbs index (for debruijn indices) and the starting level of DeBruijn monad
deBruijnInitIndex :: Index
Expand All @@ -113,7 +114,7 @@ deBruijnInitIndex = 0
-- | A term name as a de Bruijn index.
data NamedDeBruijn = NamedDeBruijn {ndbnString :: !T.Text, ndbnIndex :: !Index}
deriving stock (Show, Generic, Read)
deriving anyclass (NFData)
deriving anyclass (Hashable, NFData)

{-| A wrapper around `NamedDeBruijn` that *must* hold the invariant of name=`fakeName`.
Expand All @@ -123,7 +124,7 @@ but injection `ND->FND` is unsafe, thus they are not isomorphic.
See NOTE: [Why newtype FakeNamedDeBruijn]
-}
newtype FakeNamedDeBruijn = FakeNamedDeBruijn { unFakeNamedDeBruijn :: NamedDeBruijn }
deriving newtype (Show, Eq, NFData, PrettyBy config)
deriving newtype (Show, Eq, Hashable, NFData, PrettyBy config)

toFake :: DeBruijn -> FakeNamedDeBruijn
toFake (DeBruijn ix) = FakeNamedDeBruijn $ NamedDeBruijn fakeName ix
Expand All @@ -142,7 +143,7 @@ instance Eq NamedDeBruijn where
-- | A term name as a de Bruijn index, without the name string.
newtype DeBruijn = DeBruijn {dbnIndex :: Index}
deriving stock (Show, Generic, Eq)
deriving newtype (NFData)
deriving newtype (Hashable, NFData)

-- | A type name as a de Bruijn index.
newtype NamedTyDeBruijn = NamedTyDeBruijn NamedDeBruijn
Expand Down
13 changes: 13 additions & 0 deletions plutus-core/plutus-core/src/Universe/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import Data.Dependent.Sum
import Data.GADT.Compare
import Data.GADT.DeepSeq
import Data.GADT.Show
import Data.Hashable
import Data.Kind
import Data.Proxy
import Data.Some.Newtype
Expand Down Expand Up @@ -793,3 +794,15 @@ instance Closed uni => NFData (SomeTypeIn uni) where

instance (Closed uni, uni `Everywhere` NFData) => NFData (ValueOf uni a) where
rnf = grnf

instance (Closed uni, GEq uni) => Hashable (SomeTypeIn uni) where
hashWithSalt salt (SomeTypeIn uni) = hashWithSalt salt $ encodeUni uni

instance (Closed uni, GEq uni, uni `Everywhere` Eq, uni `Everywhere` Hashable) =>
Hashable (ValueOf uni a) where
hashWithSalt salt (ValueOf uni x) =
bring (Proxy @Hashable) uni $ hashWithSalt salt (SomeTypeIn uni, x)

instance (Closed uni, GEq uni, uni `Everywhere` Eq, uni `Everywhere` Hashable) =>
Hashable (Some (ValueOf uni)) where
hashWithSalt salt (Some s) = hashWithSalt salt s
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
-- editorconfig-checker-disable-file
{-# OPTIONS_GHC -fno-warn-orphans #-}

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
Expand All @@ -19,11 +20,23 @@ import PlutusCore.Rename.Monad
import Universe

import Data.Foldable (for_)
import Data.Hashable

instance (GEq uni, Closed uni, uni `Everywhere` Eq, Eq fun, Eq ann) =>
Eq (Term Name uni fun ann) where
term1 == term2 = runEqRename $ eqTermM term1 term2

type HashableTermConstraints uni fun ann =
( GEq uni
, Closed uni
, uni `Everywhere` Eq
, uni `Everywhere` Hashable
, Hashable ann
, Hashable fun
)

instance HashableTermConstraints uni fun ann => Hashable (Term Name uni fun ann)

-- Simple Structural Equality of a `Term NamedDeBruijn`. This implies three things:
-- a) We ignore the name part of the nameddebruijn
-- b) We do not do equality "modulo init index, see deBruijnInitIndex". E.g. `LamAbs 0 (Var 0) /= LamAbs 1 (Var 1)`.
Expand All @@ -33,14 +46,20 @@ deriving stock instance
(GEq uni, Closed uni, uni `Everywhere` Eq, Eq fun, Eq ann) =>
Eq (Term NamedDeBruijn uni fun ann)

instance HashableTermConstraints uni fun ann => Hashable (Term NamedDeBruijn uni fun ann)

deriving stock instance
(GEq uni, Closed uni, uni `Everywhere` Eq, Eq fun, Eq ann) =>
Eq (Term FakeNamedDeBruijn uni fun ann)

instance HashableTermConstraints uni fun ann => Hashable (Term FakeNamedDeBruijn uni fun ann)

deriving stock instance
(GEq uni, Closed uni, uni `Everywhere` Eq, Eq fun, Eq ann) =>
Eq (Term DeBruijn uni fun ann)

instance HashableTermConstraints uni fun ann => Hashable (Term DeBruijn uni fun ann)

deriving stock instance (GEq uni, Closed uni, uni `Everywhere` Eq, Eq fun, Eq ann,
Eq (Term name uni fun ann)
) => Eq (Program name uni fun ann)
Expand Down

0 comments on commit 3bdff9a

Please sign in to comment.