{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

{- |
Module      : Haskoin.Script.Common
Copyright   : No rights reserved
License     : MIT
Maintainer  : jprupp@protonmail.ch
Stability   : experimental
Portability : POSIX

Common script-related functions and data types.
-}
module Haskoin.Script.Common (
    -- * Scripts
    ScriptOp (..),
    Script (..),
    PushDataType (..),
    isPushOp,
    opPushData,
    intToScriptOp,
    scriptOpToInt,
) where

import Control.DeepSeq
import Control.Monad
import Data.Binary (Binary (..))
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.Bytes.Get
import Data.Bytes.Put
import Data.Bytes.Serial
import Data.Either (fromRight)
import Data.Hashable
import Data.Serialize (Serialize (..))
import Data.Word (Word8)
import GHC.Generics (Generic)

{- | Data type representing a transaction script. Scripts are defined as lists
 of script operators 'ScriptOp'. Scripts are used to:

 * Define the spending conditions in the output of a transaction.
 * Provide signatures in the input of a transaction (except SegWit).

 SigWit only: the segregated witness data structure, and not the input script,
 contains signatures and redeem script for pay-to-witness-script and
 pay-to-witness-public-key-hash transactions.
-}
newtype Script = Script
    { -- | script operators defining this script
      Script -> [ScriptOp]
scriptOps :: [ScriptOp]
    }
    deriving (Script -> Script -> Bool
(Script -> Script -> Bool)
-> (Script -> Script -> Bool) -> Eq Script
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Script -> Script -> Bool
$c/= :: Script -> Script -> Bool
== :: Script -> Script -> Bool
$c== :: Script -> Script -> Bool
Eq, Int -> Script -> ShowS
[Script] -> ShowS
Script -> String
(Int -> Script -> ShowS)
-> (Script -> String) -> ([Script] -> ShowS) -> Show Script
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Script] -> ShowS
$cshowList :: [Script] -> ShowS
show :: Script -> String
$cshow :: Script -> String
showsPrec :: Int -> Script -> ShowS
$cshowsPrec :: Int -> Script -> ShowS
Show, ReadPrec [Script]
ReadPrec Script
Int -> ReadS Script
ReadS [Script]
(Int -> ReadS Script)
-> ReadS [Script]
-> ReadPrec Script
-> ReadPrec [Script]
-> Read Script
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Script]
$creadListPrec :: ReadPrec [Script]
readPrec :: ReadPrec Script
$creadPrec :: ReadPrec Script
readList :: ReadS [Script]
$creadList :: ReadS [Script]
readsPrec :: Int -> ReadS Script
$creadsPrec :: Int -> ReadS Script
Read, (forall x. Script -> Rep Script x)
-> (forall x. Rep Script x -> Script) -> Generic Script
forall x. Rep Script x -> Script
forall x. Script -> Rep Script x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Script x -> Script
$cfrom :: forall x. Script -> Rep Script x
Generic, Int -> Script -> Int
Script -> Int
(Int -> Script -> Int) -> (Script -> Int) -> Hashable Script
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Script -> Int
$chash :: Script -> Int
hashWithSalt :: Int -> Script -> Int
$chashWithSalt :: Int -> Script -> Int
Hashable, Script -> ()
(Script -> ()) -> NFData Script
forall a. (a -> ()) -> NFData a
rnf :: Script -> ()
$crnf :: Script -> ()
NFData)

instance Serial Script where
    deserialize :: m Script
deserialize =
        [ScriptOp] -> Script
Script ([ScriptOp] -> Script) -> m [ScriptOp] -> m Script
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m [ScriptOp]
getScriptOps
      where
        getScriptOps :: m [ScriptOp]
getScriptOps = do
            Bool
empty <- m Bool
forall (m :: * -> *). MonadGet m => m Bool
isEmpty
            if Bool
empty
                then [ScriptOp] -> m [ScriptOp]
forall (m :: * -> *) a. Monad m => a -> m a
return []
                else (:) (ScriptOp -> [ScriptOp] -> [ScriptOp])
-> m ScriptOp -> m ([ScriptOp] -> [ScriptOp])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m ScriptOp
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize m ([ScriptOp] -> [ScriptOp]) -> m [ScriptOp] -> m [ScriptOp]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m [ScriptOp]
getScriptOps

    serialize :: Script -> m ()
