{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoFieldSelectors #-}

-- |
-- 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.Aeson
import Data.Aeson.Encoding
import Data.Binary (Binary (..))
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.ByteString.Builder (char7)
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)
import Haskoin.Util (hexBuilder)
import Haskoin.Util.Helpers (decodeHex, encodeHex, hexEncoding)

-- | 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]
ops :: [ScriptOp]
  }
  deriving (Script -> Script -> Bool
(Script -> Script -> Bool)
-> (Script -> Script -> Bool) -> Eq Script
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Script -> Script -> Bool
== :: Script -> Script -> Bool
$c/= :: Script -> Script -> Bool
/= :: 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
$cshowsPrec :: Int -> Script -> ShowS
showsPrec :: Int -> Script -> ShowS
$cshow :: Script -> String
show :: Script -> String
$cshowList :: [Script] -> ShowS
showList :: [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
$creadsPrec :: Int -> ReadS Script
readsPrec :: Int -> ReadS Script
$creadList :: ReadS [Script]
readList :: ReadS [Script]
$creadPrec :: ReadPrec Script
readPrec :: ReadPrec Script
$creadListPrec :: ReadPrec [Script]
readListPrec :: ReadPrec [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
$cfrom :: forall x. Script -> Rep Script x
from :: forall x. Script -> Rep Script x
$cto :: forall x. Rep Script x -> Script
to :: forall x. Rep Script x -> Script
Generic)
  deriving newtype (Eq Script
Eq Script =>
(Int -> Script -> Int) -> (Script -> Int) -> Hashable Script
Int -> Script -> Int
Script -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> Script -> Int
hashWithSalt :: Int -> Script -> Int
$chash :: Script -> Int
hash :: Script -> Int
Hashable, Script -> ()
(Script -> ()) -> NFData Script
forall a. (a -> ()) -> NFData a
$crnf :: Script -> ()
rnf :: Script -> ()
NFData)

instance FromJSON Script where
  parseJSON :: Value -> Parser Script
parseJSON = String -> (Text -> Parser Script) -> Value -> Parser Script
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"script" ((Text -> Parser Script) -> Value -> Parser Script)
-> (Text -> Parser Script) -> Value -> Parser Script
forall a b. (a -> b) -> a -> b
$ \Text
t -> do
    ByteString
bs <- Parser ByteString
-> (ByteString -> Parser ByteString)
-> Maybe ByteString
-> Parser ByteString
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Parser ByteString
forall a. Parser a
forall (m :: * -> *) a. MonadPlus m => m a
mzero ByteString -> Parser ByteString
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Maybe ByteString
decodeHex Text
t)
    (String -> Parser Script)
-> (Script -> Parser Script)
-> Either String Script
-> Parser Script
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser Script
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail Script -> Parser Script
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return (Get Script -> ByteString -> Either String Script
forall a. Get a -> ByteString -> Either String a
runGetS Get Script
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
forall (m :: * -> *). MonadGet m => m Script
deserialize ByteString
bs)

instance ToJSON Script where
  toJSON :: Script -> Value
toJSON = Text -> Value
String (Text -> Value) -> (Script -> Text) -> Script -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
encodeHex (ByteString -> Text) -> (Script -> ByteString) -> Script -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> ByteString
runPutS (Put -> ByteString) -> (Script -> Put) -> Script -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Script -> Put
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
forall (m :: * -> *). MonadPut m => Script -> m ()
serialize
  toEncoding :: Script -> Encoding
toEncoding = ByteString -> Encoding
hexEncoding (ByteString -> Encoding)
-> (Script -> ByteString) -> Script -> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> ByteString
runPutL (Put -> ByteString) -> (Script -> Put) -> Script -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Script -> Put
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
forall (m :: * -> *). MonadPut m => Script -> m ()
serialize

instance Serial Script where
  deserialize :: forall (m :: * -> *). MonadGet m => 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 a. a -> m a
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
forall (m :: * -> *). MonadGet m => m ScriptOp
deserialize m ([ScriptOp] -> [ScriptOp]) -> m [ScriptOp] -> m [ScriptOp]
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m [ScriptOp]
getScriptOps

  serialize :: forall (m :: * -> *). MonadPut m => 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 ()
forall (m :: * -> *). MonadPut m => ScriptOp -> m ()
serialize

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

instance Serialize Script where
  put :: Script -> Put
put = Script -> Put
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
forall (m :: * -> *). MonadPut m => Script -> m ()
serialize
  get :: Get Script
get = Get Script
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
forall (m :: * -> *). MonadGet m => m Script
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
$cshowsPrec :: Int -> PushDataType -> ShowS
showsPrec :: Int -> PushDataType -> ShowS
$cshow :: PushDataType -> String
show :: PushDataType -> String
$cshowList :: [PushDataType] -> ShowS
showList :: [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
$creadsPrec :: Int -> ReadS PushDataType
readsPrec :: Int -> ReadS PushDataType
$creadList :: ReadS [PushDataType]
readList :: ReadS [PushDataType]
$creadPrec :: ReadPrec PushDataType
readPrec :: ReadPrec PushDataType
$creadListPrec :: ReadPrec [PushDataType]
readListPrec :: ReadPrec [PushDataType]
Read, PushDataType -> PushDataType -> Bool
(PushDataType -> PushDataType -> Bool)
-> (PushDataType -> PushDataType -> Bool) -> Eq PushDataType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PushDataType -> PushDataType -> Bool
== :: PushDataType -> PushDataType -> Bool
$c/= :: PushDataType -> PushDataType -> Bool
/= :: 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
$cfrom :: forall x. PushDataType -> Rep PushDataType x
from :: forall x. PushDataType -> Rep PushDataType x
$cto :: forall x. Rep PushDataType x -> PushDataType
to :: forall x. Rep PushDataType x -> PushDataType
Generic, Eq PushDataType
Eq PushDataType =>
(Int -> PushDataType -> Int)
-> (PushDataType -> Int) -> Hashable PushDataType
Int -> PushDataType -> Int
PushDataType -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> PushDataType -> Int
hashWithSalt :: Int -> PushDataType -> Int
$chash :: PushDataType -> Int
hash :: PushDataType -> Int
Hashable, PushDataType -> ()
(PushDataType -> ()) -> NFData PushDataType
forall a. (a -> ()) -> NFData a
$crnf :: PushDataType -> ()
rnf :: 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
$cshowsPrec :: Int -> ScriptOp -> ShowS
showsPrec :: Int -> ScriptOp -> ShowS
$cshow :: ScriptOp -> String
show :: ScriptOp -> String
$cshowList :: [ScriptOp] -> ShowS
showList :: [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
$creadsPrec :: Int -> ReadS ScriptOp
readsPrec :: Int -> ReadS ScriptOp
$creadList :: ReadS [ScriptOp]
readList :: ReadS [ScriptOp]
$creadPrec :: ReadPrec ScriptOp
readPrec :: ReadPrec ScriptOp
$creadListPrec :: ReadPrec [ScriptOp]
readListPrec :: ReadPrec [ScriptOp]
Read, ScriptOp -> ScriptOp -> Bool
(ScriptOp -> ScriptOp -> Bool)
-> (ScriptOp -> ScriptOp -> Bool) -> Eq ScriptOp
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ScriptOp -> ScriptOp -> Bool
== :: ScriptOp -> ScriptOp -> Bool
$c/= :: ScriptOp -> ScriptOp -> Bool
/= :: 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
$cfrom :: forall x. ScriptOp -> Rep ScriptOp x
from :: forall x. ScriptOp -> Rep ScriptOp x
$cto :: forall x. Rep ScriptOp x -> ScriptOp
to :: forall x. Rep ScriptOp x -> ScriptOp
Generic, Eq ScriptOp
Eq ScriptOp =>
(Int -> ScriptOp -> Int) -> (ScriptOp -> Int) -> Hashable ScriptOp
Int -> ScriptOp -> Int
ScriptOp -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> ScriptOp -> Int
hashWithSalt :: Int -> ScriptOp -> Int
$chash :: ScriptOp -> Int
hash :: ScriptOp -> Int
Hashable, ScriptOp -> ()
(ScriptOp -> ()) -> NFData ScriptOp
forall a. (a -> ()) -> NFData a
$crnf :: ScriptOp -> ()
rnf :: ScriptOp -> ()
NFData)

instance Serial ScriptOp where
  deserialize :: forall (m :: * -> *). MonadGet m => 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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ScriptOp
OP_PUBKEY
        | Bool
otherwise = ScriptOp -> m ScriptOp
forall a. a -> m a
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 :: forall (m :: * -> *). MonadPut m => 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 ()
forall (m :: * -> *). MonadPut m => ScriptOp -> m ()
serialize
  get :: Get ScriptOp
get = Get ScriptOp
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
forall (m :: * -> *). MonadGet m => m ScriptOp
deserialize

instance Serialize ScriptOp where
  put :: Putter ScriptOp
put = Putter ScriptOp
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
forall (m :: * -> *). MonadPut m => ScriptOp -> m ()
serialize
  get :: Get ScriptOp
get = Get ScriptOp
forall a (m :: * -> *). (Serial a, MonadGet m) => m a
forall (m :: * -> *). MonadGet m => m ScriptOp
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 a. Eq a => a -> [a] -> 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
forall (m :: * -> *). MonadGet m => m ScriptOp
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 a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int
1 .. Int
16] = Int -> Either String Int
forall a. a -> Either String a
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 (HasCallStack => ByteString -> Word8
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 ()
forall (m :: * -> *). MonadPut m => ScriptOp -> m ()
serialize ScriptOp
s) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
0x50