{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wno-orphans #-}

module Cardano.Ledger.Allegra.Scripts (
  AllegraEraScript (..),
  mkRequireSignatureTimelock,
  getRequireSignatureTimelock,
  mkRequireAllOfTimelock,
  getRequireAllOfTimelock,
  mkRequireAnyOfTimelock,
  getRequireAnyOfTimelock,
  mkRequireMOfTimelock,
  getRequireMOfTimelock,
  mkTimeStartTimelock,
  getTimeStartTimelock,
  mkTimeExpireTimelock,
  getTimeExpireTimelock,
  Timelock,
  pattern RequireTimeExpire,
  pattern RequireTimeStart,
  TimelockRaw,
  pattern TimelockConstr,
  inInterval,
  showTimelock,
  evalTimelock,
  eqTimelockRaw,
  ValidityInterval (..),
  encodeVI,
  decodeVI,
  -- translate,
  translateTimelock,
)
where

import Cardano.Crypto.Hash.Class (HashAlgorithm)
import Cardano.Ledger.Allegra.Era (AllegraEra)
import Cardano.Ledger.BaseTypes (StrictMaybe (SJust, SNothing))
import Cardano.Ledger.Binary (
  Annotator (..),
  DecCBOR (decCBOR),
  EncCBOR (encCBOR),
  ToCBOR (..),
 )
import Cardano.Ledger.Binary.Coders (
  Decode (..),
  Density (..),
  Encode (..),
  Wrapped (..),
  decode,
  encode,
  (!>),
  (<!),
  (<*!),
 )
import Cardano.Ledger.Core
import Cardano.Ledger.Crypto (Crypto, HASH, StandardCrypto)
import Cardano.Ledger.Keys (KeyHash (..), KeyRole (Witness))
import Cardano.Ledger.MemoBytes (
  EqRaw (..),
  Mem,
  MemoBytes (Memo),
  Memoized (..),
  getMemoRawType,
  mkMemoBytes,
  mkMemoized,
 )
import Cardano.Ledger.SafeHash (SafeToHash)
import Cardano.Ledger.Shelley.Scripts (
  ShelleyEraScript (..),
  nativeMultiSigTag,
  pattern RequireAllOf,
  pattern RequireAnyOf,
  pattern RequireMOf,
  pattern RequireSignature,
 )

import Cardano.Slotting.Slot (SlotNo (..))
import Control.DeepSeq (NFData (..))
import Data.Aeson (ToJSON (..), (.=))
import qualified Data.Aeson as Aeson
import Data.ByteString.Lazy (fromStrict)
import Data.ByteString.Short (fromShort)
import Data.Sequence.Strict as Seq (StrictSeq (Empty, (:<|)))
import qualified Data.Sequence.Strict as SSeq
import qualified Data.Set as Set (Set, member)
import GHC.Generics (Generic)
import NoThunks.Class (NoThunks (..))

-- | ValidityInterval is a half open interval. Closed on the bottom, open on the top.
--   A SNothing on the bottom is negative infinity, and a SNothing on the top is positive infinity
data ValidityInterval = ValidityInterval
  { ValidityInterval -> StrictMaybe SlotNo
invalidBefore :: !(StrictMaybe SlotNo)
  , ValidityInterval -> StrictMaybe SlotNo
invalidHereafter :: !(StrictMaybe SlotNo)
  }
  deriving (Eq ValidityInterval
ValidityInterval -> ValidityInterval -> Bool
ValidityInterval -> ValidityInterval -> Ordering
ValidityInterval -> ValidityInterval -> ValidityInterval
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ValidityInterval -> ValidityInterval -> ValidityInterval
$cmin :: ValidityInterval -> ValidityInterval -> ValidityInterval
max :: ValidityInterval -> ValidityInterval -> ValidityInterval
$cmax :: ValidityInterval -> ValidityInterval -> ValidityInterval
>= :: ValidityInterval -> ValidityInterval -> Bool
$c>= :: ValidityInterval -> ValidityInterval -> Bool
> :: ValidityInterval -> ValidityInterval -> Bool
$c> :: ValidityInterval -> ValidityInterval -> Bool
<= :: ValidityInterval -> ValidityInterval -> Bool
$c<= :: ValidityInterval -> ValidityInterval -> Bool
< :: ValidityInterval -> ValidityInterval -> Bool
$c< :: ValidityInterval -> ValidityInterval -> Bool
compare :: ValidityInterval -> ValidityInterval -> Ordering
$ccompare :: ValidityInterval -> ValidityInterval -> Ordering
Ord, ValidityInterval -> ValidityInterval -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ValidityInterval -> ValidityInterval -> Bool
$c/= :: ValidityInterval -> ValidityInterval -> Bool
== :: ValidityInterval -> ValidityInterval -> Bool
$c== :: ValidityInterval -> ValidityInterval -> Bool
Eq, forall x. Rep ValidityInterval x -> ValidityInterval
forall x. ValidityInterval -> Rep ValidityInterval x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ValidityInterval x -> ValidityInterval
$cfrom :: forall x. ValidityInterval -> Rep ValidityInterval x
Generic, Int -> ValidityInterval -> ShowS
[ValidityInterval] -> ShowS
ValidityInterval -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ValidityInterval] -> ShowS
$cshowList :: [ValidityInterval] -> ShowS
show :: ValidityInterval -> String
$cshow :: ValidityInterval -> String
showsPrec :: Int -> ValidityInterval -> ShowS
$cshowsPrec :: Int -> ValidityInterval -> ShowS
Show, Context -> ValidityInterval -> IO (Maybe ThunkInfo)
Proxy ValidityInterval -> String
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy ValidityInterval -> String
$cshowTypeOf :: Proxy ValidityInterval -> String
wNoThunks :: Context -> ValidityInterval -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> ValidityInterval -> IO (Maybe ThunkInfo)
noThunks :: Context -> ValidityInterval -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> ValidityInterval -> IO (Maybe ThunkInfo)
NoThunks, ValidityInterval -> ()
forall a. (a -> ()) -> NFData a
rnf :: ValidityInterval -> ()
$crnf :: ValidityInterval -> ()
NFData)

