{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}
{-|
Module      : Haskoin.Script.SigHash
Copyright   : No rights reserved
License     : MIT
Maintainer  : jprupp@protonmail.ch
Stability   : experimental
Portability : POSIX

Transaction signatures and related functions.
-}
module Haskoin.Script.SigHash
    ( -- * Script Signatures
      SigHash(..)
    , SigHashFlag(..)
    , sigHashAll
    , sigHashNone
    , sigHashSingle
    , hasAnyoneCanPayFlag
    , hasForkIdFlag
    , setAnyoneCanPayFlag
    , setForkIdFlag
    , isSigHashAll
    , isSigHashNone
    , isSigHashSingle
    , isSigHashUnknown
    , sigHashAddForkId
    , sigHashGetForkId
    , sigHashAddNetworkId
    , txSigHash
    , txSigHashForkId
    , TxSignature(..)
    , encodeTxSig
    , decodeTxSig
    ) where

import           Control.DeepSeq
import           Control.Monad
import qualified Data.Aeson                 as J
import           Data.Bits
import qualified Data.ByteString            as BS
import           Data.Hashable
import           Data.Maybe
import           Data.Scientific
import           Data.Serialize
import           Data.Word
import           GHC.Generics               (Generic)
import           Haskoin.Constants
import           Haskoin.Crypto.Hash
import           Haskoin.Network.Common
import           Haskoin.Crypto
import           Haskoin.Script.Common
import           Haskoin.Transaction.Common
import           Haskoin.Util

-- | Constant representing a SIGHASH flag that controls what is being signed.
data SigHashFlag
    = SIGHASH_ALL
      -- ^ sign all outputs
    | SIGHASH_NONE
      -- ^ sign no outputs
    | SIGHASH_SINGLE
      -- ^ sign the output index corresponding to the input
    | SIGHASH_FORKID
      -- ^ replay protection for Bitcoin Cash transactions
    | SIGHASH_ANYONECANPAY
      -- ^ new inputs can be added
    deriving (SigHashFlag -> SigHashFlag -> Bool
(SigHashFlag -> SigHashFlag -> Bool)
-> (SigHashFlag -> SigHashFlag -> Bool) -> Eq SigHashFlag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SigHashFlag -> SigHashFlag -> Bool
$c/= :: SigHashFlag -> SigHashFlag -> Bool
== :: SigHashFlag -> SigHashFlag -> Bool
$c== :: SigHashFlag -> SigHashFlag -> Bool
Eq, Eq SigHashFlag
Eq SigHashFlag =>
(SigHashFlag -> SigHashFlag -> Ordering)
-> (SigHashFlag -> SigHashFlag -> Bool)
-> (SigHashFlag -> SigHashFlag -> Bool)
-> (SigHashFlag -> SigHashFlag -> Bool)
-> (SigHashFlag -> SigHashFlag -> Bool)
-> (SigHashFlag -> SigHashFlag -> SigHashFlag)
-> (SigHashFlag -> SigHashFlag -> SigHashFlag)
-> Ord SigHashFlag
SigHashFlag -> SigHashFlag -> Bool
SigHashFlag -> SigHashFlag -> Ordering
SigHashFlag -> SigHashFlag -> SigHashFlag
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SigHashFlag -> SigHashFlag -> SigHashFlag
$cmin :: SigHashFlag -> SigHashFlag -> SigHashFlag
max :: SigHashFlag -> SigHashFlag -> SigHashFlag
$cmax :: SigHashFlag -> SigHashFlag -> SigHashFlag
>= :: SigHashFlag -> SigHashFlag -> Bool
$c>= :: SigHashFlag -> SigHashFlag -> Bool
> :: SigHashFlag -> SigHashFlag -> Bool
$c> :: SigHashFlag -> SigHashFlag -> Bool
<= :: SigHashFlag -> SigHashFlag -> Bool
$c<= :: SigHashFlag -> SigHashFlag -> Bool
< :: SigHashFlag -> SigHashFlag -> Bool
$c< :: SigHashFlag -> SigHashFlag -> Bool
compare :: SigHashFlag -> SigHashFlag -> Ordering
$ccompare :: SigHashFlag -> SigHashFlag -> Ordering
$cp1Ord :: Eq SigHashFlag
Ord, Int -> SigHashFlag -> ShowS
[SigHashFlag] -> ShowS
SigHashFlag -> String
(Int -> SigHashFlag -> ShowS)
-> (SigHashFlag -> String)
-> ([SigHashFlag] -> ShowS)
-> Show SigHashFlag
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SigHashFlag] -> ShowS
$cshowList :: [SigHashFlag] -> ShowS
show :: SigHashFlag -> String
$cshow :: SigHashFlag -> String
showsPrec :: Int -> SigHashFlag -> ShowS
$cshowsPrec :: Int -> SigHashFlag -> ShowS
Show, ReadPrec [SigHashFlag]
ReadPrec SigHashFlag
Int -> ReadS SigHashFlag
ReadS [SigHashFlag]
(Int -> ReadS SigHashFlag)
-> ReadS [SigHashFlag]
-> ReadPrec SigHashFlag
-> ReadPrec [SigHashFlag]
-> Read SigHashFlag
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SigHashFlag]
$creadListPrec :: ReadPrec [SigHashFlag]
readPrec :: ReadPrec SigHashFlag
$creadPrec :: ReadPrec SigHashFlag
readList :: ReadS [SigHashFlag]
$creadList :: ReadS [SigHashFlag]
readsPrec :: Int -> ReadS SigHashFlag
$creadsPrec :: Int -> ReadS SigHashFlag
Read, (forall x. SigHashFlag -> Rep SigHashFlag x)
-> (forall x. Rep SigHashFlag x -> SigHashFlag)
-> Generic SigHashFlag
forall x. Rep SigHashFlag x -> SigHashFlag
forall x. SigHashFlag -> Rep SigHashFlag x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep SigHashFlag x -> SigHashFlag
$cfrom :: forall x. SigHashFlag -> Rep SigHashFlag x
Generic)

