{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NoFieldSelectors #-}

-- |
-- Module      : Haskoin.Transaction.Builder.Sign
-- Copyright   : No rights reserved
-- License     : MIT
-- Maintainer  : jprupp@protonmail.ch
-- Stability   : experimental
-- Portability : POSIX
--
-- Types and logic for signing transactions.
module Haskoin.Transaction.Builder.Sign
  ( SigInput (..),
    makeSignature,
    makeSigHash,
    signTx,
    findInputIndex,
    signInput,
    buildInput,
    sigKeys,
  )
where

import Control.DeepSeq
import Control.Monad
import Crypto.Secp256k1
import Data.Aeson
import Data.Aeson.Encoding
import Data.Bytes.Get
import Data.Bytes.Put
import Data.Bytes.Serial
import Data.Either
import Data.Hashable
import Data.List
import Data.Maybe
import Data.Word
import GHC.Generics
import Haskoin.Address
import Haskoin.Crypto.Hash
import Haskoin.Crypto.Keys.Common
import Haskoin.Crypto.Signature
import Haskoin.Network.Data
import Haskoin.Script
import Haskoin.Transaction.Common
import Haskoin.Transaction.Segwit
import Haskoin.Util

-- | Data type used to specify the signing parameters of a transaction input.
-- To sign an input, the previous output script, outpoint and sighash are
-- required. When signing a pay to script hash output, an additional redeem
-- script is required.
data SigInput = SigInput
  { -- | output script to spend
    -- ^ output script value
    SigInput -> ScriptOutput
script :: !ScriptOutput,
    -- | output script value
    -- ^ outpoint to spend
    SigInput -> Word64
value :: !Word64,
    -- | outpoint to spend
    -- ^ signature type
    SigInput -> OutPoint
outpoint :: !OutPoint,
    -- | signature type
    -- ^ redeem script
    SigInput -> SigHash
sighash :: !SigHash,
    -- | redeem script
    SigInput -> Maybe ScriptOutput
redeem :: !(Maybe RedeemScript)
  }
  deriving (Int -> SigInput -> ShowS
[SigInput] -> ShowS
SigInput -> String
(Int -> SigInput -> ShowS)
-> (SigInput -> String) -> ([SigInput] -> ShowS) -> Show SigInput
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SigInput -> ShowS
showsPrec :: Int -> SigInput -> ShowS
$cshow :: SigInput -> String
show :: SigInput -> String
$cshowList :: [SigInput] -> ShowS
showList :: [SigInput] -> ShowS
Show, ReadPrec [SigInput]
ReadPrec SigInput
Int -> ReadS SigInput
ReadS [SigInput]
(Int -> ReadS SigInput)
-> ReadS [SigInput]
-> ReadPrec SigInput
-> ReadPrec [SigInput]
-> Read SigInput
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS SigInput
readsPrec :: Int -> ReadS SigInput
$creadList :: ReadS [SigInput]
readList :: ReadS [SigInput]
$creadPrec :: ReadPrec SigInput
readPrec :: ReadPrec SigInput
$creadListPrec :: ReadPrec [SigInput]
readListPrec :: ReadPrec [SigInput]
Read, SigInput -> SigInput -> Bool
(SigInput -> SigInput -> Bool)
-> (SigInput -> SigInput -> Bool) -> Eq SigInput
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SigInput -> SigInput -> Bool
== :: SigInput -> SigInput -> Bool
$c/= :: SigInput -> SigInput -> Bool
/= :: SigInput -> SigInput -> Bool
Eq, (forall x. SigInput -> Rep SigInput x)
-> (forall x. Rep SigInput x -> SigInput) -> Generic SigInput
forall x. Rep SigInput x -> SigInput
forall x. SigInput -> Rep SigInput x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SigInput -> Rep SigInput x
from :: forall x. SigInput -> Rep SigInput x
$cto :: forall x. Rep SigInput x -> SigInput
to :: forall x. Rep SigInput x -> SigInput
Generic, SigInput -> ()
(SigInput -> ()) -> NFData SigInput
forall a. (a -> ()) -> NFData a
$crnf :: SigInput -> ()
rnf :: SigInput -> ()
NFData)

instance MarshalJSON Ctx SigInput where
  marshalValue :: Ctx -> SigInput -> Value
marshalValue Ctx
ctx (SigInput ScriptOutput
s Word64
v OutPoint
o SigHash
h Maybe ScriptOutput
r) =
    [Pair] -> Value
object ([Pair] -> Value) -> [Pair] -> Value
forall a b. (a -> b) -> a -> b
$
      [ Key
"pkscript" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Ctx -> ScriptOutput -> Value
forall s a. MarshalJSON s a => s -> a -> Value
marshalValue Ctx
ctx ScriptOutput
s,
        Key
"value" Key -> Word64 -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Word64
v,
        Key
"outpoint" Key -> OutPoint -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= OutPoint
o,
        Key
"sighash" Key -> SigHash -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= SigHash
h
      ]
        [Pair] -> [Pair] -> [Pair]
forall a. [a] -> [a] -> [a]
++ [ Key
"redeem" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Ctx -> ScriptOutput -> Value
forall s a. MarshalJSON s a => s -> a -> Value
marshalValue Ctx
ctx ScriptOutput
r
             | ScriptOutput
r <- Maybe ScriptOutput -> [ScriptOutput]
forall a. Maybe a -> [a]
maybeToList Maybe ScriptOutput
r
           ]

  marshalEncoding :: Ctx -> SigInput -> Encoding
marshalEncoding Ctx
ctx (SigInput ScriptOutput
s Word64
v OutPoint
o SigHash
h Maybe ScriptOutput
r) =
    Series -> Encoding
pairs (Series -> Encoding) -> Series -> Encoding
forall a b. (a -> b) -> a -> b
$
      [Series] -> Series
forall a. Monoid a => [a] -> a
mconcat
        [ Key
"pkscript" Key -> Encoding -> Series
`pair` Ctx -> ScriptOutput -> Encoding
forall s a. MarshalJSON s a => s -> a -> Encoding
marshalEncoding Ctx
ctx ScriptOutput
s,
          Key
"value" Key -> Encoding -> Series
`pair` Word64 -> Encoding
word64 Word64
v,
          Key
"outpoint" Key -> Encoding -> Series
`pair` OutPoint -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding OutPoint
o,
          Key
"sighash" Key -> Encoding -> Series
`pair` SigHash -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding SigHash
h,
          Series -> (ScriptOutput -> Series) -> Maybe ScriptOutput -> Series
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Series
forall a. Monoid a => a
mempty (Key -> Encoding -> Series
pair Key
"redeem" (Encoding -> Series)
-> (ScriptOutput -> Encoding) -> ScriptOutput -> Series
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ctx -> ScriptOutput -> Encoding
forall s a. MarshalJSON s a => s -> a -> Encoding
marshalEncoding Ctx
ctx) Maybe ScriptOutput
r
        ]

  unmarshalValue :: Ctx -> Value -> Parser SigInput
unmarshalValue Ctx
ctx =
    String -> (Object -> Parser SigInput) -> Value -> Parser SigInput
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SigInput" ((Object -> Parser SigInput) -> Value -> Parser SigInput)
-> (Object -> Parser SigInput) -> Value -> Parser SigInput
forall a b. (a -> b) -> a -> b
$ \Object
o ->
      ScriptOutput
-> Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput
SigInput
        (ScriptOutput
 -> Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput)
-> Parser ScriptOutput
-> Parser
     (Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ctx -> Value -> Parser ScriptOutput
forall s a. MarshalJSON s a => s -> Value -> Parser a
unmarshalValue Ctx
ctx (Value -> Parser ScriptOutput)
-> Parser Value -> Parser ScriptOutput
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Object
o Object -> Key -> Parser Value
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"pkscript")
        Parser
  (Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput)
-> Parser Word64
-> Parser (OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser Word64
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"value"
        Parser (OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput)
-> Parser OutPoint
-> Parser (SigHash -> Maybe ScriptOutput -> SigInput)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser OutPoint
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"outpoint"
        Parser (SigHash -> Maybe ScriptOutput -> SigInput)
-> Parser SigHash -> Parser (Maybe ScriptOutput -> SigInput)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser SigHash
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"sighash"
        Parser (Maybe ScriptOutput -> SigInput)
-> Parser (Maybe ScriptOutput) -> Parser SigInput
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((Value -> Parser ScriptOutput)
-> Maybe Value -> Parser (Maybe ScriptOutput)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Maybe a -> m (Maybe b)
mapM (Ctx -> Value -> Parser ScriptOutput
forall s a. MarshalJSON s a => s -> Value -> Parser a
unmarshalValue Ctx
ctx) (Maybe Value -> Parser (Maybe ScriptOutput))
-> Parser (Maybe Value) -> Parser (Maybe ScriptOutput)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Object
o Object -> Key -> Parser (Maybe Value)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"redeem")

-- | Sign a transaction by providing the 'SigInput' signing parameters and a
-- list of private keys. The signature is computed deterministically as defined
-- in RFC-6979.
signTx ::
  Network ->
  Ctx ->
  -- | transaction to sign
  Tx ->
  -- | signing parameters, with nesting flag
  [(SigInput, Bool)] ->
  -- | private keys to sign with
  [SecKey] ->
  -- | signed transaction
  Either String Tx
signTx :: Network
-> Ctx -> Tx -> [(SigInput, Bool)] -> [SecKey] -> Either String Tx
signTx Network
net Ctx
ctx Tx
otx [(SigInput, Bool)]
sigis [SecKey]
allKeys
  | [TxIn] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TxIn]
ti = String -> Either String Tx
forall a b. a -> Either a b
Left String
"signTx: Transaction has no inputs"
  | Bool
otherwise = (Tx -> ((SigInput, Bool), Int) -> Either String Tx)
-> Tx -> [((SigInput, Bool), Int)] -> Either String Tx
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM Tx -> ((SigInput, Bool), Int) -> Either String Tx
go Tx
otx ([((SigInput, Bool), Int)] -> Either String Tx)
-> [((SigInput, Bool), Int)] -> Either String Tx
forall a b. (a -> b) -> a -> b
$ ((SigInput, Bool) -> OutPoint)
-> [(SigInput, Bool)] -> [TxIn] -> [((SigInput, Bool), Int)]
forall a. (a -> OutPoint) -> [a] -> [TxIn] -> [(a, Int)]
findInputIndex ((.outpoint) (SigInput -> OutPoint)
-> ((SigInput, Bool) -> SigInput) -> (SigInput, Bool) -> OutPoint
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SigInput, Bool) -> SigInput
forall a b. (a, b) -> a
fst) [(SigInput, Bool)]
sigis [TxIn]
ti
  where
    ti :: [TxIn]