serialize (Script [ScriptOp]
ops) = [ScriptOp] -> (ScriptOp -> m ()) -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ScriptOp]
ops ScriptOp -> m ()
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize

instance Binary Script where
    put :: Script -> Put
put = Script -> Put
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize
    get :: Get Script
get = Get Script
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize

instance Serialize Script where
    put :: Putter Script
put = Putter Script
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize
    get :: Get Script
get = Get Script
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize

-- | Data type representing the type of an OP_PUSHDATA opcode.
data PushDataType
    = -- | next opcode bytes is data to be pushed
      OPCODE
    | -- | next byte contains number of bytes of data to be pushed
      OPDATA1
    | -- | next two bytes contains number of bytes to be pushed
      OPDATA2
    | -- | next four bytes contains the number of bytes to be pushed
      OPDATA4
    deriving (Int -> PushDataType -> ShowS
[PushDataType] -> ShowS
PushDataType -> String
(Int -> PushDataType -> ShowS)
-> (PushDataType -> String)
-> ([PushDataType] -> ShowS)
-> Show PushDataType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PushDataType] -> ShowS
$cshowList :: [PushDataType] -> ShowS
show :: PushDataType -> String
$cshow :: PushDataType -> String
showsPrec :: Int -> PushDataType -> ShowS
$cshowsPrec :: Int -> PushDataType -> ShowS
Show, ReadPrec [PushDataType]
ReadPrec PushDataType
Int -> ReadS PushDataType
ReadS [PushDataType]
(Int -> ReadS PushDataType)
-> ReadS [PushDataType]
-> ReadPrec PushDataType
-> ReadPrec [PushDataType]
-> Read PushDataType
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [PushDataType]
$creadListPrec :: ReadPrec [PushDataType]
readPrec :: ReadPrec PushDataType
$creadPrec :: ReadPrec PushDataType
readList :: ReadS [PushDataType]
$creadList :: ReadS [PushDataType]
readsPrec :: Int -> ReadS PushDataType
$creadsPrec :: Int -> ReadS PushDataType
Read, PushDataType -> PushDataType -> Bool
(PushDataType -> PushDataType -> Bool)
-> (PushDataType -> PushDataType -> Bool) -> Eq PushDataType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PushDataType -> PushDataType -> Bool
$c/= :: PushDataType -> PushDataType -> Bool
== :: PushDataType -> PushDataType -> Bool
$c== :: PushDataType -> PushDataType -> Bool
Eq, (forall x. PushDataType -> Rep PushDataType x)
-> (forall x. Rep PushDataType x -> PushDataType)
-> Generic PushDataType
forall x. Rep PushDataType x -> PushDataType
forall x. PushDataType -> Rep PushDataType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PushDataType x -> PushDataType
$cfrom :: forall x. PushDataType -> Rep PushDataType x
Generic, Int -> PushDataType -> Int
PushDataType -> Int
(Int -> PushDataType -> Int)
-> (PushDataType -> Int) -> Hashable PushDataType
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: PushDataType -> Int
$chash :: PushDataType -> Int
hashWithSalt :: Int -> PushDataType -> Int
$chashWithSalt :: Int -> PushDataType -> Int
Hashable, PushDataType -> ()
(PushDataType -> ()) -> NFData PushDataType
forall a. (a -> ()) -> NFData a
rnf :: PushDataType -> ()
$crnf :: PushDataType -> ()
NFData)

