Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions cardano-crypto-peras/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
# Changelog for `cardano-crypto-peras`

## 0.1.0.1
## 0.2.0.0

*
* Add the Peras certificate types
* Add `PerasVotersBitmap`, the voters bitmap with its inclusive upper bound, built on
`Data.Bitmap` from `cardano-strict-containers`
* Remove the placeholder `BoostedBlock`; rename `pcBostedBlock` to `pcBoostedBlock`
* No CBOR instances, matching `cardano-crypto-leios`: `EncCBOR`/`DecCBOR` instances are
provided by `cardano-ledger-binary`
* Change `PerasRoundNo`'s representation from `Word64` to `Word32`
* Add `Cardano.Crypto.Peras.Vote` (`PerasVote`, `PerasVoteEligibilityProof`)
* Add `PerasCertSize` and `perasCertSizeUpperBound` to `Cardano.Crypto.Peras.Cert`

### `testlib`

* Add `Test.Cardano.Crypto.Peras.Gen`
* Add `genPerasVote`, `genPerasVoteEligibilityProof`

## 0.1.0.0

Expand Down
8 changes: 8 additions & 0 deletions cardano-crypto-peras/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@ needed by layers other than Consensus:
coordinate the end of a cooldown. Since this addition ultimately affects
block sizes (and block size checks live in Ledger), the best place to store
these certificates is at the Ledger level.
- **Peras votes**: the individual, per-committee-member votes that
certificates aggregate.

Base types live in `Cardano.Crypto.Peras`, certificates in
`Cardano.Crypto.Peras.Cert`, and votes in `Cardano.Crypto.Peras.Vote`. This
package does not provide CBOR instances for these types (matching
`cardano-crypto-leios`): `EncCBOR`/`DecCBOR` instances are provided by
`cardano-ledger-binary` instead.
49 changes: 47 additions & 2 deletions cardano-crypto-peras/cardano-crypto-peras.cabal
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
cabal-version: 3.0
name: cardano-crypto-peras
version: 0.1.0.0
version: 0.2.0.0
synopsis: Crypto primitives for Peras
description:
Data types and wire format for Peras certificates, shared by cardano-ledger and
ouroboros-consensus.

license: Apache-2.0
license-files:
LICENSE
Expand Down Expand Up @@ -37,8 +40,50 @@ library
exposed-modules:
Cardano.Crypto.Peras
Cardano.Crypto.Peras.Cert
Cardano.Crypto.Peras.Vote

build-depends:
base,
bytestring,
cardano-binary >=1.9.1,
cardano-crypto-class >=2.6,
cardano-slotting,
cardano-strict-containers >=0.1.7,
deepseq,
nothunks,
quiet,
serialise,

library testlib
import: base, project-config
visibility: public
hs-source-dirs: testlib
exposed-modules:
Test.Cardano.Crypto.Peras.Gen

build-depends:
QuickCheck,
bytestring,
cardano-base:testlib,
cardano-crypto-class:{cardano-crypto-class, testlib},
cardano-crypto-peras,
cardano-slotting,

test-suite tests
import: base, project-config
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Main.hs
other-modules:
Test.Cardano.Crypto.Peras

build-depends:
QuickCheck,
bytestring,
cardano-crypto-class,
cardano-crypto-peras:{cardano-crypto-peras, testlib},
cardano-slotting,
hspec,

ghc-options:
-threaded
-rtsopts
118 changes: 113 additions & 5 deletions cardano-crypto-peras/src/Cardano/Crypto/Peras.hs
Original file line number Diff line number Diff line change
@@ -1,15 +1,44 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeApplications #-}

module Cardano.Crypto.Peras (
-- * Peras round numbers
PerasRoundNo (..),
onPerasRoundNo,
PerasSeatIndex (..),
maxPerasSeatIndex,
PerasBlockRef (..),
perasBlockHashSize,
mkPerasBlockRef,
PerasBoostedBlock (..),
PerasDSIGN,
PerasSigningKey,
PerasVerificationKey,
PerasSignature (..),
PerasVRFOutput (..),
perasSignatureSize,
perasSignatureToBytes,
perasVRFOutputToBytes,
) where

import Cardano.Binary.FixedSizeCodec (fixedSize, rawEncodeFixedSized)
import Cardano.Crypto.DSIGN (SigDSIGN, SignKeyDSIGN, VerKeyDSIGN)
import Cardano.Crypto.DSIGN.BLS12381 (BLS12381MinSigDSIGN)
import Cardano.Slotting.Slot (SlotNo, WithOrigin)
import Codec.Serialise (Serialise)
import Control.DeepSeq (NFData)
import Data.ByteString (ByteString)
import Data.ByteString.Short (ShortByteString)
import qualified Data.ByteString.Short as SBS
import Data.Coerce (coerce)
import Data.Word (Word64)
import Data.Ord (comparing)
import Data.Proxy (Proxy (..))
import Data.Word (Word16, Word32)
import GHC.Generics (Generic)
import NoThunks.Class (NoThunks)
import Quiet (Quiet (..))
Expand All @@ -18,13 +47,92 @@ import Quiet (Quiet (..))
Peras round numbers
-------------------------------------------------------------------------------}