ti = Tx
otx.inputs
    go :: Tx -> ((SigInput, Bool), Int) -> Either String Tx
go Tx
tx (sigi :: (SigInput, Bool)
sigi@(SigInput ScriptOutput
so Word64
_ OutPoint
_ SigHash
_ Maybe ScriptOutput
rdmM, Bool
_), Int
i) = do
      [PrivateKey]
keys <- Ctx
-> ScriptOutput
-> Maybe ScriptOutput
-> [SecKey]
-> Either String [PrivateKey]
sigKeys Ctx
ctx ScriptOutput
so Maybe ScriptOutput
rdmM [SecKey]
allKeys
      (Tx -> PrivateKey -> Either String Tx)
-> Tx -> [PrivateKey] -> Either String Tx
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (\Tx
t PrivateKey
k -> Network
-> Ctx
-> Tx
-> Int
-> (SigInput, Bool)
-> PrivateKey
-> Either String Tx
signInput Network
net Ctx
ctx Tx
t Int
i (SigInput, Bool)
sigi PrivateKey
k) Tx
tx [PrivateKey]
keys

-- | Sign a single input in a transaction deterministically (RFC-6979).  The
-- nesting flag only affects the behavior of segwit inputs.
signInput ::
  Network ->
  Ctx ->
  Tx ->
  Int ->
  -- | boolean flag: nest input
  (SigInput, Bool) ->
  PrivateKey ->
  Either String Tx