-- | Data type representing an operator allowed inside a 'Script'.
data ScriptOp
    = -- Pushing Data
      OP_PUSHDATA
        !ByteString
        !PushDataType
    | OP_0
    | OP_1NEGATE
    | OP_RESERVED
    | OP_1
    | OP_2
    | OP_3
    | OP_4
    | OP_5
    | OP_6
    | OP_7
    | OP_8
    | OP_9
    | OP_10
    | OP_11
    | OP_12
    | OP_13
    | OP_14
    | OP_15
    | OP_16
    | -- Flow control
      OP_NOP
    | OP_VER -- reserved
    | OP_IF
    | OP_NOTIF
    | OP_VERIF -- resreved
    | OP_VERNOTIF -- reserved
    | OP_ELSE
    | OP_ENDIF
    | OP_VERIFY
    | OP_RETURN
    | -- Stack operations
      OP_TOALTSTACK
    | OP_FROMALTSTACK
    | OP_IFDUP
    | OP_DEPTH
    | OP_DROP
    | OP_DUP
    | OP_NIP
    | OP_OVER
    | OP_PICK
    | OP_ROLL
    | OP_ROT
    | OP_SWAP
    | OP_TUCK
    | OP_2DROP
    | OP_2DUP
    | OP_3DUP
    | OP_2OVER
    | OP_2ROT
    | OP_2SWAP
    | -- Splice
      OP_CAT
    | OP_SUBSTR
    | OP_LEFT
    | OP_RIGHT
    | OP_SIZE
    | -- Bitwise logic
      OP_INVERT
    | OP_AND
    | OP_OR
    | OP_XOR
    | OP_EQUAL
    | OP_EQUALVERIFY
    | OP_RESERVED1
    | OP_RESERVED2
    | -- Arithmetic
      OP_1ADD
    | OP_1SUB
    | OP_2MUL
    | OP_2DIV
    | OP_NEGATE
    | OP_ABS
    | OP_NOT
    | OP_0NOTEQUAL
    | OP_ADD
    | OP_SUB
    | OP_MUL
    | OP_DIV
    | OP_MOD
    | OP_LSHIFT
    | OP_RSHIFT
    | OP_BOOLAND
    | OP_BOOLOR
    | OP_NUMEQUAL
    | OP_NUMEQUALVERIFY
    | OP_NUMNOTEQUAL
    | OP_LESSTHAN
    | OP_GREATERTHAN
    | OP_LESSTHANOREQUAL
    | OP_GREATERTHANOREQUAL
    | OP_MIN
    | OP_MAX
    | OP_WITHIN
    | -- Crypto
      OP_RIPEMD160
    | OP_SHA1
    | OP_SHA256
    | OP_HASH160
    | OP_HASH256
    | OP_CODESEPARATOR
    | OP_CHECKSIG
    | OP_CHECKSIGVERIFY
    | OP_CHECKMULTISIG
    | OP_CHECKMULTISIGVERIFY
    | -- Expansion
      OP_NOP1
    | OP_CHECKLOCKTIMEVERIFY
    | OP_CHECKSEQUENCEVERIFY
    | OP_NOP4
    | OP_NOP5
    | OP_NOP6
    | OP_NOP7
    | OP_NOP8
    | OP_NOP9
    | OP_NOP10
    | -- Bitcoin Cash Nov 2018 hard fork
      OP_CHECKDATASIG
    | OP_CHECKDATASIGVERIFY
    | -- Bitcoin Cash May 2020 hard fork
      OP_REVERSEBYTES
    | -- Other
      OP_PUBKEYHASH
    | OP_PUBKEY
    | OP_INVALIDOPCODE !Word8
    deriving (Int -> ScriptOp -> ShowS
[ScriptOp] -> ShowS
ScriptOp -> String
(Int -> ScriptOp -> ShowS)
-> (ScriptOp -> String) -> ([ScriptOp] -> ShowS) -> Show ScriptOp
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ScriptOp] -> ShowS
$cshowList :: [ScriptOp] -> ShowS
show :: ScriptOp -> String
$cshow :: ScriptOp -> String
showsPrec :: Int -> ScriptOp -> ShowS
$cshowsPrec :: Int -> ScriptOp -> ShowS
Show, ReadPrec [ScriptOp]
ReadPrec ScriptOp
Int -> ReadS ScriptOp
ReadS [ScriptOp]
(Int -> ReadS ScriptOp)
-> ReadS [ScriptOp]
-> ReadPrec ScriptOp
-> ReadPrec [ScriptOp]
-> Read ScriptOp
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [ScriptOp]
$creadListPrec :: ReadPrec [ScriptOp]
readPrec :: ReadPrec ScriptOp
$creadPrec :: ReadPrec ScriptOp
readList :: ReadS [ScriptOp]
$creadList :: ReadS [ScriptOp]
readsPrec :: Int -> ReadS ScriptOp
$creadsPrec :: Int -> ReadS ScriptOp
Read, ScriptOp -> ScriptOp -> Bool
(ScriptOp -> ScriptOp -> Bool)
-> (ScriptOp -> ScriptOp -> Bool) -> Eq ScriptOp
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ScriptOp -> ScriptOp -> Bool
$c/= :: ScriptOp -> ScriptOp -> Bool
== :: ScriptOp -> ScriptOp -> Bool
$c== :: ScriptOp -> ScriptOp -> Bool
Eq, (forall x. ScriptOp -> Rep ScriptOp x)
-> (forall x. Rep ScriptOp x -> ScriptOp) -> Generic ScriptOp
forall x. Rep ScriptOp x -> ScriptOp
forall x. ScriptOp -> Rep ScriptOp x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ScriptOp x -> ScriptOp
$cfrom :: forall x. ScriptOp -> Rep ScriptOp x
Generic, Int -> ScriptOp -> Int
ScriptOp -> Int
(Int -> ScriptOp -> Int) -> (ScriptOp -> Int) -> Hashable ScriptOp
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: ScriptOp -> Int
$chash :: ScriptOp -> Int
hashWithSalt :: Int -> ScriptOp -> Int
$chashWithSalt :: Int -> ScriptOp -> Int
Hashable, ScriptOp -> ()
(ScriptOp -> ()) -> NFData ScriptOp
forall a. (a -> ()) -> NFData a
rnf :: ScriptOp -> ()
$crnf :: ScriptOp -> ()
NFData)