newtype PerasRoundNo = PerasRoundNo {unPerasRoundNo :: Word64}
-- | Round number in a Peras election.
newtype PerasRoundNo = PerasRoundNo {unPerasRoundNo :: Word32}
deriving (Show) via Quiet PerasRoundNo
deriving stock (Generic)
deriving newtype (Enum, Eq, Ord, Num, Bounded, NoThunks)
deriving newtype (Enum, Eq, Ord, Num, Bounded, NoThunks, NFData, Serialise)

-- | Lift a binary operation on 'Word64' to 'PerasRoundNo'
-- | Lift a binary operation on 'Word32' to 'PerasRoundNo'
onPerasRoundNo ::
(Word64 -> Word64 -> Word64) ->
(Word32 -> Word32 -> Word32) ->
(PerasRoundNo -> PerasRoundNo -> PerasRoundNo)
onPerasRoundNo = coerce

{-------------------------------------------------------------------------------
Seat indices
-------------------------------------------------------------------------------}

-- | Seat index in the voting committee used for Peras
newtype PerasSeatIndex = PerasSeatIndex {unPerasSeatIndex :: Word16}
deriving stock (Show, Eq, Ord, Generic)
deriving newtype (Enum, Bounded, NoThunks, NFData)

maxPerasSeatIndex :: PerasSeatIndex
maxPerasSeatIndex = maxBound

{-------------------------------------------------------------------------------
Block references
-------------------------------------------------------------------------------}

-- | A reference to a block: its slot number and 32-byte hash.
--
-- NOTE: this is intended to be equivalent to a @Point blk@ when
-- @HeaderHash blk ~ ShortByteString@.
data PerasBlockRef = PerasBlockRef
Comment thread
gdeest marked this conversation as resolved.
{ pbrSlot :: !SlotNo
, pbrHash :: !ShortByteString
}
deriving stock (Show, Eq, Ord, Generic)
deriving anyclass (NoThunks, NFData)

perasBlockHashSize :: Int
perasBlockHashSize = 32

mkPerasBlockRef :: SlotNo -> ShortByteString -> Maybe PerasBlockRef
mkPerasBlockRef slot hash
| SBS.length hash == perasBlockHashSize = Just (PerasBlockRef slot hash)
| otherwise = Nothing

-- | The slot number and 32-byte hash of the block being voted for.
newtype PerasBoostedBlock = PerasBoostedBlock {unPerasBoostedBlock :: WithOrigin PerasBlockRef}
deriving stock (Show, Eq, Ord, Generic)
deriving newtype (NoThunks, NFData)

{-------------------------------------------------------------------------------
BLS cryptography
-------------------------------------------------------------------------------}

type PerasDSIGN = BLS12381MinSigDSIGN

type PerasSigningKey = SignKeyDSIGN PerasDSIGN

type PerasVerificationKey = VerKeyDSIGN PerasDSIGN

newtype PerasSignature = PerasSignature {unPerasSignature :: SigDSIGN PerasDSIGN}
deriving stock (Show, Eq, Generic)
deriving newtype (NoThunks, NFData)

-- | 'SigDSIGN PerasDSIGN' (an elliptic curve point) has no natural total
-- order to derive an 'Ord' instance from (unlike 'Eq', which
-- @cardano-crypto-class@ provides via curve-point equality), so we compare on
-- the fixed-size wire encoding instead.
instance Ord PerasSignature where
Comment thread
agustinmista marked this conversation as resolved.
compare = comparing perasSignatureToBytes

newtype PerasVRFOutput = PerasVRFOutput {unPerasVRFOutput :: SigDSIGN PerasDSIGN}
deriving stock (Show, Eq, Generic)
deriving newtype (NoThunks, NFData)

-- | See the 'Ord PerasSignature' instance: no derivable 'Ord' exists either.
instance Ord PerasVRFOutput where
compare = comparing perasVRFOutputToBytes

perasSignatureSize :: Word
perasSignatureSize = fixedSize (Proxy @(SigDSIGN PerasDSIGN))

perasSignatureToBytes :: PerasSignature -> ByteString
perasSignatureToBytes = rawEncodeFixedSized . unPerasSignature

perasVRFOutputToBytes :: PerasVRFOutput -> ByteString
perasVRFOutputToBytes = rawEncodeFixedSized . unPerasVRFOutput
Loading
Loading