signInput :: Network
-> Ctx
-> Tx
-> Int
-> (SigInput, Bool)
-> PrivateKey
-> Either String Tx
signInput Network
net Ctx
ctx Tx
tx Int
i (sigIn :: SigInput
sigIn@(SigInput ScriptOutput
so Word64
val OutPoint
_ SigHash
_ Maybe ScriptOutput
rdmM), Bool
nest) PrivateKey
key = do
  let sig :: TxSignature
sig = Network
-> Ctx -> Tx -> Int -> SigInput -> PrivateKey -> TxSignature
makeSignature Network
net Ctx
ctx Tx
tx Int
i SigInput
sigIn PrivateKey
key
  ScriptInput
si <- Network
-> Ctx
-> Tx
-> Int
-> ScriptOutput
-> Word64
-> Maybe ScriptOutput
-> TxSignature
-> PublicKey
-> Either String ScriptInput
buildInput Network
net Ctx
ctx Tx
tx Int
i ScriptOutput
so Word64
val Maybe ScriptOutput
rdmM TxSignature
sig (PublicKey -> Either String ScriptInput)
-> PublicKey -> Either String ScriptInput
forall a b. (a -> b) -> a -> b
$ Ctx -> PrivateKey -> PublicKey
derivePublicKey Ctx
ctx PrivateKey
key
  WitnessData
w <- Network
-> Ctx
-> Tx
-> Int
-> ScriptOutput
-> ScriptInput
-> Either String WitnessData
updatedWitnessData Network
net Ctx
ctx Tx
tx Int
i ScriptOutput
so ScriptInput
si
  Tx -> Either String Tx
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return Tx
tx {inputs = nextTxIn so si, witness = w}
  where
    f :: a -> TxIn -> TxIn
f a
si TxIn {Word32
ByteString
OutPoint
outpoint :: OutPoint
script :: ByteString
sequence :: Word32
$sel:outpoint:TxIn :: TxIn -> OutPoint
$sel:script:TxIn :: TxIn -> ByteString
$sel:sequence:TxIn :: TxIn -> Word32
..} = TxIn {$sel:script:TxIn :: ByteString
script = (Network, Ctx) -> a -> ByteString
forall s a. Marshal s a => s -> a -> ByteString
marshal (Network
net, Ctx
ctx) a
si, Word32
OutPoint
outpoint :: OutPoint
sequence :: Word32
$sel:outpoint:TxIn :: OutPoint
$sel:sequence:TxIn :: Word32
..}
    g :: a -> TxIn -> TxIn
g a
so' TxIn {Word32
ByteString
OutPoint
$sel:outpoint:TxIn :: TxIn -> OutPoint
$sel:script:TxIn :: TxIn -> ByteString
$sel:sequence:TxIn :: TxIn -> Word32
outpoint :: OutPoint
script :: ByteString
sequence :: Word32
..} = TxIn {$sel:script:TxIn :: ByteString
script = a -> ByteString
forall {a}. Marshal Ctx a => a -> ByteString
pkScript a
so', Word32
OutPoint
$sel:outpoint:TxIn :: OutPoint
$sel:sequence:TxIn :: Word32
outpoint :: OutPoint
sequence :: Word32
..}
    pkScript :: a -> ByteString