instance Serial ScriptOp where
    deserialize :: m ScriptOp
deserialize = Word8 -> m ScriptOp
forall (m :: * -> *). MonadGet m => Word8 -> m ScriptOp
go (Word8 -> m ScriptOp) -> (Word8 -> Word8) -> Word8 -> m ScriptOp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> m ScriptOp) -> m Word8 -> m ScriptOp
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m Word8
forall (m :: * -> *). MonadGet m => m Word8
getWord8
      where
        go :: Word8 -> m ScriptOp
go Word8
op
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x00 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_0
            | Word8
op Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
0x4b = do
                ByteString
payload <- Int -> m ByteString
forall (m :: * -> *). MonadGet m => Int -> m ByteString
getByteString (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
op)
                ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOp -> m ScriptOp) -> ScriptOp -> m ScriptOp
forall a b. (a -> b) -> a -> b
$ ByteString -> PushDataType -> ScriptOp
OP_PUSHDATA ByteString
payload PushDataType
OPCODE
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x4c = do
                Word8
len <- m Word8
forall (m :: * -> *). MonadGet m => m Word8
getWord8
                ByteString
payload <- Int -> m ByteString
forall (m :: * -> *). MonadGet m => Int -> m ByteString
getByteString (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
len)
                ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOp -> m ScriptOp) -> ScriptOp -> m ScriptOp
forall a b. (a -> b) -> a -> b
$ ByteString -> PushDataType -> ScriptOp
OP_PUSHDATA ByteString
payload PushDataType
OPDATA1
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x4d = do
                Word16
len <- m Word16
forall (m :: * -> *). MonadGet m => m Word16
getWord16le
                ByteString
payload <- Int -> m ByteString
forall (m :: * -> *). MonadGet m => Int -> m ByteString
getByteString (Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
len)
                ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOp -> m ScriptOp) -> ScriptOp -> m ScriptOp
forall a b. (a -> b) -> a -> b
$ ByteString -> PushDataType -> ScriptOp
OP_PUSHDATA ByteString
payload PushDataType
OPDATA2
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x4e = do
                Word32
len <- m Word32
forall (m :: * -> *). MonadGet m => m Word32
getWord32le
                ByteString
payload <- Int -> m ByteString
forall (m :: * -> *). MonadGet m => Int -> m ByteString
getByteString (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
len)
                ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOp -> m ScriptOp) -> ScriptOp -> m ScriptOp