instance NFData SigHashFlag

instance Hashable SigHashFlag

instance Enum SigHashFlag where
    fromEnum :: SigHashFlag -> Int
fromEnum SIGHASH_ALL          = 0x01
    fromEnum SIGHASH_NONE         = 0x02
    fromEnum SIGHASH_SINGLE       = 0x03
    fromEnum SIGHASH_FORKID       = 0x40
    fromEnum SIGHASH_ANYONECANPAY = 0x80
    toEnum :: Int -> SigHashFlag
toEnum 0x01 = SigHashFlag
SIGHASH_ALL
    toEnum 0x02 = SigHashFlag
SIGHASH_NONE
    toEnum 0x03 = SigHashFlag
SIGHASH_SINGLE
    toEnum 0x40 = SigHashFlag
SIGHASH_FORKID
    toEnum 0x80 = SigHashFlag
SIGHASH_ANYONECANPAY
    toEnum _    = String -> SigHashFlag
forall a. HasCallStack => String -> a
error "Not a valid sighash flag"

-- | Data type representing the different ways a transaction can be signed.
-- When producing a signature, a hash of the transaction is used as the message
-- to be signed. The 'SigHash' parameter controls which parts of the
-- transaction are used or ignored to produce the transaction hash. The idea is
-- that if some part of a transaction is not used to produce the transaction
-- hash, then you can change that part of the transaction after producing a
-- signature without invalidating that signature.
--
-- If the 'SIGHASH_ANYONECANPAY' flag is set (true), then only the current input
-- is signed. Otherwise, all of the inputs of a transaction are signed. The
-- default value for 'SIGHASH_ANYONECANPAY' is unset (false).
newtype SigHash =
    SigHash Word32
    deriving ( SigHash -> SigHash -> Bool
(SigHash -> SigHash -> Bool)
-> (SigHash -> SigHash -> Bool) -> Eq SigHash
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SigHash -> SigHash -> Bool
$c/= :: SigHash -> SigHash -> Bool
== :: SigHash -> SigHash -> Bool
$c== :: SigHash -> SigHash -> Bool
Eq
             , Eq SigHash
Eq SigHash =>
(SigHash -> SigHash -> Ordering)
-> (SigHash -> SigHash -> Bool)
-> (SigHash -> SigHash -> Bool)
-> (SigHash -> SigHash -> Bool)
-> (SigHash -> SigHash -> Bool)
-> (SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> SigHash)
-> Ord SigHash
SigHash -> SigHash -> Bool
SigHash -> SigHash -> Ordering
SigHash -> SigHash -> SigHash
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SigHash -> SigHash -> SigHash
$cmin :: SigHash -> SigHash -> SigHash
max :: SigHash -> SigHash -> SigHash
$cmax :: SigHash -> SigHash -> SigHash
>= :: SigHash -> SigHash -> Bool
$c>= :: SigHash -> SigHash -> Bool
> :: SigHash -> SigHash -> Bool
$c> :: SigHash -> SigHash -> Bool
<= :: SigHash -> SigHash -> Bool
$c<= :: SigHash -> SigHash -> Bool
< :: SigHash -> SigHash -> Bool
$c< :: SigHash -> SigHash -> Bool
compare :: SigHash -> SigHash -> Ordering
$ccompare :: SigHash -> SigHash -> Ordering
$cp1Ord :: Eq SigHash
Ord
             , Eq SigHash
SigHash
Eq SigHash =>
(SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> SigHash
-> (Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> Bool)
-> (SigHash -> Maybe Int)
-> (SigHash -> Int)
-> (SigHash -> Bool)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int -> SigHash)
-> (SigHash -> Int)
-> Bits SigHash
Int -> SigHash
SigHash -> Bool
SigHash -> Int
SigHash -> Maybe Int
SigHash -> SigHash
SigHash -> Int -> Bool
SigHash -> Int -> SigHash
SigHash -> SigHash -> SigHash
forall a.
Eq a =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> a
-> (Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> Bool)
-> (a -> Maybe Int)
-> (a -> Int)
-> (a -> Bool)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int -> a)
-> (a -> Int)
-> Bits a
popCount :: SigHash -> Int
$cpopCount :: SigHash -> Int
rotateR :: SigHash -> Int -> SigHash
$crotateR :: SigHash -> Int -> SigHash
rotateL :: SigHash -> Int -> SigHash
$crotateL :: SigHash -> Int -> SigHash
unsafeShiftR :: SigHash -> Int -> SigHash
$cunsafeShiftR :: SigHash -> Int -> SigHash
shiftR :: SigHash -> Int -> SigHash
$cshiftR :: SigHash -> Int -> SigHash
unsafeShiftL :: SigHash -> Int -> SigHash
$cunsafeShiftL :: SigHash -> Int -> SigHash
shiftL :: SigHash -> Int -> SigHash
$cshiftL :: SigHash -> Int -> SigHash
isSigned :: SigHash -> Bool
$cisSigned :: SigHash -> Bool
bitSize :: SigHash -> Int
$cbitSize :: SigHash -> Int
bitSizeMaybe :: SigHash -> Maybe Int
$cbitSizeMaybe :: SigHash -> Maybe Int
testBit :: SigHash -> Int -> Bool
$ctestBit :: SigHash -> Int -> Bool
complementBit :: SigHash -> Int -> SigHash
$ccomplementBit :: SigHash -> Int -> SigHash
clearBit :: SigHash -> Int -> SigHash
$cclearBit :: SigHash -> Int -> SigHash
setBit :: SigHash -> Int -> SigHash
$csetBit :: SigHash -> Int -> SigHash
bit :: Int -> SigHash
$cbit :: Int -> SigHash
zeroBits :: SigHash
$czeroBits :: SigHash
rotate :: SigHash -> Int -> SigHash
$crotate :: SigHash -> Int -> SigHash
shift :: SigHash -> Int -> SigHash
$cshift :: SigHash -> Int -> SigHash
complement :: SigHash -> SigHash
$ccomplement :: SigHash -> SigHash
xor :: SigHash -> SigHash -> SigHash
$cxor :: SigHash -> SigHash -> SigHash
.|. :: SigHash -> SigHash -> SigHash
$c.|. :: SigHash -> SigHash -> SigHash
.&. :: SigHash -> SigHash -> SigHash
$c.&. :: SigHash -> SigHash -> SigHash
$cp1Bits :: Eq SigHash
Bits
             , Int -> SigHash