encodeVI :: ValidityInterval -> Encode ('Closed 'Dense) ValidityInterval
encodeVI :: ValidityInterval -> Encode ('Closed 'Dense) ValidityInterval
encodeVI (ValidityInterval StrictMaybe SlotNo
f StrictMaybe SlotNo
t) = forall t. t -> Encode ('Closed 'Dense) t
Rec StrictMaybe SlotNo -> StrictMaybe SlotNo -> ValidityInterval
ValidityInterval forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To StrictMaybe SlotNo
f forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To StrictMaybe SlotNo
t

instance EncCBOR ValidityInterval where
  encCBOR :: ValidityInterval -> Encoding
encCBOR ValidityInterval
vi = forall (w :: Wrapped) t. Encode w t -> Encoding
encode (ValidityInterval -> Encode ('Closed 'Dense) ValidityInterval
encodeVI ValidityInterval
vi)

decodeVI :: Decode ('Closed 'Dense) ValidityInterval
decodeVI :: Decode ('Closed 'Dense) ValidityInterval
decodeVI = forall t. t -> Decode ('Closed 'Dense) t
RecD StrictMaybe SlotNo -> StrictMaybe SlotNo -> ValidityInterval
ValidityInterval forall (w1 :: Wrapped) a t (w :: Density).
Decode w1 (a -> t) -> Decode ('Closed w) a -> Decode w1 t
<! forall t (w :: Wrapped). DecCBOR t => Decode w t
From forall (w1 :: Wrapped) a t (w :: Density).
Decode w1 (a -> t) -> Decode ('Closed w) a -> Decode w1 t
<! forall t (w :: Wrapped). DecCBOR t => Decode w t
From

instance DecCBOR ValidityInterval where
  decCBOR :: forall s. Decoder s ValidityInterval
decCBOR = forall (w :: Wrapped) t s. Decode w t -> Decoder s t
decode Decode ('Closed 'Dense) ValidityInterval
decodeVI

instance ToJSON ValidityInterval where
  toJSON :: ValidityInterval -> Value
toJSON ValidityInterval
vi =
    [Pair] -> Value
Aeson.object forall a b. (a -> b) -> a -> b
$
      [ Key
k forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= SlotNo
v
      | (Key
k, SJust SlotNo
v) <-
          [ (Key
"invalidBefore", ValidityInterval -> StrictMaybe SlotNo
invalidBefore ValidityInterval
vi)
          , (Key
"invalidHereafter", ValidityInterval -> StrictMaybe SlotNo
invalidHereafter ValidityInterval
vi)
          ]
      ]

-- ==================================================================

data TimelockRaw era
  = Signature !(KeyHash 'Witness (EraCrypto era))
  | AllOf !(StrictSeq (Timelock era)) -- NOTE that Timelock and
  | AnyOf !(StrictSeq (Timelock era)) -- TimelockRaw are mutually recursive.
  | MOfN !Int !(StrictSeq (Timelock era))
  | -- Note that the Int may be negative in which case (MOfN (-2) [..]) is always True
    TimeStart !SlotNo -- The start time
  | TimeExpire !SlotNo -- The time it expires
  deriving (TimelockRaw era -> TimelockRaw era -> Bool
forall era. TimelockRaw era -> TimelockRaw era -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TimelockRaw era -> TimelockRaw era -> Bool
$c/= :: forall era. TimelockRaw era -> TimelockRaw era -> Bool
== :: TimelockRaw era -> TimelockRaw era -> Bool
$c== :: forall era. TimelockRaw era -> TimelockRaw era -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall era x. Rep (TimelockRaw era) x -> TimelockRaw era
forall era x. TimelockRaw era -> Rep (TimelockRaw era) x
$cto :: forall era x. Rep (TimelockRaw era) x -> TimelockRaw era
$cfrom :: forall era x. TimelockRaw era -> Rep (TimelockRaw era) x
Generic, forall era. TimelockRaw era -> ()
forall a. (a -> ()) -> NFData a
rnf :: TimelockRaw era -> ()
$crnf :: forall era. TimelockRaw era -> ()
NFData)

class ShelleyEraScript era => AllegraEraScript era where
  mkTimeStart :: SlotNo -> NativeScript era
  getTimeStart :: NativeScript era -> Maybe SlotNo

  mkTimeExpire :: SlotNo -> NativeScript era
  getTimeExpire :: NativeScript era -> Maybe SlotNo

deriving instance Era era => NoThunks (TimelockRaw era)

deriving instance HashAlgorithm (HASH (EraCrypto era)) => Show (TimelockRaw era)

-- | This function deconstructs and then reconstructs the timelock script
-- to prove the compiler that we can arbirarily switch out the eras as long
-- as the cryptos for both eras are the same.
translateTimelock ::
  forall era1 era2.
  ( Era era1
  , Era era2
  , EraCrypto era1 ~ EraCrypto era2
  ) =>
  Timelock era1 ->
  Timelock era2
translateTimelock :: forall era1 era2.
(Era era1, Era era2, EraCrypto era1 ~ EraCrypto era2) =>
Timelock era1 -> Timelock era2
translateTimelock (TimelockConstr (Memo TimelockRaw era1
tl ShortByteString
bs)) =
  let rewrap :: TimelockRaw era2 -> Timelock era2
rewrap TimelockRaw era2
rtl = forall era. MemoBytes TimelockRaw era -> Timelock era
TimelockConstr forall a b. (a -> b) -> a -> b
$ forall era (t :: * -> *).
Era era =>
t era -> ByteString -> MemoBytes t era
mkMemoBytes TimelockRaw era2
rtl (ByteString -> ByteString
fromStrict forall a b. (a -> b) -> a -> b
$ ShortByteString -> ByteString
fromShort ShortByteString
bs)
   in case TimelockRaw era1
tl of
        Signature KeyHash 'Witness (EraCrypto era1)
s -> TimelockRaw era2 -> Timelock era2
rewrap forall a b. (a -> b) -> a -> b
$ forall era. KeyHash 'Witness (EraCrypto era) -> TimelockRaw era
Signature KeyHash 'Witness (EraCrypto era1)
s
        AllOf StrictSeq (Timelock era1)
l -> TimelockRaw era2 -> Timelock era2
rewrap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era. StrictSeq (Timelock era) -> TimelockRaw era
AllOf forall a b. (a -> b) -> a -> b
$ forall era1 era2.
(Era era1, Era era2, EraCrypto era1 ~ EraCrypto era2) =>
Timelock era1 -> Timelock era2
translateTimelock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StrictSeq (Timelock era1)
l
        AnyOf StrictSeq (Timelock era1)
l -> TimelockRaw era2 -> Timelock era2
rewrap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era. StrictSeq (Timelock era) -> TimelockRaw era
AnyOf forall a b. (a -> b) -> a -> b
$ forall era1 era2.
(Era era1, Era era2, EraCrypto era1 ~ EraCrypto era2) =>
Timelock era1 -> Timelock era2
translateTimelock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StrictSeq (Timelock era1)
l
        MOfN Int
n StrictSeq (Timelock era1)
l -> TimelockRaw era2 -> Timelock era2
rewrap forall a b. (a -> b) -> a -> b
$ forall era. Int -> StrictSeq (Timelock era) -> TimelockRaw era
MOfN Int
n (forall era1 era2.
(Era era1, Era era2, EraCrypto era1 ~ EraCrypto era2) =>
Timelock era1 -> Timelock era2
translateTimelock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StrictSeq (Timelock era1)
l)
        TimeStart SlotNo
x -> TimelockRaw era2 -> Timelock era2
rewrap forall a b. (a -> b) -> a -> b
$ forall era. SlotNo -> TimelockRaw era
TimeStart SlotNo
x
        TimeExpire SlotNo
x -> TimelockRaw era2 -> Timelock era2
rewrap forall a b. (a -> b) -> a -> b
$ forall era. SlotNo -> TimelockRaw era
TimeExpire SlotNo
x

-- These coding choices are chosen so that a MultiSig script
-- can be deserialised as a Timelock script

instance Era era => EncCBOR (TimelockRaw era) where
  encCBOR :: TimelockRaw era -> Encoding
encCBOR =
    forall (w :: Wrapped) t. Encode w t -> Encoding
encode forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
      Signature KeyHash 'Witness (EraCrypto era)
hash -> forall t. t -> Word -> Encode 'Open t
Sum forall era. KeyHash 'Witness (EraCrypto era) -> TimelockRaw era
Signature Word
0 forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To KeyHash 'Witness (EraCrypto era)
hash
      AllOf StrictSeq (Timelock era)
xs -> forall t. t -> Word -> Encode 'Open t
Sum forall era. StrictSeq (Timelock era) -> TimelockRaw era
AllOf Word
1 forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To StrictSeq (Timelock era)
xs
      AnyOf StrictSeq (Timelock era)
xs -> forall t. t -> Word -> Encode 'Open t
Sum forall era. StrictSeq (Timelock era) -> TimelockRaw era
AnyOf Word
2 forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To StrictSeq (Timelock era)
xs
      MOfN Int
m StrictSeq (Timelock era)
xs -> forall t. t -> Word -> Encode 'Open t
Sum forall era. Int -> StrictSeq (Timelock era) -> TimelockRaw era
MOfN Word
3 forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To Int
m forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To StrictSeq (Timelock era)
xs
      TimeStart SlotNo
m -> forall t. t -> Word -> Encode 'Open t
Sum forall era. SlotNo -> TimelockRaw era
TimeStart Word
4 forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To SlotNo
m
      TimeExpire SlotNo
m -> forall t. t -> Word -> Encode 'Open t
Sum forall era. SlotNo -> TimelockRaw era
TimeExpire Word
5 forall (w :: Wrapped) a t (r :: Density).
Encode w (a -> t) -> Encode ('Closed r) a -> Encode w t
!> forall t. EncCBOR t => t -> Encode ('Closed 'Dense) t
To SlotNo
m

-- This instance allows us to derive instance DecCBOR (Annotator (Timelock crypto)).
-- Since Timelock is a newtype around (Memo (Timelock crypto)).

instance Era era => DecCBOR (Annotator (TimelockRaw era)) where
  decCBOR :: forall s. Decoder s (Annotator (TimelockRaw era))
decCBOR = forall (w :: Wrapped) t s. Decode w t -> Decoder s t
decode (forall t.
Text -> (Word -> Decode 'Open t) -> Decode ('Closed 'Dense) t
Summands Text
"TimelockRaw" Word -> Decode 'Open (Annotator (TimelockRaw era))
decRaw)
    where
      decRaw :: Word -> Decode 'Open (Annotator (TimelockRaw era))
      decRaw :: Word -> Decode 'Open (Annotator (TimelockRaw era))
decRaw Word
0 = forall (w :: Wrapped) t1. Decode w t1 -> Decode w (Annotator t1)
Ann (forall t. t -> Decode 'Open t
SumD forall era. KeyHash 'Witness (EraCrypto era) -> TimelockRaw era
Signature forall (w1 :: Wrapped) a t (w :: Density).
Decode w1 (a -> t) -> Decode ('Closed w) a -> Decode w1 t
<! forall t (w :: Wrapped). DecCBOR t => Decode w t
From)
      decRaw Word
1 = forall (w :: Wrapped) t1. Decode w t1 -> Decode w (Annotator t1)
Ann (forall t. t -> Decode 'Open t
SumD forall era. StrictSeq (Timelock era) -> TimelockRaw era
AllOf) forall (w1 :: Wrapped) a t (d :: Density).
Decode w1 (Annotator (a -> t))
-> Decode ('Closed d) (Annotator a) -> Decode w1 (Annotator t)
<*! forall t. (forall s. Decoder s t) -> Decode ('Closed 'Dense) t
D (forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a s. DecCBOR a => Decoder s a
decCBOR)
      decRaw Word
2 = forall (w :: Wrapped) t1. Decode w t1 -> Decode w (Annotator t1)
Ann (forall t. t -> Decode 'Open t
SumD forall era. StrictSeq (Timelock era) -> TimelockRaw era
AnyOf) forall (w1 :: Wrapped) a t (d :: Density).
Decode w1 (Annotator (a -> t))
-> Decode ('Closed d) (Annotator a) -> Decode w1 (Annotator t)
<*! forall t. (forall s. Decoder s t) -> Decode ('Closed 'Dense) t
D (forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a s. DecCBOR a => Decoder s a
decCBOR)
      decRaw Word
3 = forall (w :: Wrapped) t1. Decode w t1 -> Decode w (Annotator t1)
Ann (forall t. t -> Decode 'Open t
SumD forall era. Int -> StrictSeq (Timelock era) -> TimelockRaw era
MOfN) forall (w1 :: Wrapped) a t (d :: Density).
Decode w1 (Annotator (a -> t))
-> Decode ('Closed d) (Annotator a) -> Decode w1 (Annotator t)
<*! forall (w :: Wrapped) t1. Decode w t1 -> Decode w (Annotator t1)
Ann forall t (w :: Wrapped). DecCBOR t => Decode w t
From forall (w1 :: Wrapped) a t (d :: Density).
Decode w1 (Annotator (a -> t))
-> Decode ('Closed d) (Annotator a) -> Decode w1 (Annotator t)
<*! forall t. (forall s. Decoder s t) -> Decode ('Closed 'Dense) t
D (forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a s. DecCBOR a => Decoder s a
decCBOR)
      decRaw Word
4 = forall (w :: Wrapped) t1. Decode w t1 -> Decode w (Annotator t1)
Ann (forall t. t -> Decode 'Open t
SumD forall era. SlotNo -> TimelockRaw era
TimeStart forall (w1 :: Wrapped) a t (w :: Density).
Decode w1 (a -> t) -> Decode ('Closed w) a -> Decode w1 t
<! forall t (w :: Wrapped). DecCBOR t => Decode w t
From)
      decRaw Word
5 = forall (w :: Wrapped) t1. Decode w t1 -> Decode w (Annotator t1)
Ann (forall t. t -> Decode 'Open t
SumD forall era. SlotNo -> TimelockRaw era
TimeExpire forall (w1 :: Wrapped) a t (w :: Density).
Decode w1 (a -> t) -> Decode ('Closed w) a -> Decode w1 t
<! forall t (w :: Wrapped). DecCBOR t => Decode w t
From)
      decRaw Word
n = forall (w :: Wrapped) t. Word -> Decode w t
Invalid Word
n

-- =================================================================
-- Native Scripts are Memoized TimelockRaw.
-- The patterns give the appearence that the mutual recursion is not present.
-- They rely on memoBytes, and TimelockRaw to memoize each constructor of Timelock
-- =================================================================

newtype Timelock era = TimelockConstr (MemoBytes TimelockRaw era)
  deriving (Timelock era -> Timelock era -> Bool
forall era. Timelock era -> Timelock era -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Timelock era -> Timelock era -> Bool
$c/= :: forall era. Timelock era -> Timelock era -> Bool
== :: Timelock era -> Timelock era -> Bool
$c== :: forall era. Timelock era -> Timelock era -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall era x. Rep (Timelock era) x -> Timelock era
forall era x. Timelock era -> Rep (Timelock era) x
$cto :: forall era x. Rep (Timelock era) x -> Timelock era
$cfrom :: forall era x. Timelock era -> Rep (Timelock era) x
Generic)
  deriving newtype (Timelock era -> Encoding
(forall t. ToCBOR t => Proxy t -> Size)
-> Proxy [Timelock era] -> Size
(forall t. ToCBOR t => Proxy t -> Size)
-> Proxy (Timelock era) -> Size
forall {era}. Typeable era => Typeable (Timelock era)
forall era. Typeable era => Timelock era -> Encoding
forall a.
Typeable a
-> (a -> Encoding)
-> ((forall t. ToCBOR t => Proxy t -> Size) -> Proxy a -> Size)
-> ((forall t. ToCBOR t => Proxy t -> Size) -> Proxy [a] -> Size)
-> ToCBOR a
forall era.
Typeable era =>
(forall t. ToCBOR t => Proxy t -> Size)
-> Proxy [Timelock era] -> Size
forall era.
Typeable era =>
(forall t. ToCBOR t => Proxy t -> Size)
-> Proxy (Timelock era) -> Size
encodedListSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size)
-> Proxy [Timelock era] -> Size
$cencodedListSizeExpr :: forall era.
Typeable era =>
(forall t. ToCBOR t => Proxy t -> Size)
-> Proxy [Timelock era] -> Size
encodedSizeExpr :: (forall t. ToCBOR t => Proxy t -> Size)
-> Proxy (Timelock era) -> Size
$cencodedSizeExpr :: forall era.
Typeable era =>
(forall t. ToCBOR t => Proxy t -> Size)
-> Proxy (Timelock era) -> Size
toCBOR :: Timelock era -> Encoding
$ctoCBOR :: forall era. Typeable era => Timelock era -> Encoding
ToCBOR, Context -> Timelock era -> IO (Maybe ThunkInfo)
Proxy (Timelock era) -> String
forall era.
Era era =>
Context -> Timelock era -> IO (Maybe ThunkInfo)
forall era. Era era => Proxy (Timelock era) -> String
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy (Timelock era) -> String
$cshowTypeOf :: forall era. Era era => Proxy (Timelock era) -> String
wNoThunks :: Context -> Timelock era -> IO (Maybe ThunkInfo)
$cwNoThunks :: forall era.
Era era =>
Context -> Timelock era -> IO (Maybe ThunkInfo)
noThunks :: Context -> Timelock era -> IO (Maybe ThunkInfo)
$cnoThunks :: forall era.
Era era =>
Context -> Timelock era -> IO (Maybe ThunkInfo)
NoThunks, Timelock era -> ()
forall era. Timelock era -> ()
forall a. (a -> ()) -> NFData a
rnf :: Timelock era -> ()
$crnf :: forall era. Timelock era -> ()
NFData, Timelock era -> Int
Timelock era -> ByteString
forall era. Timelock era -> Int
forall era. Timelock era -> ByteString
forall t.
(t -> ByteString)
-> (t -> Int)
-> (forall c index.
    HashAlgorithm (HASH c) =>
    Proxy c -> Proxy index -> t -> SafeHash c index)
-> SafeToHash t
forall c index.
HashAlgorithm (HASH c) =>
Proxy c -> Proxy index -> Timelock era -> SafeHash c index
forall era c index.
HashAlgorithm (HASH c) =>
Proxy c -> Proxy index -> Timelock era -> SafeHash c index
makeHashWithExplicitProxys :: forall c index.
HashAlgorithm (HASH c) =>
Proxy c -> Proxy index -> Timelock era -> SafeHash c index
$cmakeHashWithExplicitProxys :: forall era c index.
HashAlgorithm (HASH c) =>
Proxy c -> Proxy index -> Timelock era -> SafeHash c index
originalBytesSize :: Timelock era -> Int
$coriginalBytesSize :: forall era. Timelock era -> Int
originalBytes :: Timelock era -> ByteString
$coriginalBytes :: forall era. Timelock era -> ByteString
SafeToHash)

instance Era era => EncCBOR (Timelock era)

instance Memoized Timelock where
  type RawType Timelock = TimelockRaw

deriving instance HashAlgorithm (HASH (EraCrypto era)) => Show (Timelock era)

instance EqRaw (Timelock era) where
  eqRaw :: Timelock era -> Timelock era -> Bool
eqRaw = forall era. Timelock era -> Timelock era -> Bool
eqTimelockRaw

deriving via
  Mem TimelockRaw era
  instance
    Era era => DecCBOR (Annotator (Timelock era))

-- | Since Timelock scripts are a strictly backwards compatible extension of
-- MultiSig scripts, we can use the same 'scriptPrefixTag' tag here as we did
-- for the ValidateScript instance in MultiSig
instance Crypto c => EraScript (AllegraEra c) where
  type Script (AllegraEra c) = Timelock (AllegraEra c)
  type NativeScript (AllegraEra c) = Timelock (AllegraEra c)

  upgradeScript :: EraScript (PreviousEra (AllegraEra c)) =>
Script (PreviousEra (AllegraEra c)) -> Script (AllegraEra c)
upgradeScript = \case
    RequireSignature KeyHash 'Witness (EraCrypto (ShelleyEra c))
keyHash -> forall era.
ShelleyEraScript era =>
KeyHash 'Witness (EraCrypto era) -> NativeScript era
RequireSignature KeyHash 'Witness (EraCrypto (ShelleyEra c))
keyHash
    RequireAllOf StrictSeq (NativeScript (ShelleyEra c))
sigs -> forall era.
ShelleyEraScript era =>
StrictSeq (NativeScript era) -> NativeScript era
RequireAllOf forall a b. (a -> b) -> a -> b
$ forall era.
(EraScript era, EraScript (PreviousEra era)) =>
Script (PreviousEra era) -> Script era
upgradeScript forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StrictSeq (NativeScript (ShelleyEra c))
sigs
    RequireAnyOf StrictSeq (NativeScript (ShelleyEra c))
sigs -> forall era.
ShelleyEraScript era =>
StrictSeq (NativeScript era) -> NativeScript era
RequireAnyOf forall a b. (a -> b) -> a -> b
$ forall era.
(EraScript era, EraScript (PreviousEra era)) =>
Script (PreviousEra era) -> Script era
upgradeScript forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StrictSeq (NativeScript (ShelleyEra c))
sigs
    RequireMOf Int
n StrictSeq (NativeScript (ShelleyEra c))
sigs -> forall era.
ShelleyEraScript era =>
Int -> StrictSeq (NativeScript era) -> NativeScript era
RequireMOf Int
n forall a b. (a -> b) -> a -> b
$ forall era.
(EraScript era, EraScript (PreviousEra era)) =>
Script (PreviousEra era) -> Script era
upgradeScript forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StrictSeq (NativeScript (ShelleyEra c))
sigs
    Script (PreviousEra (AllegraEra c))
_ -> forall a. HasCallStack => String -> a
error String
"Impossible: All NativeScripts should have been accounted for"

  scriptPrefixTag :: Script (AllegraEra c) -> ByteString
scriptPrefixTag Script (AllegraEra c)
_script = ByteString
nativeMultiSigTag -- "\x00"

  getNativeScript :: Script (AllegraEra c) -> Maybe (NativeScript (AllegraEra c))
getNativeScript = forall a. a -> Maybe a
Just

  fromNativeScript :: NativeScript (AllegraEra c) -> Script (AllegraEra c)
fromNativeScript = forall a. a -> a
id

instance Crypto c => ShelleyEraScript (AllegraEra c) where
  {-# SPECIALIZE instance ShelleyEraScript (AllegraEra StandardCrypto) #-}

  mkRequireSignature :: KeyHash 'Witness (EraCrypto (AllegraEra c))
-> NativeScript (AllegraEra c)
mkRequireSignature = forall era.
Era era =>
KeyHash 'Witness (EraCrypto era) -> Timelock era
mkRequireSignatureTimelock
  getRequireSignature :: NativeScript (AllegraEra c)
-> Maybe (KeyHash 'Witness (EraCrypto (AllegraEra c)))
getRequireSignature = forall era.
Era era =>
Timelock era -> Maybe (KeyHash 'Witness (EraCrypto era))
getRequireSignatureTimelock

  mkRequireAllOf :: StrictSeq (NativeScript (AllegraEra c))
-> NativeScript (AllegraEra c)
mkRequireAllOf = forall era. Era era => StrictSeq (Timelock era) -> Timelock era
mkRequireAllOfTimelock
  getRequireAllOf :: NativeScript (AllegraEra c)
-> Maybe (StrictSeq (NativeScript (AllegraEra c)))
getRequireAllOf = forall era.
Era era =>
Timelock era -> Maybe (StrictSeq (Timelock era))
getRequireAllOfTimelock

  mkRequireAnyOf :: StrictSeq (NativeScript (AllegraEra c))
-> NativeScript (AllegraEra c)
mkRequireAnyOf = forall era. Era era => StrictSeq (Timelock era) -> Timelock era
mkRequireAnyOfTimelock
  getRequireAnyOf :: NativeScript (AllegraEra c)
-> Maybe (StrictSeq (NativeScript (AllegraEra c)))
getRequireAnyOf = forall era.
Era era =>
Timelock era -> Maybe (StrictSeq (Timelock era))
getRequireAnyOfTimelock

  mkRequireMOf :: Int
-> StrictSeq (NativeScript (AllegraEra c))
-> NativeScript (AllegraEra c)
mkRequireMOf = forall era.
Era era =>
Int -> StrictSeq (Timelock era) -> Timelock era
mkRequireMOfTimelock
  getRequireMOf :: NativeScript (AllegraEra c)
-> Maybe (Int, StrictSeq (NativeScript (AllegraEra c)))
getRequireMOf = forall era.
Era era =>
Timelock era -> Maybe (Int, StrictSeq (Timelock era))
getRequireMOfTimelock

instance Crypto c => AllegraEraScript (AllegraEra c) where
  {-# SPECIALIZE instance AllegraEraScript (AllegraEra StandardCrypto) #-}

  mkTimeStart :: SlotNo -> NativeScript (AllegraEra c)
mkTimeStart = forall era. Era era => SlotNo -> Timelock era
mkTimeStartTimelock
  getTimeStart :: NativeScript (AllegraEra c) -> Maybe SlotNo
getTimeStart = forall era. Era era => Timelock era -> Maybe SlotNo
getTimeStartTimelock

  mkTimeExpire :: SlotNo -> NativeScript (AllegraEra c)
mkTimeExpire = forall era. Era era => SlotNo -> Timelock era
mkTimeExpireTimelock
  getTimeExpire :: NativeScript (AllegraEra c) -> Maybe SlotNo
getTimeExpire = forall era. Era era => Timelock era -> Maybe SlotNo
getTimeExpireTimelock

pattern RequireTimeExpire :: AllegraEraScript era => SlotNo -> NativeScript era
pattern $bRequireTimeExpire :: forall era. AllegraEraScript era => SlotNo -> NativeScript era
$mRequireTimeExpire :: forall {r} {era}.
AllegraEraScript era =>
NativeScript era -> (SlotNo -> r) -> ((# #) -> r) -> r
RequireTimeExpire mslot <- (getTimeExpire -> Just mslot)
  where
    RequireTimeExpire SlotNo
mslot = forall era. AllegraEraScript era => SlotNo -> NativeScript era
mkTimeExpire SlotNo
mslot

pattern RequireTimeStart :: AllegraEraScript era => SlotNo -> NativeScript era
pattern $bRequireTimeStart :: forall era. AllegraEraScript era => SlotNo -> NativeScript era
$mRequireTimeStart :: forall {r} {era}.
AllegraEraScript era =>
NativeScript era -> (SlotNo -> r) -> ((# #) -> r) -> r
RequireTimeStart mslot <- (getTimeStart -> Just mslot)
  where
    RequireTimeStart SlotNo
mslot = forall era. AllegraEraScript era => SlotNo -> NativeScript era
mkTimeStart SlotNo
mslot

{-# COMPLETE
  RequireSignature
  , RequireAllOf
  , RequireAnyOf
  , RequireMOf
  , RequireTimeExpire
  , RequireTimeStart
  #-}

mkRequireSignatureTimelock :: Era era => KeyHash 'Witness (EraCrypto era) -> Timelock era
mkRequireSignatureTimelock :: forall era.
Era era =>
KeyHash 'Witness (EraCrypto era) -> Timelock era
mkRequireSignatureTimelock = forall era (t :: * -> *).
(Era era, EncCBOR (RawType t era), Memoized t) =>
RawType t era -> t era
mkMemoized forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era. KeyHash 'Witness (EraCrypto era) -> TimelockRaw era
Signature
getRequireSignatureTimelock :: Era era => Timelock era -> Maybe (KeyHash 'Witness (EraCrypto era))
getRequireSignatureTimelock :: forall era.
Era era =>
Timelock era -> Maybe (KeyHash 'Witness (EraCrypto era))
getRequireSignatureTimelock (TimelockConstr (Memo (Signature KeyHash 'Witness (EraCrypto era)
kh) ShortByteString
_)) = forall a. a -> Maybe a
Just KeyHash 'Witness (EraCrypto era)
kh
getRequireSignatureTimelock Timelock era
_ = forall a. Maybe a
Nothing

mkRequireAllOfTimelock :: Era era => StrictSeq (Timelock era) -> Timelock era
mkRequireAllOfTimelock :: forall era. Era era => StrictSeq (Timelock era) -> Timelock era
mkRequireAllOfTimelock = forall era (t :: * -> *).
(Era era, EncCBOR (RawType t era), Memoized t) =>
RawType t era -> t era
mkMemoized forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era. StrictSeq (Timelock era) -> TimelockRaw era
AllOf
getRequireAllOfTimelock :: Era era => Timelock era -> Maybe (StrictSeq (Timelock era))
getRequireAllOfTimelock :: forall era.
Era era =>
Timelock era -> Maybe (StrictSeq (Timelock era))
getRequireAllOfTimelock (TimelockConstr (Memo (AllOf StrictSeq (Timelock era)
ms) ShortByteString
_)) = forall a. a -> Maybe a
Just StrictSeq (Timelock era)
ms
getRequireAllOfTimelock Timelock era
_ = forall a. Maybe a
Nothing

mkRequireAnyOfTimelock :: Era era => StrictSeq (Timelock era) -> Timelock era
mkRequireAnyOfTimelock :: forall era. Era era => StrictSeq (Timelock era) -> Timelock era
mkRequireAnyOfTimelock = forall era (t :: * -> *).
(Era era, EncCBOR (RawType t era), Memoized t) =>
RawType t era -> t era
mkMemoized forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era. StrictSeq (Timelock era) -> TimelockRaw era
AnyOf
getRequireAnyOfTimelock :: Era era => Timelock era -> Maybe (StrictSeq (Timelock era))
getRequireAnyOfTimelock :: forall era.
Era era =>
Timelock era -> Maybe (StrictSeq (Timelock era))
getRequireAnyOfTimelock (TimelockConstr (Memo (AnyOf StrictSeq (Timelock era)
ms) ShortByteString
_)) = forall a. a -> Maybe a
Just StrictSeq (Timelock era)
ms
getRequireAnyOfTimelock Timelock era
_ = forall a. Maybe a
Nothing

mkRequireMOfTimelock :: Era era => Int -> StrictSeq (Timelock era) -> Timelock era
mkRequireMOfTimelock :: forall era.
Era era =>
Int -> StrictSeq (Timelock era) -> Timelock era
mkRequireMOfTimelock Int
n = forall era (t :: * -> *).
(Era era, EncCBOR (RawType t era), Memoized t) =>
RawType t era -> t era
mkMemoized forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era. Int -> StrictSeq (Timelock era) -> TimelockRaw era
MOfN Int
n
getRequireMOfTimelock :: Era era => Timelock era -> Maybe (Int, (StrictSeq (Timelock era)))
getRequireMOfTimelock :: forall era.
Era era =>
Timelock era -> Maybe (Int, StrictSeq (Timelock era))
getRequireMOfTimelock (TimelockConstr (Memo (MOfN Int
n StrictSeq (Timelock era)
ms) ShortByteString
_)) = forall a. a -> Maybe a
Just (Int
n, StrictSeq (Timelock era)
ms)
getRequireMOfTimelock Timelock era
_ = forall a. Maybe a
Nothing

mkTimeStartTimelock :: Era era => SlotNo -> Timelock era
mkTimeStartTimelock :: forall era. Era era => SlotNo -> Timelock era
mkTimeStartTimelock = forall era (t :: * -> *).
(Era era, EncCBOR (RawType t era), Memoized t) =>
RawType t era -> t era
mkMemoized forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era. SlotNo -> TimelockRaw era
TimeStart
getTimeStartTimelock :: Era era => Timelock era -> Maybe SlotNo
getTimeStartTimelock :: forall era. Era era => Timelock era -> Maybe SlotNo
getTimeStartTimelock (TimelockConstr (Memo (TimeStart SlotNo
mslot) ShortByteString
_)) = forall a. a -> Maybe a
Just SlotNo
mslot
getTimeStartTimelock Timelock era
_ = forall a. Maybe a
Nothing

mkTimeExpireTimelock :: Era era => SlotNo -> Timelock era
mkTimeExpireTimelock :: forall era. Era era => SlotNo -> Timelock era
mkTimeExpireTimelock = forall era (t :: * -> *).
(Era era, EncCBOR (RawType t era), Memoized t) =>
RawType t era -> t era
mkMemoized forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall era. SlotNo -> TimelockRaw era
TimeExpire
getTimeExpireTimelock :: Era era => Timelock era -> Maybe SlotNo
getTimeExpireTimelock :: forall era. Era era => Timelock era -> Maybe SlotNo
getTimeExpireTimelock (TimelockConstr (Memo (TimeExpire SlotNo
mslot) ShortByteString
_)) = forall a. a -> Maybe a
Just SlotNo
mslot
getTimeExpireTimelock Timelock era
_ = forall a. Maybe a
Nothing

-- =================================================================
-- Evaluating and validating a Timelock

-- | less-than-equal comparison, where Nothing is negative infinity
lteNegInfty :: SlotNo -> StrictMaybe SlotNo -> Bool
lteNegInfty :: SlotNo -> StrictMaybe SlotNo -> Bool
lteNegInfty SlotNo
_ StrictMaybe SlotNo
SNothing = Bool
False -- i > -∞
lteNegInfty SlotNo
i (SJust SlotNo
j) = SlotNo
i forall a. Ord a => a -> a -> Bool
<= SlotNo
j

-- | less-than-equal comparison, where Nothing is positive infinity
ltePosInfty :: StrictMaybe SlotNo -> SlotNo -> Bool
ltePosInfty :: StrictMaybe SlotNo -> SlotNo -> Bool
ltePosInfty StrictMaybe SlotNo
SNothing SlotNo
_ = Bool
False -- ∞ > j
ltePosInfty (SJust SlotNo
i) SlotNo
j = SlotNo
i forall a. Ord a => a -> a -> Bool
<= SlotNo
j

evalTimelock ::
  AllegraEraScript era =>
  Set.Set (KeyHash 'Witness (EraCrypto era)) ->
  ValidityInterval ->
  NativeScript era ->
  Bool
evalTimelock :: forall era.
AllegraEraScript era =>
Set (KeyHash 'Witness (EraCrypto era))
-> ValidityInterval -> NativeScript era -> Bool
evalTimelock Set (KeyHash 'Witness (EraCrypto era))
vhks (ValidityInterval StrictMaybe SlotNo
txStart StrictMaybe SlotNo
txExp) = NativeScript era -> Bool
go
  where
    -- The important part of this validator is that it will stop as soon as it reaches the
    -- required number of valid scripts
    isValidMOf :: Int -> StrictSeq (NativeScript era) -> Bool
isValidMOf Int
n StrictSeq (NativeScript era)
SSeq.Empty = Int
n forall a. Ord a => a -> a -> Bool
<= Int
0
    isValidMOf Int
n (NativeScript era
ts SSeq.:<| StrictSeq (NativeScript era)
tss) =
      Int
n forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| if NativeScript era -> Bool
go NativeScript era
ts then Int -> StrictSeq (NativeScript era) -> Bool
isValidMOf (Int
n forall a. Num a => a -> a -> a
- Int
1) StrictSeq (NativeScript era)
tss else Int -> StrictSeq (NativeScript era) -> Bool
isValidMOf Int
n StrictSeq (NativeScript era)
tss
    go :: NativeScript era -> Bool
go = \case
      RequireTimeStart SlotNo
lockStart -> SlotNo
lockStart SlotNo -> StrictMaybe SlotNo -> Bool
`lteNegInfty` StrictMaybe SlotNo
txStart
      RequireTimeExpire SlotNo
lockExp -> StrictMaybe SlotNo
txExp StrictMaybe SlotNo -> SlotNo -> Bool
`ltePosInfty` SlotNo
lockExp
      RequireSignature KeyHash 'Witness (EraCrypto era)
hash -> KeyHash 'Witness (EraCrypto era)
hash forall a. Ord a => a -> Set a -> Bool
`Set.member` Set (KeyHash 'Witness (EraCrypto era))
vhks
      RequireAllOf StrictSeq (NativeScript era)
xs -> forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all NativeScript era -> Bool
go StrictSeq (NativeScript era)
xs
      RequireAnyOf StrictSeq (NativeScript era)
xs -> forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any NativeScript era -> Bool
go StrictSeq (NativeScript era)
xs
      RequireMOf Int
m StrictSeq (NativeScript era)
xs -> Int -> StrictSeq (NativeScript era) -> Bool
isValidMOf Int
m StrictSeq (NativeScript era)
xs

-- =========================================================
-- Operations on Timelock scripts

-- | Test if a slot is in the Validity interval. Recall that a ValidityInterval
--   is a half Open interval, that is why we use (slot < top)
inInterval :: SlotNo -> ValidityInterval -> Bool
inInterval :: SlotNo -> ValidityInterval -> Bool
inInterval SlotNo
_slot (ValidityInterval StrictMaybe SlotNo
SNothing StrictMaybe SlotNo
SNothing) = Bool
True
inInterval SlotNo
slot (ValidityInterval StrictMaybe SlotNo
SNothing (SJust SlotNo
top)) = SlotNo
slot forall a. Ord a => a -> a -> Bool
< SlotNo
top
inInterval SlotNo
slot (ValidityInterval (SJust SlotNo
bottom) StrictMaybe SlotNo
SNothing) = SlotNo
bottom forall a. Ord a => a -> a -> Bool
<= SlotNo
slot
inInterval SlotNo
slot (ValidityInterval (SJust SlotNo
bottom) (SJust SlotNo
top)) =
  SlotNo
bottom forall a. Ord a => a -> a -> Bool
<= SlotNo
slot Bool -> Bool -> Bool
&& SlotNo
slot forall a. Ord a => a -> a -> Bool
< SlotNo
top

showTimelock :: AllegraEraScript era => NativeScript era -> String
showTimelock :: forall era. AllegraEraScript era => NativeScript era -> String
showTimelock (RequireTimeStart (SlotNo Word64
i)) = String
"(Start >= " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Word64
i forall a. [a] -> [a] -> [a]
++ String
")"
showTimelock (RequireTimeExpire (SlotNo Word64
i)) = String
"(Expire < " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Word64
i forall a. [a] -> [a] -> [a]
++ String
")"
showTimelock (RequireAllOf StrictSeq (NativeScript era)
xs) = String
"(AllOf " forall a. [a] -> [a] -> [a]
++ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall {era}.
AllegraEraScript era =>
String -> NativeScript era -> String
accum String
")" StrictSeq (NativeScript era)
xs
  where
    accum :: String -> NativeScript era -> String
accum String
ans NativeScript era
x = forall era. AllegraEraScript era => NativeScript era -> String
showTimelock NativeScript era
x forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ String
ans
showTimelock (RequireAnyOf StrictSeq (NativeScript era)
xs) = String
"(AnyOf " forall a. [a] -> [a] -> [a]
++ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall {era}.
AllegraEraScript era =>
String -> NativeScript era -> String
accum String
")" StrictSeq (NativeScript era)
xs
  where
    accum :: String -> NativeScript era -> String
accum String
ans NativeScript era
x = forall era. AllegraEraScript era => NativeScript era -> String
showTimelock NativeScript era
x forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ String
ans
showTimelock (RequireMOf Int
m StrictSeq (NativeScript era)
xs) = String
"(MOf " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Int
m forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall {era}.
AllegraEraScript era =>
String -> NativeScript era -> String
accum String
")" StrictSeq (NativeScript era)
xs
  where
    accum :: String -> NativeScript era -> String
accum String
ans NativeScript era
x = forall era. AllegraEraScript era => NativeScript era -> String
showTimelock NativeScript era
x forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ String
ans
showTimelock (RequireSignature KeyHash 'Witness (EraCrypto era)
hash) = String
"(Signature " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show KeyHash 'Witness (EraCrypto era)
hash forall a. [a] -> [a] -> [a]
++ String
")"

-- | Check the equality of two underlying types, while ignoring their binary
-- representation, which `Eq` instance normally does. This is used for testing.
eqTimelockRaw :: Timelock era -> Timelock era -> Bool
eqTimelockRaw :: forall era. Timelock era -> Timelock era -> Bool
eqTimelockRaw Timelock era
t1 Timelock era
t2 = forall era. TimelockRaw era -> TimelockRaw era -> Bool
go (forall (t :: * -> *) era. Memoized t => t era -> RawType t era
getMemoRawType Timelock era
t1) (forall (t :: * -> *) era. Memoized t => t era -> RawType t era
getMemoRawType Timelock era
t2)
  where
    seqEq :: StrictSeq (Timelock era) -> StrictSeq (Timelock era) -> Bool
seqEq StrictSeq (Timelock era)
Empty StrictSeq (Timelock era)
Empty = Bool
True
    seqEq (Timelock era
x :<| StrictSeq (Timelock era)
xs) (Timelock era
y :<| StrictSeq (Timelock era)
ys) = forall era. Timelock era -> Timelock era -> Bool
eqTimelockRaw Timelock era
x Timelock era
y Bool -> Bool -> Bool
&& StrictSeq (Timelock era) -> StrictSeq (Timelock era) -> Bool
seqEq StrictSeq (Timelock era)
xs StrictSeq (Timelock era)
ys
    seqEq StrictSeq (Timelock era)
_ StrictSeq (Timelock era)
_ = Bool
False
    go :: TimelockRaw era -> TimelockRaw era -> Bool
go (Signature KeyHash 'Witness (EraCrypto era)
kh1) (Signature KeyHash 'Witness (EraCrypto era)
kh2) = KeyHash 'Witness (EraCrypto era)
kh1 forall a. Eq a => a -> a -> Bool
== KeyHash 'Witness (EraCrypto era)
kh2
    go (AllOf StrictSeq (Timelock era)
ts1) (AllOf StrictSeq (Timelock era)
ts2) = forall {era}.
StrictSeq (Timelock era) -> StrictSeq (Timelock era) -> Bool
seqEq StrictSeq (Timelock era)
ts1 StrictSeq (Timelock era)
ts2
    go (AnyOf StrictSeq (Timelock era)
ts1) (AnyOf StrictSeq (Timelock era)
ts2) = forall {era}.
StrictSeq (Timelock era) -> StrictSeq (Timelock era) -> Bool
seqEq StrictSeq (Timelock era)
ts1 StrictSeq (Timelock era)
ts2
    go (MOfN Int
n1 StrictSeq (Timelock era)
ts1) (MOfN Int
n2 StrictSeq (Timelock era)
ts2) = Int
n1 forall a. Eq a => a -> a -> Bool
== Int
n2 Bool -> Bool -> Bool
&& forall {era}.
StrictSeq (Timelock era) -> StrictSeq (Timelock era) -> Bool
seqEq StrictSeq (Timelock era)
ts1 StrictSeq (Timelock era)
ts2
    go (TimeStart SlotNo
sn1) (TimeStart SlotNo
sn2) = SlotNo
sn1 forall a. Eq a => a -> a -> Bool
== SlotNo
sn2
    go (TimeExpire SlotNo
sn1) (TimeExpire SlotNo
sn2) = SlotNo
sn1 forall a. Eq a => a -> a -> Bool
== SlotNo
sn2
    go TimelockRaw era
_ TimelockRaw era
_ = Bool
False