forall a b. (a -> b) -> a -> b
$ ByteString -> PushDataType -> ScriptOp
OP_PUSHDATA ByteString
payload PushDataType
OPDATA4
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x4f = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_1NEGATE
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x50 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_RESERVED
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x51 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_1
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x52 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_2
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x53 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_3
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x54 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_4
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x55 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_5
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x56 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_6
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x57 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_7
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x58 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_8
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x59 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_9
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x5a = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_10
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x5b = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_11
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x5c = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_12
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x5d = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_13
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x5e = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_14
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x5f = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_15
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x60 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_16
            -- Flow control
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x61 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x62 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_VER -- reserved
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x63 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_IF
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x64 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOTIF
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x65 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_VERIF -- reserved
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x66 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_VERNOTIF -- reserved
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x67 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_ELSE
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x68 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_ENDIF
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x69 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_VERIFY
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x6a = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_RETURN
            -- Stack
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x6b = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_TOALTSTACK
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x6c = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_FROMALTSTACK
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x6d = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_2DROP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x6e = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_2DUP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x6f = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_3DUP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x70 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_2OVER
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x71 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_2ROT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x72 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_2SWAP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x73 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_IFDUP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x74 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_DEPTH
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x75 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_DROP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x76 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_DUP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x77 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NIP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x78 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_OVER
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x79 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_PICK
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x7a = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_ROLL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x7b = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_ROT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x7c = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_SWAP
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x7d = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_TUCK
            -- Splice
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x7e = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CAT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x7f = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_SUBSTR
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x80 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_LEFT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x81 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_RIGHT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x82 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_SIZE
            -- Bitwise logic
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x83 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_INVERT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x84 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_AND
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x85 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_OR
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x86 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_XOR
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x87 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_EQUAL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x88 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_EQUALVERIFY
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x89 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_RESERVED1
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x8a = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_RESERVED2
            -- Arithmetic
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x8b = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_1ADD
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x8c = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_1SUB
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x8d = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_2MUL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x8e = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_2DIV
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x8f = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NEGATE
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x90 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_ABS
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x91 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x92 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_0NOTEQUAL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x93 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_ADD
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x94 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_SUB
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x95 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_MUL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x96 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_DIV
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x97 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_MOD
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x98 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_LSHIFT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x99 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_RSHIFT
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x9a = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_BOOLAND
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x9b = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_BOOLOR
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x9c = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NUMEQUAL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x9d = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NUMEQUALVERIFY
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x9e = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NUMNOTEQUAL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x9f = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_LESSTHAN
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa0 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_GREATERTHAN
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa1 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_LESSTHANOREQUAL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa2 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_GREATERTHANOREQUAL
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa3 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_MIN
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa4 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_MAX
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa5 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_WITHIN
            -- Crypto
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa6 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_RIPEMD160
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa7 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_SHA1
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa8 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_SHA256
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xa9 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_HASH160
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xaa = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_HASH256
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xab = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CODESEPARATOR
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xac = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CHECKSIG
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xad = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CHECKSIGVERIFY
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xae = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CHECKMULTISIG
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xaf = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CHECKMULTISIGVERIFY
            -- More NOPs
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb0 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP1
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb1 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CHECKLOCKTIMEVERIFY
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb2 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CHECKSEQUENCEVERIFY
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb3 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP4
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb4 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP5
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb5 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP6
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb6 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP7
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb7 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP8
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb8 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP9
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xb9 = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_NOP10
            -- Bitcoin Cash Nov 2018 hard fork
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xba = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CHECKDATASIG
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xbb = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_CHECKDATASIGVERIFY
            -- Bitcoin Cash May 2020 hard fork
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xbc = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_REVERSEBYTES
            -- Constants
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xfd = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_PUBKEYHASH
            | Word8
op Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0xfe = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_PUBKEY
            | Bool
otherwise = ScriptOp -> m ScriptOp
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOp -> m ScriptOp) -> ScriptOp -> m ScriptOp
forall a b. (a -> b) -> a -> b
$ Word8 -> ScriptOp
OP_INVALIDOPCODE Word8
op

    serialize :: ScriptOp -> m ()
serialize ScriptOp
op = case ScriptOp
op of
        (OP_PUSHDATA ByteString
payload PushDataType
optype) -> do
            let len :: Int
len = ByteString -> Int
B.length ByteString
payload
            case PushDataType
optype of
                PushDataType
OPCODE -> do
                    Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0x4b) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
                        String -> m ()