SigHash -> Int
SigHash -> [SigHash]
SigHash -> SigHash
SigHash -> SigHash -> [SigHash]
SigHash -> SigHash -> SigHash -> [SigHash]
(SigHash -> SigHash)
-> (SigHash -> SigHash)
-> (Int -> SigHash)
-> (SigHash -> Int)
-> (SigHash -> [SigHash])
-> (SigHash -> SigHash -> [SigHash])
-> (SigHash -> SigHash -> [SigHash])
-> (SigHash -> SigHash -> SigHash -> [SigHash])
-> Enum SigHash
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: SigHash -> SigHash -> SigHash -> [SigHash]
$cenumFromThenTo :: SigHash -> SigHash -> SigHash -> [SigHash]
enumFromTo :: SigHash -> SigHash -> [SigHash]
$cenumFromTo :: SigHash -> SigHash -> [SigHash]
enumFromThen :: SigHash -> SigHash -> [SigHash]
$cenumFromThen :: SigHash -> SigHash -> [SigHash]
enumFrom :: SigHash -> [SigHash]
$cenumFrom :: SigHash -> [SigHash]
fromEnum :: SigHash -> Int
$cfromEnum :: SigHash -> Int
toEnum :: Int -> SigHash
$ctoEnum :: Int -> SigHash
pred :: SigHash -> SigHash
$cpred :: SigHash -> SigHash
succ :: SigHash -> SigHash
$csucc :: SigHash -> SigHash
Enum
             , Enum SigHash
Real SigHash
(Real SigHash, Enum SigHash) =>
(SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> (SigHash, SigHash))
-> (SigHash -> SigHash -> (SigHash, SigHash))
-> (SigHash -> Integer)
-> Integral SigHash
SigHash -> Integer
SigHash -> SigHash -> (SigHash, SigHash)
SigHash -> SigHash -> SigHash
forall a.
(Real a, Enum a) =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: SigHash -> Integer
$ctoInteger :: SigHash -> Integer
divMod :: SigHash -> SigHash -> (SigHash, SigHash)
$cdivMod :: SigHash -> SigHash -> (SigHash, SigHash)
quotRem :: SigHash -> SigHash -> (SigHash, SigHash)
$cquotRem :: SigHash -> SigHash -> (SigHash, SigHash)
mod :: SigHash -> SigHash -> SigHash
$cmod :: SigHash -> SigHash -> SigHash
div :: SigHash -> SigHash -> SigHash
$cdiv :: SigHash -> SigHash -> SigHash
rem :: SigHash -> SigHash -> SigHash
$crem :: SigHash -> SigHash -> SigHash
quot :: SigHash -> SigHash -> SigHash
$cquot :: SigHash -> SigHash -> SigHash
$cp2Integral :: Enum SigHash
$cp1Integral :: Real SigHash
Integral
             , Integer -> SigHash
SigHash -> SigHash
SigHash -> SigHash -> SigHash
(SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash -> SigHash)
-> (SigHash -> SigHash)
-> (SigHash -> SigHash)
-> (SigHash -> SigHash)
-> (Integer -> SigHash)
-> Num SigHash
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> SigHash
$cfromInteger :: Integer -> SigHash
signum :: SigHash -> SigHash
$csignum :: SigHash -> SigHash
abs :: SigHash -> SigHash
$cabs :: SigHash -> SigHash
negate :: SigHash -> SigHash
$cnegate :: SigHash -> SigHash
* :: SigHash -> SigHash -> SigHash
$c* :: SigHash -> SigHash -> SigHash
- :: SigHash -> SigHash -> SigHash
$c- :: SigHash -> SigHash -> SigHash
+ :: SigHash -> SigHash -> SigHash
$c+ :: SigHash -> SigHash -> SigHash
Num
             , Num SigHash
Ord SigHash
(Num SigHash, Ord SigHash) => (SigHash -> Rational) -> Real SigHash
SigHash -> Rational
forall a. (Num a, Ord a) => (a -> Rational) -> Real a
toRational :: SigHash -> Rational
$ctoRational :: SigHash -> Rational
$cp2Real :: Ord SigHash
$cp1Real :: Num SigHash
Real
             , Int -> SigHash -> ShowS
