Skip to content

Commit

Permalink
Improve hashes and keys haddock
Browse files Browse the repository at this point in the history
  • Loading branch information
lehins committed Dec 20, 2024
1 parent 33f7c01 commit 885db90
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 79 deletions.
4 changes: 2 additions & 2 deletions libs/cardano-ledger-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
* `SafeHash`, `SafeToHash`, `HashAnnotated`, `castSafeHash` and `extractHash`.
* `KeyRoleVRF`, `VRFVerKeyHash`, `toVRFVerKeyHash`, `fromVRFVerKeyHash`
* `GenDelegPair` and `GenDelegs`
* Re-export `KeyRole` from `Cardano.Ledger.Hashes`:
* Re-export some of the new additions to `Cardano.Ledger.Hashes` from `Cardano.Ledger.Core.
* Re-export `KeyRole` from `Cardano.Ledger.Hashes`.
* Re-export some of the new additions to `Cardano.Ledger.Hashes` from `Cardano.Ledger.Core`.
* Remove `GenesisCredential` as unused.
* Remove `HASH`, `ADDRHASH` and `DSIGN` type families out of `Crypto` type class and turn
them into type synonyms for the exact algorithms previously being used in
Expand Down
16 changes: 8 additions & 8 deletions libs/cardano-ledger-core/src/Cardano/Ledger/Crypto.hs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module Cardano.Ledger.Crypto
{-# DEPRECATED
"Cardano.Ledger.Crypto interface have been completely overhauled. In particular:\
"@Cardano.Ledger.Crypto@ interface have been completely overhauled. In particular: \
\\
\* `Crypto` type class no longer contains `DSIGN`, `HASH` and `ADDRHASH` type families,\
\ instead they have been extracted into type synonyms that point to exact algorithms that previously\
\ where specified in `StandardCrypto` for those type families.\
\ * `DSIGN` type synonym can be imported from `Cardano.Ledger.Keys` module\
\ * `HASH` and `ADDRHASH` type synonyms can be imported from `Cardano.Ledger.Hashes` module\
\1). `Crypto` type class no longer contains `DSIGN`, `HASH` and `ADDRHASH` type families, \
\ instead they have been extracted into type synonyms that point to exact algorithms that previously \
\ where specified in `StandardCrypto` for those type families: \
\ a). `DSIGN` type synonym can be imported from \"Cardano.Ledger.Keys\" module \
\ b). `HASH` and `ADDRHASH` type synonyms can be imported from \"Cardano.Ledger.Hashes\" module \
\\
\* `Crypto` type class has retained its `KES` and `VRF` type families, which are not used in Ledger, therefore\
\ this type class as well as `StandardCrypto` definition will be migrated to `Cardano.Protocol.Crypto` module\
\2). `Crypto` type class has retained its `KES` and `VRF` type families, which are not used in Ledger, therefore \
\ this type class as well as `StandardCrypto` definition will be migrated to \"Cardano.Protocol.Crypto\" module \
\ and from now on should be imported from 'cardano-protocol-tpraos' package instead."
#-} (
Crypto (..),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_HADDOCK not-home #-}

-- Contents of this module will be moved to `Cardano.Protocol.Crypto` at some point later
-- whenever we are ready to remove derpecations
-- whenever we are ready to remove deprecations
module Cardano.Ledger.Crypto.Internal (
Crypto (..),
StandardCrypto,
Expand Down
72 changes: 28 additions & 44 deletions libs/cardano-ledger-core/src/Cardano/Ledger/Hashes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,41 +56,21 @@ module Cardano.Ledger.Hashes (
toVRFVerKeyHash,
fromVRFVerKeyHash,

-- ** Genesis @DSIGN@ and @VRF@ Verification Key hashes
-- ** Genesis @DSIGN@ and @VRF@ Verification Key Hashes
GenDelegPair (..),
GenDelegs (..),

-- * SafeHash

-- In cardano-ledger, hashing a type @X@ is based upon the serialization of @X@. Serialization is
-- based upon the 'EncCBOR' and DecCBOR type classes, and the values produced by 'EncCBOR' instances for a
-- particular type, are not necessarily unique. For this reason, when an @X@ object comes
-- over the network in serialized form, we must preserve the original bytes that arrived over
-- the network, otherwise when the system hashes that object, the hash in the ledger, and the hash of
-- that object from the other side of the network may not agree. The module 'Cardano.Ledger.SafeHash'
-- introduces the 'SafeToHash' type class that ensures that types with a @(SafeToHash X)@ instance store the
-- original bytes that arrived over the network for the value of @X@. The recommended way to store the
-- original bytes is to use the type 'MemoBytes', although there are
-- a few types that store their original bytes in other ways. In order to encourage the use of 'MemoBytes'
-- newtypes defined as a 'MemoBytes' get the to derive 'SafeToHash' instances for free.

--
-- $SAFE
-- $SAFEHASH
SafeHash,
SafeToHash (..),

-- ** Creating SafeHash

--
-- $MAKE
HashAnnotated,
hashAnnotated,
unsafeMakeSafeHash,

-- ** Other operations

--
-- $OTHER
castSafeHash,
extractHash,
indexProxy,
Expand Down Expand Up @@ -305,6 +285,23 @@ newtype GenDelegs = GenDelegs
-- Safe Hashes
--------------------------------------------------------------------------------

-- $SAFEHASH
--
-- In cardano-ledger, hashing a type @X@ is based upon the serialization of
-- @X@. Serialization is based upon the 'EncCBOR' and 'DecCBOR' type classes, and the
-- serialization that can be handled by 'DecCBOR' instances for a particular type, are not
-- necessarily unique. For this reason, when an @X@ object comes over the network in
-- serialized form, we must preserve the original bytes that arrived over the network,
-- otherwise when the system hashes that object, the hash in the ledger, and the hash of
-- that object from the other side of the network may not agree. In otherwords
-- reserialization for the purpose of hash calculation is not an option. The 'SafeToHash'
-- type class ensures that types with a @(SafeToHash X)@ instance store the original bytes
-- that arrived over the network for the value of @X@. The recommended way to store the
-- original bytes is to use the type 'MemoBytes', although there are a few types that
-- store their original bytes in other ways. In order to encourage the use of newtype over
-- 'Cardano.Ledger.MemoBytes.MemoBytes' newtype defined as a 'MemoBytes', which would get
-- the functionality of retaining bytes and deriving of 'SafeToHash' instance for free.

-- | A 'SafeHash' is a hash of something that is safe to hash. Such types store their own
-- serialisation bytes. The prime example is @('MemoBytes' t)@, but other examples are
-- things that consist of only ByteStrings (i.e. they are their own serialization) or for
Expand All @@ -328,10 +325,8 @@ instance Default (SafeHash i) where
extractHash :: SafeHash i -> Hash.Hash HASH i
extractHash (SafeHash h) = h

-- MAKE

-- | Don't use this except in Testing to make Arbitrary instances, etc.
-- Defined here, only because the Constructor is in scope here.
-- | Don't use this except in Testing to make Arbitrary instances, etc. or in cases when
-- it can be guaranteed that original bytes were used for computing the hash.
unsafeMakeSafeHash :: Hash.Hash HASH i -> SafeHash i
unsafeMakeSafeHash = SafeHash

Expand Down Expand Up @@ -361,40 +356,29 @@ class SafeToHash t where
-- value to be hashed.
makeHashWithExplicitProxys _ x = SafeHash $ Hash.castHash (Hash.hashWith originalBytes x)

-- There are a limited number of direct instances. Everything else should come
-- from newtype deriving.

instance SafeToHash ShortByteString where
originalBytes = fromShort
originalBytesSize = SBS.length

instance SafeToHash ByteString where
originalBytes x = x

-- If one looks at the deriving clause in the definitions of SafeHash, we see that we
-- derive that it is SafeToHash. We can derive this instance because SafeHash is
-- a newtype around (Hash.Hash c i) which is a primitive SafeToHash type.

-- | Hash of a hash. Hash is always safe to hash. Do you even hash?
instance Hash.HashAlgorithm h => SafeToHash (Hash.Hash h i) where
originalBytes = Hash.hashToBytes

-- | Types that are 'SafeToHash', AND have both of the following two invariants,
-- are made members of the HashAnnotated class. The preconditions are:
--
-- 1. The type uniquely determines the 'index' type tag of (SafeHashrypto index)
-- 2. The type uniquely determines the 'crypto' type of (SafeHashrytop index)
-- | Types that are 'SafeToHash' AND have the type uniquely determines the 'index' type
-- tag of @`SafeHash` index@
--
-- The 'SafeToHash' and the 'HashAnnotated' classes are designed so that their
-- instances can be easily derived (because their methods have default methods
-- when the type is a newtype around a type that is 'SafeToHash'). For example,
-- The 'SafeToHash' and the 'HashAnnotated' classes are designed so that their instances
-- can be easily derived (because their methods have default methods when the type is a
-- newtype around a type that is 'SafeToHash'). For example,
class SafeToHash x => HashAnnotated x i | x -> i where
-- TODO: move outside of type class
indexProxy :: x -> Proxy i
indexProxy _ = Proxy @i

-- | Create a @('SafeHash' i crypto)@,
-- given @(Hash.HashAlgorithm (HASH crypto))@
-- and @(HashAnnotated x i crypto)@ instances.
-- | Create a @('SafeHash' i)@, given @(`HashAnnotated` x i)@ instance.
hashAnnotated :: x -> SafeHash i
hashAnnotated = makeHashWithExplicitProxys (Proxy @i)
{-# INLINE hashAnnotated #-}
Expand Down
24 changes: 12 additions & 12 deletions libs/cardano-ledger-core/src/Cardano/Ledger/Keys.hs
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ hashVerKeyVRF = VRFVerKeyHash . Hash.castHash . VRF.hashVerKeyVRF
{-# DEPRECATED hashVerKeyVRF "Use `Cardano.Protocol.Crypto.hashVerKeyVRF` instead" #-}

type Hash = Hash.Hash HASH
{-# DEPRECATED Hash "In favor of `Hash.Hash` `HASH`" #-}
{-# DEPRECATED Hash "In favor of `Cardano.Crypto.Hash.Hash` `HASH`" #-}

type SignedDSIGN = DSIGN.SignedDSIGN DSIGN
{-# DEPRECATED SignedDSIGN "In favor of @`DSIGN.SignedDSIGN` `DSIGN`@" #-}
{-# DEPRECATED SignedDSIGN "In favor of @`Cardano.Crypto.DSIGN.SignedDSIGN` `DSIGN`@" #-}

type SignKeyDSIGN = DSIGN.SignKeyDSIGN DSIGN
{-# DEPRECATED SignKeyDSIGN "In favor of @`DSIGN.SignKeyDSIGN` `DSIGN`@" #-}
{-# DEPRECATED SignKeyDSIGN "In favor of @`Cardano.Crypto.DSIGN.SignKeyDSIGN` `DSIGN`@" #-}

-- | Hash a given signature
hashSignature ::
Expand All @@ -105,37 +105,37 @@ hashSignature (DSIGN.SignedDSIGN sigDSIGN) = Hash.castHash $ Hash.hashWith DSIGN
{-# DEPRECATED
hashSignature
"In favor of `Cardano.Ledger.Hashes.hashTxBodySignature`. \
\Fallback on `Hash.hashWith` if you need more general hashing functionality."
\Fallback on `Cardano.Crypto.Hash.hashWith` if you need more general hashing functionality."
#-}

--------------------------------------------------------------------------------
-- KES
--------------------------------------------------------------------------------

type KESignable c = KES.Signable (KES c)
{-# DEPRECATED KESignable "In favor of @`KES.Signable` (`KES` c)@" #-}
{-# DEPRECATED KESignable "In favor of @`Cardano.Crypto.KES.Signable` (`KES` c)@" #-}

type SignedKES c = KES.SignedKES (KES c)
{-# DEPRECATED SignedKES "In favor of @`KES.SignedKES` (`KES` c)@`" #-}
{-# DEPRECATED SignedKES "In favor of @`Cardano.Crypto.KES.SignedKES` (`KES` c)@" #-}

type SignKeyKES c = KES.SignKeyKES (KES c)
{-# DEPRECATED SignKeyKES "In favor of @`KES.SignKeyKES` (`KES` c)@`" #-}
{-# DEPRECATED SignKeyKES "In favor of @`Cardano.Crypto.KES.SignKeyKES` (`KES` c)@" #-}

type VerKeyKES c = KES.VerKeyKES (KES c)
{-# DEPRECATED VerKeyKES "In favor of @`KES.VerKeyKES` (`KES` c)@`" #-}
{-# DEPRECATED VerKeyKES "In favor of @`Cardano.Crypto.KES.VerKeyKES` (`KES` c)@" #-}

--------------------------------------------------------------------------------
-- VRF
--------------------------------------------------------------------------------

type VRFSignable c = VRF.Signable (VRF c)
{-# DEPRECATED VRFSignable "In favor of @`VRF.Signable` (`VRF` c)@`" #-}
{-# DEPRECATED VRFSignable "In favor of @`Cardano.Crypto.VRF.Signable` (`VRF` c)@" #-}

type CertifiedVRF c = VRF.CertifiedVRF (VRF c)
{-# DEPRECATED CertifiedVRF "In favor of @`VRF.CertifiedVRF` (`VRF` c)@`" #-}
{-# DEPRECATED CertifiedVRF "In favor of @`Cardano.Crypto.VRF.CertifiedVRF` (`VRF` c)@" #-}

type SignKeyVRF c = VRF.SignKeyVRF (VRF c)
{-# DEPRECATED SignKeyVRF "In favor of @`VRF.SignKeyVRF` (`VRF` c)@`" #-}
{-# DEPRECATED SignKeyVRF "In favor of @`Cardano.Crypto.VRF.SignKeyVRF` (`VRF` c)@" #-}

type VerKeyVRF c = VRF.VerKeyVRF (VRF c)
{-# DEPRECATED VerKeyVRF "In favor of @`VRF.VerKeyVRF` (`VRF` c)@`" #-}
{-# DEPRECATED VerKeyVRF "In favor of @`Cardano.Crypto.VRF.VerKeyVRF` (`VRF` c)@" #-}
21 changes: 9 additions & 12 deletions libs/cardano-ledger-core/src/Cardano/Ledger/Keys/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,20 @@ import GHC.Generics (Generic)
import NoThunks.Class (NoThunks (..))
import Quiet

-- | Cryptographic saigning algorithm used on Cardano blockchain.
-- | Cryptographic signing algorithm used on Cardano blockchain.
type DSIGN = DSIGN.Ed25519DSIGN

-- | The role of a key.
--
-- Note that a role is not _fixed_, nor is it unique. In particular, keys may
-- variously be used as witnesses, and so in many case we will change the role
-- of a key to the 'Witness' role.
-- All key roles are __fixed__ and unique, except for the `Witness` role. In particular,
-- keys can be cast to a `Witness` role with the help of `asWitness`, because same witness
-- can be valid for many roles.
--
-- It is also perfectly allowable for a key to be used in many roles; there is
-- nothing prohibiting somebody using the same underlying key as their payment
-- and staking key, as well as the key for their stake pool. So these roles
-- are more intended for two purposes:
--
-- - To make explicit how we are using a key in the specifications
-- - To provide a guide to downstream implementors, for whom the profusion of
-- keys may be confusing.
-- In fact, it is perfectly allowable for a key to be used in many roles by the end user;
-- there is nothing prohibiting somebody using the same underlying key or a script as
-- their payment and staking credential, as well as the key for their stake pool. However,
-- in the ledger code mixing up keys with different roles could be catastrophic, that is
-- why we have this separation.
data KeyRole
= Genesis
| GenesisDelegate
Expand Down

0 comments on commit 885db90

Please sign in to comment.