forall a. HasCallStack => String -> a
error String
"OP_PUSHDATA OPCODE: Payload size too big"
                    Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 (Word8 -> m ()) -> Word8 -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len
                PushDataType
OPDATA1 -> do
                    Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0xff) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
                        String -> m ()
forall a. HasCallStack => String -> a
error String
"OP_PUSHDATA OPDATA1: Payload size too big"
                    Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x4c
                    Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 (Word8 -> m ()) -> Word8 -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len
                PushDataType
OPDATA2 -> do
                    Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0xffff) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
                        String -> m ()
forall a. HasCallStack => String -> a
error String
"OP_PUSHDATA OPDATA2: Payload size too big"
                    Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x4d
                    Word16 -> m ()
forall (m :: * -> *). MonadPut m => Word16 -> m ()
putWord16le (Word16 -> m ()) -> Word16 -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len
                PushDataType
OPDATA4 -> do
                    Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0x7fffffff) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
                        String -> m ()
forall a. HasCallStack => String -> a
error String
"OP_PUSHDATA OPDATA4: Payload size too big"
                    Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x4e
                    Word32 -> m ()
forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le (Word32 -> m ()) -> Word32 -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len
            ByteString -> m ()
forall (m :: * -> *). MonadPut m => ByteString -> m ()
putByteString ByteString
payload

        -- Constants
        ScriptOp
OP_0 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x00
        ScriptOp
OP_1NEGATE -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x4f
        ScriptOp
OP_RESERVED -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x50
        ScriptOp
OP_1 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x51
        ScriptOp
OP_2 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x52
        ScriptOp
OP_3 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x53
        ScriptOp
OP_4 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x54
        ScriptOp
OP_5 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x55
        ScriptOp
OP_6 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x56
        ScriptOp
OP_7 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x57
        ScriptOp
OP_8 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x58
        ScriptOp
OP_9 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x59
        ScriptOp
OP_10 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x5a
        ScriptOp
OP_11 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x5b
        ScriptOp
OP_12 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x5c
        ScriptOp
OP_13 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x5d
        ScriptOp
OP_14 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x5e
        ScriptOp
OP_15 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x5f
        ScriptOp
OP_16 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x60
        -- Crypto Constants
        ScriptOp
OP_PUBKEY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xfe
        ScriptOp
OP_PUBKEYHASH -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xfd
        -- Invalid Opcodes
        (OP_INVALIDOPCODE Word8
x) -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
x
        -- Flow Control
        ScriptOp
OP_NOP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x61
        ScriptOp
OP_VER -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x62
        ScriptOp
OP_IF -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x63
        ScriptOp
OP_NOTIF -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x64
        ScriptOp
OP_VERIF -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x65
        ScriptOp
OP_VERNOTIF -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x66
        ScriptOp
OP_ELSE -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x67
        ScriptOp
OP_ENDIF -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x68
        ScriptOp
OP_VERIFY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x69
        ScriptOp
OP_RETURN -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x6a
        -- Stack Operations
        ScriptOp
OP_TOALTSTACK -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x6b
        ScriptOp
OP_FROMALTSTACK -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x6c
        ScriptOp
OP_2DROP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x6d
        ScriptOp
OP_2DUP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x6e
        ScriptOp
OP_3DUP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x6f
        ScriptOp
OP_2OVER -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x70
        ScriptOp
OP_2ROT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x71
        ScriptOp
OP_2SWAP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x72
        ScriptOp
OP_IFDUP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x73
        ScriptOp
OP_DEPTH -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x74
        ScriptOp
OP_DROP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x75
        ScriptOp
OP_DUP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x76
        ScriptOp
OP_NIP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x77
        ScriptOp
OP_OVER -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x78
        ScriptOp
OP_PICK -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x79
        ScriptOp
OP_ROLL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x7a
        ScriptOp
OP_ROT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x7b
        ScriptOp
OP_SWAP -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x7c
        ScriptOp
OP_TUCK -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x7d
        -- Splice
        ScriptOp
OP_CAT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x7e
        ScriptOp
OP_SUBSTR -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x7f
        ScriptOp
OP_LEFT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x80
        ScriptOp
OP_RIGHT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x81
        ScriptOp
OP_SIZE -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x82
        -- Bitwise Logic
        ScriptOp