pkScript a
so' = Put -> ByteString
runPutS (Put -> ByteString)
-> (ByteString -> Put) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScriptOp -> Put
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
forall (m :: * -> *). MonadPut m => ScriptOp -> m ()
serialize (ScriptOp -> Put) -> (ByteString -> ScriptOp) -> ByteString -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ScriptOp
opPushData (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Ctx -> a -> ByteString
forall s a. Marshal s a => s -> a -> ByteString
marshal Ctx
ctx a
so'
    nextTxIn :: ScriptOutput -> a -> [TxIn]
nextTxIn ScriptOutput
so' a
si
      | ScriptOutput -> Bool
isSegwit ScriptOutput
so' Bool -> Bool -> Bool
&& Bool
nest = Int -> [TxIn] -> (TxIn -> TxIn) -> [TxIn]
forall a. Int -> [a] -> (a -> a) -> [a]
updateIndex Int
i Tx
tx.inputs (ScriptOutput -> TxIn -> TxIn
forall {a}. Marshal Ctx a => a -> TxIn -> TxIn
g ScriptOutput
so')
      | ScriptOutput -> Bool
isSegwit ScriptOutput
so' = Tx
tx.inputs
      | Bool
otherwise = Int -> [TxIn] -> (TxIn -> TxIn) -> [TxIn]
forall a. Int -> [a] -> (a -> a) -> [a]
updateIndex Int
i Tx
tx.inputs (a -> TxIn -> TxIn
forall {a}. Marshal (Network, Ctx) a => a -> TxIn -> TxIn
f a
si)

-- | Add the witness data of the transaction given segwit parameters for an input.
--
-- @since 0.11.0.0
updatedWitnessData ::
  Network ->
  Ctx ->
  Tx ->
  Int ->
  ScriptOutput ->
  ScriptInput ->
  Either String WitnessData
updatedWitnessData :: Network
-> Ctx
-> Tx
-> Int
-> ScriptOutput
-> ScriptInput
-> Either String WitnessData
updatedWitnessData Network
net Ctx
ctx Tx
tx Int
i ScriptOutput
so ScriptInput
si
  | ScriptOutput -> Bool
isSegwit ScriptOutput
so =
      WitnessStack -> Either String WitnessData
forall {a}. IsString a => WitnessStack -> Either a WitnessData
updateWitness (WitnessStack -> Either String WitnessData)
-> (WitnessProgram -> WitnessStack)
-> WitnessProgram
-> Either String WitnessData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Network -> Ctx -> WitnessProgram -> WitnessStack
toWitnessStack Network
net Ctx
ctx (WitnessProgram -> Either String WitnessData)
-> Either String WitnessProgram -> Either String WitnessData
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Network
-> Ctx
-> ScriptOutput
-> ScriptInput
-> Either String WitnessProgram
calcWitnessProgram Network
net Ctx
ctx ScriptOutput
so ScriptInput
si
  | Bool
otherwise =
      WitnessData -> Either String WitnessData
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return Tx
tx.witness
  where
    updateWitness :: WitnessStack -> Either a WitnessData
updateWitness WitnessStack
w
      | WitnessData -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Tx
tx.witness = WitnessData -> Either a WitnessData
forall a. a -> Either a a
forall (m :: * -> *) a. Monad m => a -> m a
return (WitnessData -> Either a WitnessData)
-> WitnessData -> Either a WitnessData
forall a b. (a -> b) -> a -> b
$ Int -> WitnessData -> (WitnessStack -> WitnessStack) -> WitnessData
forall a. Int -> [a] -> (a -> a) -> [a]
updateIndex Int
i WitnessData
defaultStack (WitnessStack -> WitnessStack -> WitnessStack
forall a b. a -> b -> a
const WitnessStack
w)
      | WitnessData -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Tx
tx.witness Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
n = a -> Either a WitnessData
forall a b. a -> Either a b
Left a
"Invalid number of witness stacks"
      | Bool
otherwise = WitnessData -> Either a WitnessData
forall a. a -> Either a a
forall (m :: * -> *) a. Monad m => a -> m a
return (WitnessData -> Either a WitnessData)
-> WitnessData -> Either a WitnessData
forall a b. (a -> b) -> a -> b
$ Int -> WitnessData -> (WitnessStack -> WitnessStack) -> WitnessData
forall a. Int -> [a] -> (a -> a) -> [a]
updateIndex Int
i Tx
tx.witness (WitnessStack -> WitnessStack -> WitnessStack
forall a b. a -> b -> a
const WitnessStack
w)
    defaultStack :: WitnessData
defaultStack = Int -> WitnessStack -> WitnessData
forall a. Int -> a -> [a]
replicate Int
n (WitnessStack -> WitnessData) -> WitnessStack -> WitnessData
forall a b. (a -> b) -> a -> b
$ Network -> Ctx -> WitnessProgram -> WitnessStack
toWitnessStack Network
net Ctx
ctx WitnessProgram
EmptyWitnessProgram
    n :: Int
n = [TxIn] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Tx
tx.inputs

-- | Associate an input index to each value in a list
findInputIndex ::
  -- | extract an outpoint
  (a -> OutPoint) ->
  -- | input list
  [a] ->
  -- | reference list of inputs
  [TxIn] ->
  [(a, Int)]
findInputIndex :: forall a. (a -> OutPoint) -> [a] -> [TxIn] -> [(a, Int)]
findInputIndex a -> OutPoint
getOutPoint [a]
as [TxIn]
ti =
  ((Maybe a, Int) -> Maybe (a, Int))
-> [(Maybe a, Int)] -> [(a, Int)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Maybe a, Int) -> Maybe (a, Int)
forall {a} {b}. (Maybe a, b) -> Maybe (a, b)
g ([(Maybe a, Int)] -> [(a, Int)]) -> [(Maybe a, Int)] -> [(a, Int)]
forall a b. (a -> b) -> a -> b
$ [Maybe a] -> [Int] -> [(Maybe a, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip ([a] -> [TxIn] -> (a -> TxIn -> Bool) -> [Maybe a]
forall a b. [a] -> [b] -> (a -> b -> Bool) -> [Maybe a]
matchTemplate [a]
as [TxIn]
ti a -> TxIn -> Bool
forall {r}. HasField "outpoint" r OutPoint => a -> r -> Bool
f) [Int
0 ..]
  where
    f :: a -> r -> Bool
f a
s r
txin = a -> OutPoint
getOutPoint a
s OutPoint -> OutPoint -> Bool
forall a. Eq a => a -> a -> Bool
== r
txin.outpoint
    g :: (Maybe a, b) -> Maybe (a, b)
g (Just a
s, b
i) = (a, b) -> Maybe (a, b)
forall a. a -> Maybe a
Just (a
s, b
i)
    g (Maybe a
Nothing, b
_) = Maybe (a, b)
forall a. Maybe a
Nothing

-- | Find from the list of provided private keys which one is required to sign
-- the 'ScriptOutput'.
sigKeys ::
  Ctx ->
  ScriptOutput ->
  Maybe RedeemScript ->
  [SecKey] ->
  Either String [PrivateKey]
sigKeys :: Ctx
-> ScriptOutput
-> Maybe ScriptOutput
-> [SecKey]
-> Either String [PrivateKey]
sigKeys Ctx
ctx ScriptOutput
so Maybe ScriptOutput
rdmM [SecKey]
keys =
  case (ScriptOutput
so, Maybe ScriptOutput
rdmM) of
    (PayPK PublicKey
p, Maybe ScriptOutput
Nothing) ->
      [PrivateKey] -> Either String [PrivateKey]
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return ([PrivateKey] -> Either String [PrivateKey])
-> (Maybe (PrivateKey, PublicKey) -> [PrivateKey])
-> Maybe (PrivateKey, PublicKey)
-> Either String [PrivateKey]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((PrivateKey, PublicKey) -> PrivateKey)
-> [(PrivateKey, PublicKey)] -> [PrivateKey]
forall a b. (a -> b) -> [a] -> [b]
map (PrivateKey, PublicKey) -> PrivateKey
forall a b. (a, b) -> a
fst ([(PrivateKey, PublicKey)] -> [PrivateKey])
-> (Maybe (PrivateKey, PublicKey) -> [(PrivateKey, PublicKey)])
-> Maybe (PrivateKey, PublicKey)
-> [PrivateKey]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (PrivateKey, PublicKey) -> [(PrivateKey, PublicKey)]
forall a. Maybe a -> [a]
maybeToList (Maybe (PrivateKey, PublicKey) -> Either String [PrivateKey])
-> Maybe (PrivateKey, PublicKey) -> Either String [PrivateKey]
forall a b. (a -> b) -> a -> b
$ ((PrivateKey, PublicKey) -> Bool)
-> [(PrivateKey, PublicKey)] -> Maybe (PrivateKey, PublicKey)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((PublicKey -> PublicKey -> Bool
forall a. Eq a => a -> a -> Bool
== PublicKey
p) (PublicKey -> Bool)
-> ((PrivateKey, PublicKey) -> PublicKey)
-> (PrivateKey, PublicKey)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PrivateKey, PublicKey) -> PublicKey
forall a b. (a, b) -> b
snd) [(PrivateKey, PublicKey)]
zipKeys
    (PayPKHash Hash160
h, Maybe ScriptOutput
Nothing) -> [PrivateKey] -> Either String [PrivateKey]
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return ([PrivateKey] -> Either String [PrivateKey])
-> [PrivateKey] -> Either String [PrivateKey]
forall a b. (a -> b) -> a -> b
$ Hash160 -> [PrivateKey]
keyByHash Hash160
h
    (PayMulSig [PublicKey]
ps Int
r, Maybe ScriptOutput
Nothing) ->
      [PrivateKey] -> Either String [PrivateKey]
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return ([PrivateKey] -> Either String [PrivateKey])
-> [PrivateKey] -> Either String [PrivateKey]
forall a b. (a -> b) -> a -> b
$ ((PrivateKey, PublicKey) -> PrivateKey)
-> [(PrivateKey, PublicKey)] -> [PrivateKey]
forall a b. (a -> b) -> [a] -> [b]
map (PrivateKey, PublicKey) -> PrivateKey
forall a b. (a, b) -> a
fst ([(PrivateKey, PublicKey)] -> [PrivateKey])
-> [(PrivateKey, PublicKey)] -> [PrivateKey]
forall a b. (a -> b) -> a -> b
$ Int -> [(PrivateKey, PublicKey)] -> [(PrivateKey, PublicKey)]
forall a. Int -> [a] -> [a]
take Int
r ([(PrivateKey, PublicKey)] -> [(PrivateKey, PublicKey)])
-> [(PrivateKey, PublicKey)] -> [(PrivateKey, PublicKey)]
forall a b. (a -> b) -> a -> b
$ ((PrivateKey, PublicKey) -> Bool)
-> [(PrivateKey, PublicKey)] -> [(PrivateKey, PublicKey)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((PublicKey -> [PublicKey] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [PublicKey]
ps) (PublicKey -> Bool)
-> ((PrivateKey, PublicKey) -> PublicKey)
-> (PrivateKey, PublicKey)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PrivateKey, PublicKey) -> PublicKey
forall a b. (a, b) -> b
snd) [(PrivateKey, PublicKey)]
zipKeys
    (PayScriptHash Hash160
_, Just ScriptOutput
rdm) -> Ctx
-> ScriptOutput
-> Maybe ScriptOutput
-> [SecKey]
-> Either String [PrivateKey]
sigKeys Ctx
ctx ScriptOutput
rdm Maybe ScriptOutput
forall a. Maybe a
Nothing [SecKey]
keys
    (PayWitnessPKHash Hash160
h, Maybe ScriptOutput
_) -> [PrivateKey] -> Either String [PrivateKey]
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return ([PrivateKey] -> Either String [PrivateKey])
-> [PrivateKey] -> Either String [PrivateKey]
forall a b. (a -> b) -> a -> b
$ Hash160 -> [PrivateKey]
keyByHash Hash160
h
    (PayWitnessScriptHash Hash256
_, Just ScriptOutput
rdm) -> Ctx
-> ScriptOutput
-> Maybe ScriptOutput
-> [SecKey]
-> Either String [PrivateKey]
sigKeys Ctx
ctx ScriptOutput
rdm Maybe ScriptOutput
forall a. Maybe a
Nothing [SecKey]
keys
    (ScriptOutput, Maybe ScriptOutput)
_ -> String -> Either String [PrivateKey]
forall a b. a -> Either a b
Left String
"sigKeys: Could not decode output script"
  where
    zipKeys :: [(PrivateKey, PublicKey)]
zipKeys =
      [ (PrivateKey
prv, PublicKey
pub)
        | SecKey
k <- [SecKey]
keys,
          Bool
t <- [Bool
True, Bool
False],
          let prv :: PrivateKey
prv = Bool -> SecKey -> PrivateKey
wrapSecKey Bool
t SecKey
k,
          let pub :: PublicKey
pub = Ctx -> PrivateKey -> PublicKey
derivePublicKey Ctx
ctx PrivateKey
prv
      ]
    keyByHash :: Hash160 -> [PrivateKey]
keyByHash Hash160
h = ((PrivateKey, PublicKey) -> PrivateKey)
-> [(PrivateKey, PublicKey)] -> [PrivateKey]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (PrivateKey, PublicKey) -> PrivateKey
forall a b. (a, b) -> a
fst ([(PrivateKey, PublicKey)] -> [PrivateKey])
-> ([(PrivateKey, PublicKey)] -> [(PrivateKey, PublicKey)])
-> [(PrivateKey, PublicKey)]
-> [PrivateKey]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (PrivateKey, PublicKey) -> [(PrivateKey, PublicKey)]
forall a. Maybe a -> [a]
maybeToList (Maybe (PrivateKey, PublicKey) -> [(PrivateKey, PublicKey)])
-> ([(PrivateKey, PublicKey)] -> Maybe (PrivateKey, PublicKey))
-> [(PrivateKey, PublicKey)]
-> [(PrivateKey, PublicKey)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash160
-> [(PrivateKey, PublicKey)] -> Maybe (PrivateKey, PublicKey)
forall {t :: * -> *} {a}.
Foldable t =>
Hash160 -> t (a, PublicKey) -> Maybe (a, PublicKey)
findKey Hash160
h ([(PrivateKey, PublicKey)] -> [PrivateKey])
-> [(PrivateKey, PublicKey)] -> [PrivateKey]
forall a b. (a -> b) -> a -> b
$ [(PrivateKey, PublicKey)]
zipKeys
    findKey :: Hash160 -> t (a, PublicKey) -> Maybe (a, PublicKey)
findKey Hash160
h = ((a, PublicKey) -> Bool)
-> t (a, PublicKey) -> Maybe (a, PublicKey)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (((a, PublicKey) -> Bool)
 -> t (a, PublicKey) -> Maybe (a, PublicKey))
-> ((a, PublicKey) -> Bool)
-> t (a, PublicKey)
-> Maybe (a, PublicKey)
forall a b. (a -> b) -> a -> b
$ (Hash160 -> Hash160 -> Bool
forall a. Eq a => a -> a -> Bool
== Hash160
h) (Hash160 -> Bool)
-> ((a, PublicKey) -> Hash160) -> (a, PublicKey) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.hash160) (Address -> Hash160)
-> ((a, PublicKey) -> Address) -> (a, PublicKey) -> Hash160
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ctx -> PublicKey -> Address
pubKeyAddr Ctx
ctx (PublicKey -> Address)
-> ((a, PublicKey) -> PublicKey) -> (a, PublicKey) -> Address
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, PublicKey) -> PublicKey
forall a b. (a, b) -> b
snd

-- | Construct an input for a transaction given a signature, public key and data
-- about the previous output.
buildInput ::
  Network ->
  Ctx ->
  -- | transaction where input will be added
  Tx ->
  -- | input index where signature will go
  Int ->
  -- | output script being spent
  ScriptOutput ->
  -- | amount of previous output
  Word64 ->
  -- | redeem script if pay-to-script-hash
  Maybe RedeemScript ->
  TxSignature ->
  PublicKey ->
  Either String ScriptInput
buildInput :: Network
-> Ctx
-> Tx
-> Int
-> ScriptOutput
-> Word64
-> Maybe ScriptOutput
-> TxSignature
-> PublicKey
-> Either String ScriptInput
buildInput Network
net Ctx
ctx Tx
tx Int
i ScriptOutput
so Word64
val Maybe ScriptOutput
rdmM TxSignature
sig PublicKey
pub = do
  Bool -> Either String () -> Either String ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= [TxIn] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Tx
tx.inputs) (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 String
"buildInput: Invalid input index"
  case (ScriptOutput
so, Maybe ScriptOutput
rdmM) of
    (PayScriptHash Hash160
_, Just ScriptOutput
rdm) ->
      ScriptOutput -> Either String ScriptInput
buildScriptHashInput ScriptOutput
rdm
    (PayWitnessScriptHash Hash256
_, Just ScriptOutput
rdm) ->
      ScriptOutput -> Either String ScriptInput
buildScriptHashInput ScriptOutput
rdm
    (PayWitnessPKHash Hash160
_, Maybe ScriptOutput
Nothing) ->
      ScriptInput -> Either String ScriptInput
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptInput -> Either String ScriptInput)
-> (SimpleInput -> ScriptInput)
-> SimpleInput
-> Either String ScriptInput
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SimpleInput -> ScriptInput
RegularInput (SimpleInput -> Either String ScriptInput)
-> SimpleInput -> Either String ScriptInput
forall a b. (a -> b) -> a -> b
$ TxSignature -> PublicKey -> SimpleInput
SpendPKHash TxSignature
sig PublicKey
pub
    (ScriptOutput
_, Maybe ScriptOutput
Nothing) ->
      ScriptOutput -> Either String ScriptInput
buildRegularInput ScriptOutput
so
    (ScriptOutput, Maybe ScriptOutput)
_ -> String -> Either String ScriptInput
forall a b. a -> Either a b
Left String
"buildInput: Invalid output/redeem script combination"
  where
    buildRegularInput :: ScriptOutput -> Either String ScriptInput
buildRegularInput = \case
      PayPK PublicKey
_ -> ScriptInput -> Either String ScriptInput
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptInput -> Either String ScriptInput)
-> ScriptInput -> Either String ScriptInput
forall a b. (a -> b) -> a -> b
$ SimpleInput -> ScriptInput
RegularInput (SimpleInput -> ScriptInput) -> SimpleInput -> ScriptInput
forall a b. (a -> b) -> a -> b
$ TxSignature -> SimpleInput
SpendPK TxSignature
sig
      PayPKHash Hash160