[SigHash] -> ShowS
SigHash -> String
(Int -> SigHash -> ShowS)
-> (SigHash -> String) -> ([SigHash] -> ShowS) -> Show SigHash
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SigHash] -> ShowS
$cshowList :: [SigHash] -> ShowS
show :: SigHash -> String
$cshow :: SigHash -> String
showsPrec :: Int -> SigHash -> ShowS
$cshowsPrec :: Int -> SigHash -> ShowS
Show
             , ReadPrec [SigHash]
ReadPrec SigHash
Int -> ReadS SigHash
ReadS [SigHash]
(Int -> ReadS SigHash)
-> ReadS [SigHash]
-> ReadPrec SigHash
-> ReadPrec [SigHash]
-> Read SigHash
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SigHash]
$creadListPrec :: ReadPrec [SigHash]
readPrec :: ReadPrec SigHash
$creadPrec :: ReadPrec SigHash
readList :: ReadS [SigHash]
$creadList :: ReadS [SigHash]
readsPrec :: Int -> ReadS SigHash
$creadsPrec :: Int -> ReadS SigHash
Read
             , (forall x. SigHash -> Rep SigHash x)
-> (forall x. Rep SigHash x -> SigHash) -> Generic SigHash
forall x. Rep SigHash x -> SigHash
forall x. SigHash -> Rep SigHash x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep SigHash x -> SigHash
$cfrom :: forall x. SigHash -> Rep SigHash x
Generic
             , Int -> SigHash -> Int
SigHash -> Int
(Int -> SigHash -> Int) -> (SigHash -> Int) -> Hashable SigHash
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: SigHash -> Int
$chash :: SigHash -> Int
hashWithSalt :: Int -> SigHash -> Int
$chashWithSalt :: Int -> SigHash -> Int
Hashable
             , SigHash -> ()
(SigHash -> ()) -> NFData SigHash
forall a. (a -> ()) -> NFData a
rnf :: SigHash -> ()
$crnf :: SigHash -> ()
NFData
             )

instance J.FromJSON SigHash where
    parseJSON :: Value -> Parser SigHash
parseJSON =
        String -> (Scientific -> Parser SigHash) -> Value -> Parser SigHash
forall a. String -> (Scientific -> Parser a) -> Value -> Parser a
J.withScientific "sighash" ((Scientific -> Parser SigHash) -> Value -> Parser SigHash)
-> (Scientific -> Parser SigHash) -> Value -> Parser SigHash
forall a b. (a -> b) -> a -> b
$
        Parser SigHash
-> (Word32 -> Parser SigHash) -> Maybe Word32 -> Parser SigHash
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Parser SigHash
forall (m :: * -> *) a. MonadPlus m => m a
mzero (SigHash -> Parser SigHash
forall (m :: * -> *) a. Monad m => a -> m a
return (SigHash -> Parser SigHash)
-> (Word32 -> SigHash) -> Word32 -> Parser SigHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> SigHash
SigHash) (Maybe Word32 -> Parser SigHash)
-> (Scientific -> Maybe Word32) -> Scientific -> Parser SigHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scientific -> Maybe Word32
forall i. (Integral i, Bounded i) => Scientific -> Maybe i
toBoundedInteger

instance J.ToJSON SigHash where
    toJSON :: SigHash -> Value
toJSON = Scientific -> Value
J.Number (Scientific -> Value)
-> (SigHash -> Scientific) -> SigHash -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SigHash -> Scientific
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    toEncoding :: SigHash -> Encoding
toEncoding (SigHash n :: Word32
n) = Word32 -> Encoding
forall a. ToJSON a => a -> Encoding
J.toEncoding Word32
n

-- | SIGHASH_NONE as a byte.
sigHashNone :: SigHash
sigHashNone :: SigHash
sigHashNone = Int -> SigHash
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> SigHash) -> Int -> SigHash
forall a b. (a -> b) -> a -> b
$ SigHashFlag -> Int
forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_NONE

-- | SIGHASH_ALL as a byte.
sigHashAll :: SigHash
sigHashAll :: SigHash
sigHashAll = Int -> SigHash
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> SigHash) -> Int -> SigHash
forall a b. (a -> b) -> a -> b
$ SigHashFlag -> Int
forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_ALL

-- | SIGHASH_SINGLE as a byte.
sigHashSingle :: SigHash
sigHashSingle :: SigHash
sigHashSingle = Int -> SigHash
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> SigHash) -> Int -> SigHash
forall a b. (a -> b) -> a -> b
$ SigHashFlag -> Int
forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_SINGLE

-- | SIGHASH_FORKID as a byte.
sigHashForkId :: SigHash
sigHashForkId :: SigHash
sigHashForkId = Int -> SigHash
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> SigHash) -> Int -> SigHash
forall a b. (a -> b) -> a -> b
$ SigHashFlag -> Int
forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_FORKID

-- | SIGHASH_ANYONECANPAY as a byte.
sigHashAnyoneCanPay :: SigHash
sigHashAnyoneCanPay :: SigHash
sigHashAnyoneCanPay = Int -> SigHash
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> SigHash) -> Int -> SigHash
forall a b. (a -> b) -> a -> b
$ SigHashFlag -> Int
forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_ANYONECANPAY

-- | Set SIGHASH_FORKID flag.
setForkIdFlag :: SigHash -> SigHash
setForkIdFlag :: SigHash -> SigHash
setForkIdFlag = (SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.|. SigHash
sigHashForkId)

-- | Set SIGHASH_ANYONECANPAY flag.
setAnyoneCanPayFlag :: SigHash -> SigHash
setAnyoneCanPayFlag :: SigHash -> SigHash
setAnyoneCanPayFlag = (SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.|. SigHash
sigHashAnyoneCanPay)