OP_INVERT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x83
        ScriptOp
OP_AND -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x84
        ScriptOp
OP_OR -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x85
        ScriptOp
OP_XOR -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x86
        ScriptOp
OP_EQUAL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x87
        ScriptOp
OP_EQUALVERIFY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x88
        ScriptOp
OP_RESERVED1 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x89
        ScriptOp
OP_RESERVED2 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x8a
        -- Arithmetic
        ScriptOp
OP_1ADD -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x8b
        ScriptOp
OP_1SUB -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x8c
        ScriptOp
OP_2MUL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x8d
        ScriptOp
OP_2DIV -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x8e
        ScriptOp
OP_NEGATE -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x8f
        ScriptOp
OP_ABS -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x90
        ScriptOp
OP_NOT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x91
        ScriptOp
OP_0NOTEQUAL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x92
        ScriptOp
OP_ADD -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x93
        ScriptOp
OP_SUB -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x94
        ScriptOp
OP_MUL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x95
        ScriptOp
OP_DIV -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x96
        ScriptOp
OP_MOD -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x97
        ScriptOp
OP_LSHIFT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x98
        ScriptOp
OP_RSHIFT -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x99
        ScriptOp
OP_BOOLAND -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x9a
        ScriptOp
OP_BOOLOR -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x9b
        ScriptOp
OP_NUMEQUAL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x9c
        ScriptOp
OP_NUMEQUALVERIFY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x9d
        ScriptOp
OP_NUMNOTEQUAL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x9e
        ScriptOp
OP_LESSTHAN -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x9f
        ScriptOp
OP_GREATERTHAN -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa0
        ScriptOp
OP_LESSTHANOREQUAL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa1
        ScriptOp
OP_GREATERTHANOREQUAL -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa2
        ScriptOp
OP_MIN -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa3
        ScriptOp
OP_MAX -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa4
        ScriptOp
OP_WITHIN -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa5
        -- Crypto
        ScriptOp
OP_RIPEMD160 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa6
        ScriptOp
OP_SHA1 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa7
        ScriptOp
OP_SHA256 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa8
        ScriptOp
OP_HASH160 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xa9
        ScriptOp
OP_HASH256 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xaa
        ScriptOp
OP_CODESEPARATOR -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xab
        ScriptOp
OP_CHECKSIG -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xac
        ScriptOp
OP_CHECKSIGVERIFY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xad
        ScriptOp
OP_CHECKMULTISIG -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xae
        ScriptOp
OP_CHECKMULTISIGVERIFY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xaf
        -- More NOPs
        ScriptOp
OP_NOP1 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb0
        ScriptOp
OP_CHECKLOCKTIMEVERIFY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb1
        ScriptOp
OP_CHECKSEQUENCEVERIFY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb2
        ScriptOp
OP_NOP4 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb3
        ScriptOp
OP_NOP5 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb4
        ScriptOp
OP_NOP6 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb5
        ScriptOp
OP_NOP7 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb6
        ScriptOp
OP_NOP8 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb7
        ScriptOp
OP_NOP9 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb8
        ScriptOp
OP_NOP10 -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xb9
        -- Bitcoin Cash Nov 2018 hard fork
        ScriptOp
OP_CHECKDATASIG -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xba
        ScriptOp
OP_CHECKDATASIGVERIFY -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xbb
        -- Bitcoin Cash May 2020 hard fork
        ScriptOp
OP_REVERSEBYTES -> Word8 -> m ()
forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0xbc

instance Binary ScriptOp where
    put :: ScriptOp -> Put
put = ScriptOp -> Put
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize
    get :: Get ScriptOp
get = Get ScriptOp
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize

instance Serialize ScriptOp where
    put :: Putter ScriptOp
put = Putter ScriptOp
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize
    get :: Get ScriptOp
get = Get ScriptOp
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize

-- | Check whether opcode is only data.
isPushOp :: ScriptOp -> Bool
isPushOp :: ScriptOp -> Bool
isPushOp ScriptOp
op = case ScriptOp
op of
    OP_PUSHDATA ByteString
_ PushDataType
_ -> Bool
True
    ScriptOp
OP_0 -> Bool
True
    ScriptOp