_ -> ScriptInput -> Either String ScriptInput
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptInput -> Either String ScriptInput)
-> ScriptInput -> Either String ScriptInput
forall a b. (a -> b) -> a -> b
$ SimpleInput -> ScriptInput
RegularInput (SimpleInput -> ScriptInput) -> SimpleInput -> ScriptInput
forall a b. (a -> b) -> a -> b
$ TxSignature -> PublicKey -> SimpleInput
SpendPKHash TxSignature
sig PublicKey
pub
      PayMulSig [PublicKey]
msPubs Int
r -> do
        let mSigs :: [TxSignature]
mSigs = Int -> [TxSignature] -> [TxSignature]
forall a. Int -> [a] -> [a]
take Int
r ([TxSignature] -> [TxSignature]) -> [TxSignature] -> [TxSignature]
forall a b. (a -> b) -> a -> b
$ [Maybe TxSignature] -> [TxSignature]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe TxSignature] -> [TxSignature])
-> [Maybe TxSignature] -> [TxSignature]
forall a b. (a -> b) -> a -> b
$ [TxSignature]
-> [PublicKey]
-> (TxSignature -> PublicKey -> Bool)
-> [Maybe TxSignature]
forall a b. [a] -> [b] -> (a -> b -> Bool) -> [Maybe a]
matchTemplate [TxSignature]
allSigs [PublicKey]
msPubs TxSignature -> PublicKey -> Bool
forall {r}. HasField "point" r PubKey => TxSignature -> r -> Bool
f
            allSigs :: [TxSignature]