-- | Is the SIGHASH_FORKID flag set?
hasForkIdFlag :: SigHash -> Bool
hasForkIdFlag :: SigHash -> Bool
hasForkIdFlag = (SigHash -> SigHash -> Bool
forall a. Eq a => a -> a -> Bool
/= 0) (SigHash -> Bool) -> (SigHash -> SigHash) -> SigHash -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.&. SigHash
sigHashForkId)

-- | Is the SIGHASH_ANYONECANPAY flag set?
hasAnyoneCanPayFlag :: SigHash -> Bool
hasAnyoneCanPayFlag :: SigHash -> Bool
hasAnyoneCanPayFlag = (SigHash -> SigHash -> Bool
forall a. Eq a => a -> a -> Bool
/= 0) (SigHash -> Bool) -> (SigHash -> SigHash) -> SigHash -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.&. SigHash
sigHashAnyoneCanPay)

-- | Returns 'True' if the 'SigHash' has the value 'SIGHASH_ALL'.
isSigHashAll :: SigHash -> Bool
isSigHashAll :: SigHash -> Bool
isSigHashAll = (SigHash -> SigHash -> Bool
forall a. Eq a => a -> a -> Bool
== SigHash
sigHashAll) (SigHash -> Bool) -> (SigHash -> SigHash) -> SigHash -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.&. 0x1f)

-- | Returns 'True' if the 'SigHash' has the value 'SIGHASH_NONE'.
isSigHashNone :: SigHash -> Bool
isSigHashNone :: SigHash -> Bool
isSigHashNone = (SigHash -> SigHash -> Bool
forall a. Eq a => a -> a -> Bool
== SigHash
sigHashNone) (SigHash -> Bool) -> (SigHash -> SigHash) -> SigHash -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.&. 0x1f)

-- | Returns 'True' if the 'SigHash' has the value 'SIGHASH_SINGLE'.
isSigHashSingle :: SigHash -> Bool
isSigHashSingle :: SigHash -> Bool
isSigHashSingle = (SigHash -> SigHash -> Bool
forall a. Eq a => a -> a -> Bool
== SigHash
sigHashSingle) (SigHash -> Bool) -> (SigHash -> SigHash) -> SigHash -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.&. 0x1f)

-- | Returns 'True' if the 'SigHash' has the value 'SIGHASH_UNKNOWN'.
isSigHashUnknown :: SigHash -> Bool
isSigHashUnknown :: SigHash -> Bool
isSigHashUnknown =
    (SigHash -> [SigHash] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [SigHash
sigHashAll, SigHash
sigHashNone, SigHash
sigHashSingle]) (SigHash -> Bool) -> (SigHash -> SigHash) -> SigHash -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.&. 0x1f)

-- | Add a fork id to a 'SigHash'.
sigHashAddForkId :: SigHash -> Word32 -> SigHash
sigHashAddForkId :: SigHash -> Word32 -> SigHash
sigHashAddForkId sh :: SigHash
sh w :: Word32
w = (Word32 -> SigHash
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
w SigHash -> Int -> SigHash
forall a. Bits a => a -> Int -> a
`shiftL` 8) SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.|. (SigHash
sh SigHash -> SigHash -> SigHash
forall a. Bits a => a -> a -> a
.&. 0x000000ff)

-- | Add fork id of a particular network to a 'SigHash'.
sigHashAddNetworkId :: Network -> SigHash -> SigHash
sigHashAddNetworkId :: Network -> SigHash -> SigHash
sigHashAddNetworkId net :: Network
net =
    (SigHash -> Word32 -> SigHash
`sigHashAddForkId` Word32 -> Maybe Word32 -> Word32
forall a. a -> Maybe a -> a
fromMaybe 0 (Network -> Maybe Word32
getSigHashForkId Network
net))