OP_1NEGATE -> Bool
True
    ScriptOp
OP_1 -> Bool
True
    ScriptOp
OP_2 -> Bool
True
    ScriptOp
OP_3 -> Bool
True
    ScriptOp
OP_4 -> Bool
True
    ScriptOp
OP_5 -> Bool
True
    ScriptOp
OP_6 -> Bool
True
    ScriptOp
OP_7 -> Bool
True
    ScriptOp
OP_8 -> Bool
True
    ScriptOp
OP_9 -> Bool
True
    ScriptOp
OP_10 -> Bool
True
    ScriptOp
OP_11 -> Bool
True
    ScriptOp
OP_12 -> Bool
True
    ScriptOp
OP_13 -> Bool
True
    ScriptOp
OP_14 -> Bool
True
    ScriptOp
OP_15 -> Bool
True
    ScriptOp
OP_16 -> Bool
True
    ScriptOp
_ -> Bool
False

-- | Optimally encode data using one of the 4 types of data pushing opcodes.
opPushData :: ByteString -> ScriptOp
opPushData :: ByteString -> ScriptOp
opPushData ByteString
bs
    | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0x4b = ByteString -> PushDataType -> ScriptOp
OP_PUSHDATA ByteString
bs PushDataType
OPCODE
    | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0xff = ByteString -> PushDataType -> ScriptOp
OP_PUSHDATA ByteString
bs PushDataType
OPDATA1
    | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0xffff = ByteString -> PushDataType -> ScriptOp
OP_PUSHDATA ByteString
bs PushDataType
OPDATA2
    | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0xffffffff = ByteString -> PushDataType -> ScriptOp
OP_PUSHDATA ByteString
bs PushDataType
OPDATA4
    | Bool
otherwise = String -> ScriptOp
forall a. HasCallStack => String -> a
error String
"opPushData: payload size too big"
  where
    len :: Int
len = ByteString -> Int
B.length ByteString
bs

-- | Transforms integers @[1 .. 16]@ to 'ScriptOp' @[OP_1 .. OP_16]@.
intToScriptOp :: Int -> ScriptOp
intToScriptOp :: Int -> ScriptOp
intToScriptOp Int
i
    | Int
i Int -> [Int] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int
1 .. Int
16] = ScriptOp
op
    | Bool
otherwise = ScriptOp
forall a. a
err
  where
    op :: ScriptOp
op =
        ScriptOp -> Either String ScriptOp -> ScriptOp
forall b a. b -> Either a b -> b
fromRight ScriptOp
forall a. a
err
            (Either String ScriptOp -> ScriptOp)
-> (Int -> Either String ScriptOp) -> Int -> ScriptOp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Get ScriptOp -> ByteString -> Either String ScriptOp
forall a. Get a -> ByteString -> Either String a
runGetS Get ScriptOp
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize
            (ByteString -> Either String ScriptOp)
-> (Int -> ByteString) -> Int -> Either String ScriptOp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> ByteString
B.singleton
            (Word8 -> ByteString) -> (Int -> Word8) -> Int -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral
            (Int -> ScriptOp) -> Int -> ScriptOp
forall a b. (a -> b) -> a -> b
$ Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
0x50
    err :: a
err = String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"intToScriptOp: Invalid integer " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i

{- | Decode 'ScriptOp' @[OP_1 .. OP_16]@ to integers @[1 .. 16]@. This functions
 fails for other values of 'ScriptOp'
-}
scriptOpToInt :: ScriptOp -> Either String Int
scriptOpToInt :: ScriptOp -> Either String Int
scriptOpToInt ScriptOp
s
    | Int
res Int -> [Int] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int
1 .. Int
16] = Int -> Either String Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
res
    | Bool
otherwise = String -> Either String Int
forall a b. a -> Either a b
Left (String -> Either String Int) -> String -> Either String Int
forall a b. (a -> b) -> a -> b
$ String
"scriptOpToInt: invalid opcode " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ScriptOp -> String
forall a. Show a => a -> String
show ScriptOp
s
  where
    res :: Int
res = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Word8
B.head (ByteString -> Word8) -> ByteString -> Word8
forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPutS (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ Putter ScriptOp
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize ScriptOp
s) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
0x50