allSigs = [TxSignature] -> [TxSignature]
forall a. Eq a => [a] -> [a]
nub ([TxSignature] -> [TxSignature]) -> [TxSignature] -> [TxSignature]
forall a b. (a -> b) -> a -> b
$ TxSignature
sig TxSignature -> [TxSignature] -> [TxSignature]
forall a. a -> [a] -> [a]
: Network -> Ctx -> Tx -> ScriptOutput -> Int -> [TxSignature]
parseExistingSigs Network
net Ctx
ctx Tx
tx ScriptOutput
so Int
i
        ScriptInput -> Either String ScriptInput
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptInput -> Either String ScriptInput)
-> ScriptInput -> Either String ScriptInput
forall a b. (a -> b) -> a -> b
$ SimpleInput -> ScriptInput
RegularInput (SimpleInput -> ScriptInput) -> SimpleInput -> ScriptInput
forall a b. (a -> b) -> a -> b
$ [TxSignature] -> SimpleInput
SpendMulSig [TxSignature]
mSigs
      ScriptOutput
_ -> String -> Either String ScriptInput
forall a b. a -> Either a b
Left String
"buildInput: Invalid output/redeem script combination"
    buildScriptHashInput :: ScriptOutput -> Either String ScriptInput
buildScriptHashInput ScriptOutput
rdm = do
      ScriptInput