-- | Get fork id from 'SigHash'.
sigHashGetForkId :: SigHash -> Word32
sigHashGetForkId :: SigHash -> Word32
sigHashGetForkId (SigHash n :: Word32
n) = Word32 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Word32) -> Word32 -> Word32
forall a b. (a -> b) -> a -> b
$ Word32
n Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` 8

-- | Computes the hash that will be used for signing a transaction.
txSigHash :: Network
          -> Tx      -- ^ transaction to sign
          -> Script  -- ^ script from output being spent
          -> Word64  -- ^ value of output being spent
          -> Int     -- ^ index of input being signed
          -> SigHash -- ^ what to sign
          -> Hash256 -- ^ hash to be signed
txSigHash :: Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
txSigHash net :: Network
net tx :: Tx
tx out :: Script
out v :: Word64
v i :: Int
i sh :: SigHash
sh
    | SigHash -> Bool
hasForkIdFlag SigHash
sh Bool -> Bool -> Bool
&& Maybe Word32 -> Bool
forall a. Maybe a -> Bool
isJust (Network -> Maybe Word32
getSigHashForkId Network
net) =
        Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
txSigHashForkId Network
net Tx
tx Script
out Word64
v Int
i SigHash
sh
    | Bool
otherwise = do
        let newIn :: [TxIn]
newIn = [TxIn] -> Script -> Int -> SigHash -> [TxIn]
buildInputs (Tx -> [TxIn]
txIn Tx
tx) Script
fout Int
i SigHash
sh
        -- When SigSingle and input index > outputs, then sign integer 1
        Hash256 -> Maybe Hash256 -> Hash256
forall a. a -> Maybe a -> a
fromMaybe Hash256
one (Maybe Hash256 -> Hash256) -> Maybe Hash256 -> Hash256
forall a b. (a -> b) -> a -> b
$ do
            [TxOut]
newOut <- [TxOut] -> Int -> SigHash -> Maybe [TxOut]
buildOutputs (Tx -> [TxOut]
txOut Tx
tx) Int
i SigHash
sh
            let newTx :: Tx
newTx = Word32 -> [TxIn] -> [TxOut] -> WitnessData -> Word32 -> Tx
Tx (Tx -> Word32
txVersion Tx
tx) [TxIn]
newIn [TxOut]
newOut [] (Tx -> Word32
txLockTime Tx
tx)
            Hash256 -> Maybe Hash256
forall (m :: * -> *) a. Monad m => a -> m a
return (Hash256 -> Maybe Hash256) -> Hash256 -> Maybe Hash256
forall a b. (a -> b) -> a -> b
$
                ByteString -> Hash256
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 (ByteString -> Hash256) -> ByteString -> Hash256
forall a b. (a -> b) -> a -> b
$
                Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ do
                    Putter Tx
forall t. Serialize t => Putter t
put Tx
newTx
                    Putter Word32
putWord32le Putter Word32 -> Putter Word32
forall a b. (a -> b) -> a -> b
$ SigHash -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral SigHash
sh
  where
    fout :: Script
fout = [ScriptOp] -> Script
Script ([ScriptOp] -> Script) -> [ScriptOp] -> Script
forall a b. (a -> b) -> a -> b
$ (ScriptOp -> Bool) -> [ScriptOp] -> [ScriptOp]
forall a. (a -> Bool) -> [a] -> [a]
filter (ScriptOp -> ScriptOp -> Bool
forall a. Eq a => a -> a -> Bool
/= ScriptOp
OP_CODESEPARATOR) ([ScriptOp] -> [ScriptOp]) -> [ScriptOp] -> [ScriptOp]
forall a b. (a -> b) -> a -> b
$ Script -> [ScriptOp]
scriptOps Script
out
    one :: Hash256
one = "0100000000000000000000000000000000000000000000000000000000000000"

-- | Build transaction inputs for computing sighashes.
buildInputs :: [TxIn] -> Script -> Int -> SigHash -> [TxIn]
buildInputs :: [TxIn] -> Script -> Int -> SigHash -> [TxIn]
buildInputs txins :: [TxIn]
txins out :: Script
out i :: Int
i sh :: SigHash
sh
    | SigHash -> Bool
hasAnyoneCanPayFlag SigHash
sh =
        [ ([TxIn]
txins [TxIn] -> Int -> TxIn
forall a. [a] -> Int -> a
!! Int
i) { scriptInput :: ByteString
scriptInput = Script -> ByteString
forall a. Serialize a => a -> ByteString
encode Script
out } ]
    | SigHash -> Bool
isSigHashAll SigHash
sh Bool -> Bool -> Bool
|| SigHash -> Bool
isSigHashUnknown SigHash
sh = [TxIn]
single
    | Bool
otherwise = (TxIn -> Int -> TxIn) -> [TxIn] -> [Int] -> [TxIn]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith TxIn -> Int -> TxIn
noSeq [TxIn]
single [0 ..]
  where
    emptyIn :: [TxIn]
emptyIn = (TxIn -> TxIn) -> [TxIn] -> [TxIn]
forall a b. (a -> b) -> [a] -> [b]
map (\ti :: TxIn
ti -> TxIn
ti { scriptInput :: ByteString
scriptInput = ByteString
BS.empty }) [TxIn]
txins
    single :: [TxIn]
single =
        Int -> [TxIn] -> (TxIn -> TxIn) -> [TxIn]
forall a. Int -> [a] -> (a -> a) -> [a]
updateIndex Int
i [TxIn]
emptyIn ((TxIn -> TxIn) -> [TxIn]) -> (TxIn -> TxIn) -> [TxIn]
forall a b. (a -> b) -> a -> b
$ \ti :: TxIn
ti -> TxIn
ti { scriptInput :: ByteString
scriptInput = Script -> ByteString
forall a. Serialize a => a -> ByteString
encode Script
out }
    noSeq :: TxIn -> Int -> TxIn
noSeq ti :: TxIn
ti j :: Int
j =
        if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
j
        then TxIn
ti
        else TxIn
ti { txInSequence :: Word32
txInSequence = 0 }

-- | Build transaction outputs for computing sighashes.
buildOutputs :: [TxOut] -> Int -> SigHash -> Maybe [TxOut]
buildOutputs :: [TxOut] -> Int -> SigHash -> Maybe [TxOut]
buildOutputs txos :: [TxOut]
txos i :: Int
i sh :: SigHash
sh
    | SigHash -> Bool
isSigHashAll SigHash
sh Bool -> Bool -> Bool
|| SigHash -> Bool
isSigHashUnknown SigHash
sh = [TxOut] -> Maybe [TxOut]
forall (m :: * -> *) a. Monad m => a -> m a
return [TxOut]
txos
    | SigHash -> Bool
isSigHashNone SigHash
sh = [TxOut] -> Maybe [TxOut]
forall (m :: * -> *) a. Monad m => a -> m a
return []
    | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= [TxOut] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxOut]
txos = Maybe [TxOut]
forall a. Maybe a
Nothing
    | Bool
otherwise = [TxOut] -> Maybe [TxOut]
forall (m :: * -> *) a. Monad m => a -> m a
return ([TxOut] -> Maybe [TxOut]) -> [TxOut] -> Maybe [TxOut]
forall a b. (a -> b) -> a -> b
$ [TxOut]
buffer [TxOut] -> [TxOut] -> [TxOut]
forall a. [a] -> [a] -> [a]
++ [[TxOut]
txos [TxOut] -> Int -> TxOut
forall a. [a] -> Int -> a
!! Int
i]
  where
    buffer :: [TxOut]
buffer = Int -> TxOut -> [TxOut]
forall a. Int -> a -> [a]
replicate Int
i (TxOut -> [TxOut]) -> TxOut -> [TxOut]
forall a b. (a -> b) -> a -> b
$ Word64 -> ByteString -> TxOut
TxOut Word64
forall a. Bounded a => a
maxBound ByteString
BS.empty

-- | Compute the hash that will be used for signing a transaction. This
-- function is used when the 'SIGHASH_FORKID' flag is set.
txSigHashForkId
    :: Network
    -> Tx      -- ^ transaction to sign
    -> Script  -- ^ script from output being spent
    -> Word64  -- ^ value of output being spent
    -> Int     -- ^ index of input being signed
    -> SigHash -- ^ what to sign
    -> Hash256 -- ^ hash to be signed
txSigHashForkId :: Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
txSigHashForkId net :: Network
net tx :: Tx
tx out :: Script
out v :: Word64
v i :: Int
i sh :: SigHash
sh =
    ByteString -> Hash256
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 (ByteString -> Hash256) -> (Put -> ByteString) -> Put -> Hash256
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> ByteString
runPut (Put -> Hash256) -> Put -> Hash256
forall a b. (a -> b) -> a -> b
$ do
        Putter Word32
putWord32le Putter Word32 -> Putter Word32
forall a b. (a -> b) -> a -> b
$ Tx -> Word32
txVersion Tx
tx
        Putter Hash256
forall t. Serialize t => Putter t
put Hash256
hashPrevouts
        Putter Hash256
forall t. Serialize t => Putter t
put Hash256
hashSequence
        Putter OutPoint
forall t. Serialize t => Putter t
put Putter OutPoint -> Putter OutPoint
forall a b. (a -> b) -> a -> b
$ TxIn -> OutPoint
prevOutput (TxIn -> OutPoint) -> TxIn -> OutPoint
forall a b. (a -> b) -> a -> b
$ Tx -> [TxIn]
txIn Tx
tx [TxIn] -> Int -> TxIn
forall a. [a] -> Int -> a
!! Int
i
        Script -> Put
forall t. Serialize t => Putter t
putScript Script
out
        Putter Word64
putWord64le Word64
v
        Putter Word32
putWord32le Putter Word32 -> Putter Word32
forall a b. (a -> b) -> a -> b
$ TxIn -> Word32
txInSequence (TxIn -> Word32) -> TxIn -> Word32
forall a b. (a -> b) -> a -> b
$ Tx -> [TxIn]
txIn Tx
tx [TxIn] -> Int -> TxIn
forall a. [a] -> Int -> a
!! Int
i
        Putter Hash256
forall t. Serialize t => Putter t
put Hash256
hashOutputs
        Putter Word32
putWord32le Putter Word32 -> Putter Word32
forall a b. (a -> b) -> a -> b
$ Tx -> Word32
txLockTime Tx
tx
        Putter Word32
putWord32le Putter Word32 -> Putter Word32
forall a b. (a -> b) -> a -> b
$ SigHash -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (SigHash -> Word32) -> SigHash -> Word32
forall a b. (a -> b) -> a -> b
$ Network -> SigHash -> SigHash
sigHashAddNetworkId Network
net SigHash
sh
  where
    hashPrevouts :: Hash256
hashPrevouts
        | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ SigHash -> Bool
hasAnyoneCanPayFlag SigHash
sh =
            ByteString -> Hash256
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 (ByteString -> Hash256) -> ByteString -> Hash256
forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ (TxIn -> Put) -> [TxIn] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Putter OutPoint
forall t. Serialize t => Putter t
put Putter OutPoint -> (TxIn -> OutPoint) -> TxIn -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxIn -> OutPoint
prevOutput) ([TxIn] -> Put) -> [TxIn] -> Put
forall a b. (a -> b) -> a -> b
$ Tx -> [TxIn]
txIn Tx
tx
        | Bool
otherwise = Hash256
zeros
    hashSequence :: Hash256
hashSequence
        | Bool -> Bool
not (SigHash -> Bool
hasAnyoneCanPayFlag SigHash
sh) Bool -> Bool -> Bool
&&
              Bool -> Bool
not (SigHash -> Bool
isSigHashSingle SigHash
sh) Bool -> Bool -> Bool
&& Bool -> Bool
not (SigHash -> Bool
isSigHashNone SigHash
sh) =
            ByteString -> Hash256
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 (ByteString -> Hash256) -> ByteString -> Hash256
forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ (TxIn -> Put) -> [TxIn] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Putter Word32
putWord32le Putter Word32 -> (TxIn -> Word32) -> TxIn -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxIn -> Word32
txInSequence) ([TxIn] -> Put) -> [TxIn] -> Put
forall a b. (a -> b) -> a -> b
$ Tx -> [TxIn]
txIn Tx
tx
        | Bool
otherwise = Hash256
zeros
    hashOutputs :: Hash256
hashOutputs
        | Bool -> Bool
not (SigHash -> Bool
isSigHashSingle SigHash
sh) Bool -> Bool -> Bool
&& Bool -> Bool
not (SigHash -> Bool
isSigHashNone SigHash
sh) =
            ByteString -> Hash256
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 (ByteString -> Hash256) -> ByteString -> Hash256
forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ (TxOut -> Put) -> [TxOut] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ TxOut -> Put
forall t. Serialize t => Putter t
put ([TxOut] -> Put) -> [TxOut] -> Put
forall a b. (a -> b) -> a -> b
$ Tx -> [TxOut]
txOut Tx
tx
        | SigHash -> Bool
isSigHashSingle SigHash
sh Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< [TxOut] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Tx -> [TxOut]
txOut Tx
tx) =
            ByteString -> Hash256
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 (ByteString -> Hash256) -> ByteString -> Hash256
forall a b. (a -> b) -> a -> b
$ TxOut -> ByteString
forall a. Serialize a => a -> ByteString
encode (TxOut -> ByteString) -> TxOut -> ByteString
forall a b. (a -> b) -> a -> b
$ Tx -> [TxOut]
txOut Tx
tx [TxOut] -> Int -> TxOut
forall a. [a] -> Int -> a
!! Int
i
        | Bool
otherwise = Hash256
zeros
    putScript :: a -> Put
putScript s :: a
s = do
        let encodedScript :: ByteString
encodedScript = a -> ByteString
forall a. Serialize a => a -> ByteString
encode a
s
        Int -> Put
forall a. Integral a => a -> Put
putVarInt (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ ByteString -> Int
BS.length ByteString
encodedScript
        Putter ByteString
putByteString ByteString
encodedScript
    zeros :: Hash256
    zeros :: Hash256
zeros = "0000000000000000000000000000000000000000000000000000000000000000"

-- | Data type representing a signature together with a 'SigHash'. The 'SigHash'
-- is serialized as one byte at the end of an ECDSA 'Sig'. All signatures in
-- transaction inputs are of type 'TxSignature'.
data TxSignature
    = TxSignature
          { TxSignature -> Sig
txSignature        :: !Sig
          , TxSignature -> SigHash
txSignatureSigHash :: !SigHash
          }
    | TxSignatureEmpty
    deriving (TxSignature -> TxSignature -> Bool
(TxSignature -> TxSignature -> Bool)
-> (TxSignature -> TxSignature -> Bool) -> Eq TxSignature
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxSignature -> TxSignature -> Bool
$c/= :: TxSignature -> TxSignature -> Bool
== :: TxSignature -> TxSignature -> Bool
$c== :: TxSignature -> TxSignature -> Bool
Eq, Int -> TxSignature -> ShowS
[TxSignature] -> ShowS
TxSignature -> String
(Int -> TxSignature -> ShowS)
-> (TxSignature -> String)
-> ([TxSignature] -> ShowS)
-> Show TxSignature
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxSignature] -> ShowS
$cshowList :: [TxSignature] -> ShowS
show :: TxSignature -> String
$cshow :: TxSignature -> String
showsPrec :: Int -> TxSignature -> ShowS
$cshowsPrec :: Int -> TxSignature -> ShowS
Show, (forall x. TxSignature -> Rep TxSignature x)
-> (forall x. Rep TxSignature x -> TxSignature)
-> Generic TxSignature
forall x. Rep TxSignature x -> TxSignature
forall x. TxSignature -> Rep TxSignature x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxSignature x -> TxSignature
$cfrom :: forall x. TxSignature -> Rep TxSignature x
Generic)

instance NFData TxSignature

-- | Serialize a 'TxSignature'.
encodeTxSig :: TxSignature -> BS.ByteString
encodeTxSig :: TxSignature -> ByteString
encodeTxSig TxSignatureEmpty = String -> ByteString
forall a. HasCallStack => String -> a
error "Can not encode an empty signature"
encodeTxSig (TxSignature sig :: Sig
sig (SigHash n :: Word32
n)) =
    Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ Putter Sig
putSig Sig
sig Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Putter Word8
putWord8 (Word32 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
n)

-- | Deserialize a 'TxSignature'.
decodeTxSig :: Network -> BS.ByteString -> Either String TxSignature
decodeTxSig :: Network -> ByteString -> Either String TxSignature
decodeTxSig _   bs :: ByteString
bs | ByteString -> Bool
BS.null ByteString
bs = String -> Either String TxSignature
forall a b. a -> Either a b
Left "Empty signature candidate"
decodeTxSig net :: Network
net bs :: ByteString
bs =
    case ByteString -> Maybe Sig
decodeStrictSig (ByteString -> Maybe Sig) -> ByteString -> Maybe Sig
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
BS.init ByteString
bs of
        Just sig :: Sig
sig -> do
            let sh :: SigHash
sh = Word8 -> SigHash
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> SigHash) -> Word8 -> SigHash
forall a b. (a -> b) -> a -> b
$ ByteString -> Word8
BS.last ByteString
bs
            Bool -> Either String () -> Either String ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (SigHash -> Bool
isSigHashUnknown SigHash
sh) (Either String () -> Either String ())
-> Either String () -> Either String ()
forall a b. (a -> b) -> a -> b
$
                String -> Either String ()
forall a b. a -> Either a b
Left "Non-canonical signature: unknown hashtype byte"
            Bool -> Either String () -> Either String ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Word32 -> Bool
forall a. Maybe a -> Bool
isNothing (Network -> Maybe Word32
getSigHashForkId Network
net) Bool -> Bool -> Bool
&& SigHash -> Bool
hasForkIdFlag SigHash
sh) (Either String () -> Either String ())
-> Either String () -> Either String ()
forall a b. (a -> b) -> a -> b
$
                String -> Either String ()
forall a b. a -> Either a b
Left "Non-canonical signature: invalid network for forkId"
            TxSignature -> Either String TxSignature
forall (m :: * -> *) a. Monad m => a -> m a
return (TxSignature -> Either String TxSignature)
-> TxSignature -> Either String TxSignature
forall a b. (a -> b) -> a -> b
$ Sig -> SigHash -> TxSignature
TxSignature Sig
sig SigHash
sh
        Nothing -> String -> Either String TxSignature
forall a b. a -> Either a b
Left "Non-canonical signature: could not parse signature"