{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

-- | Definition of the shelley era, along with instances ot the @Core@ types
-- defined in @module Cardano.Ledger.Core@, and instances of the @API@ classes
-- exposed in @module Shelley.Spec.Ledger.API@.
module Cardano.Ledger.Shelley where

import Cardano.Binary (toCBOR)
import qualified Cardano.Crypto.Hash as Hash
import Cardano.Ledger.AuxiliaryData
  ( AuxiliaryDataHash (..),
    ValidateAuxiliaryData (..),
  )
import qualified Cardano.Ledger.Core as Core
import Cardano.Ledger.Crypto (HASH)
import qualified Cardano.Ledger.Crypto as CryptoClass
import Cardano.Ledger.Era (Era (Crypto))
import Cardano.Ledger.Shelley.Constraints (TxBodyConstraints)
import Shelley.Spec.Ledger.Coin (Coin)
import Shelley.Spec.Ledger.Keys (hashWithSerialiser)
import Shelley.Spec.Ledger.Metadata (Metadata (Metadata), validMetadatum)
import Shelley.Spec.Ledger.Scripts (MultiSig)
import Shelley.Spec.Ledger.Tx
  ( TxBody,
    ValidateScript (hashScript, validateScript),
    hashMultiSigScript,
    validateNativeMultiSigScript,
  )

data ShelleyEra c

instance CryptoClass.Crypto c => Era (ShelleyEra c) where
  type Crypto (ShelleyEra c) = c

--------------------------------------------------------------------------------
-- Core instances
--------------------------------------------------------------------------------

type instance Core.Value (ShelleyEra _c) = Coin

type instance Core.TxBody (ShelleyEra c) = TxBody (ShelleyEra c)

type instance Core.Script (ShelleyEra c) = MultiSig c

type instance Core.AuxiliaryData (ShelleyEra c) = Metadata

--------------------------------------------------------------------------------
-- Ledger data instances
--------------------------------------------------------------------------------

instance
  (CryptoClass.Crypto c, TxBodyConstraints (ShelleyEra c)) =>
  ValidateScript (ShelleyEra c)
  where
  validateScript :: Script (ShelleyEra c) -> Tx (ShelleyEra c) -> Bool
validateScript = Script (ShelleyEra c) -> Tx (ShelleyEra c) -> Bool
forall era.
(TxBodyConstraints era, ToCBOR (AuxiliaryData era)) =>
MultiSig (Crypto era) -> Tx era -> Bool
validateNativeMultiSigScript
  hashScript :: Script (ShelleyEra c) -> ScriptHash (Crypto (ShelleyEra c))
hashScript = Script (ShelleyEra c) -> ScriptHash (Crypto (ShelleyEra c))
forall crypto.
Crypto crypto =>
MultiSig crypto -> ScriptHash crypto
hashMultiSigScript

instance CryptoClass.Crypto c => ValidateAuxiliaryData (ShelleyEra c) where
  hashAuxiliaryData :: AuxiliaryData (ShelleyEra c)
-> AuxiliaryDataHash (Crypto (ShelleyEra c))
hashAuxiliaryData = Hash (HASH c) EraIndependentMetadata -> AuxiliaryDataHash c
forall crypto.
Hash crypto EraIndependentMetadata -> AuxiliaryDataHash crypto
AuxiliaryDataHash (Hash (HASH c) EraIndependentMetadata -> AuxiliaryDataHash c)
-> (Metadata -> Hash (HASH c) EraIndependentMetadata)
-> Metadata
-> AuxiliaryDataHash c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash (HASH c) Metadata -> Hash (HASH c) EraIndependentMetadata
forall h a b. Hash h a -> Hash h b
Hash.castHash (Hash (HASH c) Metadata -> Hash (HASH c) EraIndependentMetadata)
-> (Metadata -> Hash (HASH c) Metadata)
-> Metadata
-> Hash (HASH c) EraIndependentMetadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Metadata -> Encoding) -> Metadata -> Hash (HASH c) Metadata
forall h a. HashAlgorithm h => (a -> Encoding) -> a -> Hash h a
hashWithSerialiser @(HASH c) Metadata -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR
  validateAuxiliaryData :: AuxiliaryData (ShelleyEra c) -> Bool
validateAuxiliaryData (Metadata m) = (Metadatum -> Bool) -> Map Word64 Metadatum -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Metadatum -> Bool
validMetadatum Map Word64 Metadatum
m