inp <- ScriptOutput -> Either String ScriptInput
buildRegularInput ScriptOutput
rdm
      ScriptInput -> Either String ScriptInput
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptInput -> Either String ScriptInput)
-> ScriptInput -> Either String ScriptInput
forall a b. (a -> b) -> a -> b
$ SimpleInput -> ScriptOutput -> ScriptInput
ScriptHashInput ScriptInput
inp.get ScriptOutput
rdm
    f :: TxSignature -> r -> Bool
f (TxSignature Sig
x SigHash
sh) r
p =
      Ctx -> Hash256 -> Sig -> PubKey -> Bool
verifyHashSig
        Ctx
ctx
        (Network
-> Ctx
-> Tx
-> Int
-> ScriptOutput
-> Word64
-> SigHash
-> Maybe ScriptOutput
-> Hash256
makeSigHash Network
net Ctx
ctx Tx
tx Int
i ScriptOutput
so Word64
val SigHash
sh Maybe ScriptOutput
rdmM)
        Sig
x
        r
p.point
    f TxSignature
TxSignatureEmpty r
_ = Bool
False

-- | Apply heuristics to extract the signatures for a particular input that are
-- embedded in the transaction.
--
-- @since 0.11.0.0
parseExistingSigs :: Network -> Ctx -> Tx -> ScriptOutput -> Int -> [TxSignature]
parseExistingSigs :: Network -> Ctx -> Tx -> ScriptOutput -> Int -> [TxSignature]
parseExistingSigs Network
net Ctx
ctx Tx
tx ScriptOutput
so Int
i = [TxSignature]
insSigs [TxSignature] -> [TxSignature] -> [TxSignature]
forall a. Semigroup a => a -> a -> a
<> [TxSignature]
witSigs
  where
    insSigs :: [TxSignature]
insSigs = case (Network, Ctx) -> ByteString -> Either String ScriptInput
forall s a. Marshal s a => s -> ByteString -> Either String a
unmarshal (Network
net, Ctx
ctx) ByteString
scp of
      Right (ScriptHashInput (SpendMulSig [TxSignature]
xs) ScriptOutput
_) -> [TxSignature]
xs
      Right (RegularInput (SpendMulSig [TxSignature]
xs)) -> [TxSignature]
xs
      Either String ScriptInput
_ -> []
    scp :: ByteString
scp = (Tx
tx.inputs [TxIn] -> Int -> TxIn
forall a. HasCallStack => [a] -> Int -> a
!! Int
i).script
    witSigs :: [TxSignature]
witSigs
      | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ScriptOutput -> Bool
isSegwit ScriptOutput
so = []
      | WitnessData -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Tx
tx.witness = []
      | Bool
otherwise = [Either String TxSignature] -> [TxSignature]
forall a b. [Either a b] -> [b]
rights ([Either String TxSignature] -> [TxSignature])
-> [Either String TxSignature] -> [TxSignature]
forall a b. (a -> b) -> a -> b
$ Network -> Ctx -> ByteString -> Either String TxSignature
decodeTxSig Network
net Ctx
ctx (ByteString -> Either String TxSignature)
-> WitnessStack -> [Either String TxSignature]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Tx
tx.witness WitnessData -> Int -> WitnessStack
forall a. HasCallStack => [a] -> Int -> a
!! Int
i)

-- | Produce a structured representation of a deterministic (RFC-6979) signature over an input.
makeSignature :: Network -> Ctx -> Tx -> Int -> SigInput -> PrivateKey -> TxSignature
makeSignature :: Network
-> Ctx -> Tx -> Int -> SigInput -> PrivateKey -> TxSignature
makeSignature Network
net Ctx
ctx Tx
tx Int
i (SigInput ScriptOutput
so Word64
val OutPoint
_ SigHash
sh Maybe ScriptOutput
rdmM) PrivateKey
key =
  Sig -> SigHash -> TxSignature
TxSignature (Ctx -> SecKey -> Hash256 -> Sig
signHash Ctx
ctx PrivateKey
key.key Hash256
m) SigHash
sh
  where
    m :: Hash256
m = Network
-> Ctx
-> Tx
-> Int
-> ScriptOutput
-> Word64
-> SigHash
-> Maybe ScriptOutput
-> Hash256
makeSigHash Network
net Ctx
ctx Tx
tx Int
i ScriptOutput
so Word64
val SigHash
sh Maybe ScriptOutput
rdmM

-- | A function which selects the digest algorithm and parameters as appropriate
--
-- @since 0.11.0.0
makeSigHash ::
  Network ->
  Ctx ->
  Tx ->
  Int ->
  ScriptOutput ->
  Word64 ->
  SigHash ->
  Maybe RedeemScript ->
  Hash256
makeSigHash :: Network
-> Ctx
-> Tx
-> Int
-> ScriptOutput
-> Word64
-> SigHash
-> Maybe ScriptOutput
-> Hash256
makeSigHash Network
net Ctx
ctx Tx
tx Int
i ScriptOutput
so Word64
val SigHash
sh Maybe ScriptOutput
rdmM = Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
h Network
net Tx
tx (Ctx -> ScriptOutput -> Script
encodeOutput Ctx
ctx ScriptOutput
so') Word64
val Int
i SigHash
sh
  where
    so' :: ScriptOutput
so' = case ScriptOutput
so of
      PayWitnessPKHash Hash160
h' -> Hash160 -> ScriptOutput
PayPKHash Hash160
h'
      ScriptOutput
_ -> ScriptOutput -> Maybe ScriptOutput -> ScriptOutput
forall a. a -> Maybe a -> a
fromMaybe ScriptOutput
so Maybe ScriptOutput
rdmM
    h :: Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
h
      | ScriptOutput -> Bool
isSegwit ScriptOutput
so = Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
txSigHashForkId
      | Bool
otherwise = Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
txSigHash