{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
module Haskoin.Script.SigHash (
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.Bytes.Get
import Data.Bytes.Put
import Data.Bytes.Serial
import Data.Hashable
import Data.Maybe
import Data.Scientific
import Data.Word
import GHC.Generics (Generic)
import Haskoin.Crypto
import Haskoin.Crypto.Hash
import Haskoin.Data
import Haskoin.Network.Common
import Haskoin.Script.Common
import Haskoin.Transaction.Common
import Haskoin.Util
data SigHashFlag
=
SIGHASH_ALL
|
SIGHASH_NONE
|
SIGHASH_SINGLE
|
SIGHASH_FORKID
|
SIGHASH_ANYONECANPAY
deriving (SigHashFlag -> SigHashFlag -> Bool
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
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
Ord, Int -> SigHashFlag -> ShowS
[SigHashFlag] -> ShowS
SigHashFlag -> String
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]
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. 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 SigHashFlag
SIGHASH_ALL = Int
0x01
fromEnum SigHashFlag
SIGHASH_NONE = Int
0x02
fromEnum SigHashFlag
SIGHASH_SINGLE = Int
0x03
fromEnum SigHashFlag
SIGHASH_FORKID = Int
0x40
fromEnum SigHashFlag
SIGHASH_ANYONECANPAY = Int
0x80
toEnum :: Int -> SigHashFlag
toEnum Int
0x01 = SigHashFlag
SIGHASH_ALL
toEnum Int
0x02 = SigHashFlag
SIGHASH_NONE
toEnum Int
0x03 = SigHashFlag
SIGHASH_SINGLE
toEnum Int
0x40 = SigHashFlag
SIGHASH_FORKID
toEnum Int
0x80 = SigHashFlag
SIGHASH_ANYONECANPAY
toEnum Int
_ = forall a. HasCallStack => String -> a
error String
"Not a valid sighash flag"
newtype SigHash
= SigHash Word32
deriving
( SigHash -> SigHash -> Bool
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
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
Ord
, Eq SigHash
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
Bits
, Int -> SigHash
SigHash -> Int
SigHash -> [SigHash]
SigHash -> SigHash
SigHash -> SigHash -> [SigHash]
SigHash -> SigHash -> SigHash -> [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
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
Integral
, Integer -> SigHash
SigHash -> SigHash
SigHash -> SigHash -> 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
SigHash -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: SigHash -> Rational
$ctoRational :: SigHash -> Rational
Real
, Int -> SigHash -> ShowS
[SigHash] -> ShowS
SigHash -> String
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]
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. 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
, Eq SigHash
Int -> SigHash -> Int
SigHash -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: SigHash -> Int
$chash :: SigHash -> Int
hashWithSalt :: Int -> SigHash -> Int
$chashWithSalt :: Int -> SigHash -> Int
Hashable
, SigHash -> ()
forall a. (a -> ()) -> NFData a
rnf :: SigHash -> ()
$crnf :: SigHash -> ()
NFData
)
instance J.FromJSON SigHash where
parseJSON :: Value -> Parser SigHash
parseJSON =
forall a. String -> (Scientific -> Parser a) -> Value -> Parser a
J.withScientific String
"sighash" forall a b. (a -> b) -> a -> b
$
forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (m :: * -> *) a. MonadPlus m => m a
mzero (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> SigHash
SigHash) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i. (Integral i, Bounded i) => Scientific -> Maybe i
toBoundedInteger
instance J.ToJSON SigHash where
toJSON :: SigHash -> Value
toJSON = Scientific -> Value
J.Number forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral
toEncoding :: SigHash -> Encoding
toEncoding (SigHash Word32
n) = forall a. ToJSON a => a -> Encoding
J.toEncoding Word32
n
sigHashNone :: SigHash
sigHashNone :: SigHash
sigHashNone = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_NONE
sigHashAll :: SigHash
sigHashAll :: SigHash
sigHashAll = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_ALL
sigHashSingle :: SigHash
sigHashSingle :: SigHash
sigHashSingle = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_SINGLE
sigHashForkId :: SigHash
sigHashForkId :: SigHash
sigHashForkId = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_FORKID
sigHashAnyoneCanPay :: SigHash
sigHashAnyoneCanPay :: SigHash
sigHashAnyoneCanPay = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> Int
fromEnum SigHashFlag
SIGHASH_ANYONECANPAY
setForkIdFlag :: SigHash -> SigHash
setForkIdFlag :: SigHash -> SigHash
setForkIdFlag = (forall a. Bits a => a -> a -> a
.|. SigHash
sigHashForkId)
setAnyoneCanPayFlag :: SigHash -> SigHash
setAnyoneCanPayFlag :: SigHash -> SigHash
setAnyoneCanPayFlag = (forall a. Bits a => a -> a -> a
.|. SigHash
sigHashAnyoneCanPay)
hasForkIdFlag :: SigHash -> Bool
hasForkIdFlag :: SigHash -> Bool
hasForkIdFlag = (forall a. Eq a => a -> a -> Bool
/= SigHash
0) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Bits a => a -> a -> a
.&. SigHash
sigHashForkId)
hasAnyoneCanPayFlag :: SigHash -> Bool
hasAnyoneCanPayFlag :: SigHash -> Bool
hasAnyoneCanPayFlag = (forall a. Eq a => a -> a -> Bool
/= SigHash
0) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Bits a => a -> a -> a
.&. SigHash
sigHashAnyoneCanPay)
isSigHashAll :: SigHash -> Bool
isSigHashAll :: SigHash -> Bool
isSigHashAll = (forall a. Eq a => a -> a -> Bool
== SigHash
sigHashAll) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Bits a => a -> a -> a
.&. SigHash
0x1f)
isSigHashNone :: SigHash -> Bool
isSigHashNone :: SigHash -> Bool
isSigHashNone = (forall a. Eq a => a -> a -> Bool
== SigHash
sigHashNone) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Bits a => a -> a -> a
.&. SigHash
0x1f)
isSigHashSingle :: SigHash -> Bool
isSigHashSingle :: SigHash -> Bool
isSigHashSingle = (forall a. Eq a => a -> a -> Bool
== SigHash
sigHashSingle) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Bits a => a -> a -> a
.&. SigHash
0x1f)
isSigHashUnknown :: SigHash -> Bool
isSigHashUnknown :: SigHash -> Bool
isSigHashUnknown =
(forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [SigHash
sigHashAll, SigHash
sigHashNone, SigHash
sigHashSingle]) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Bits a => a -> a -> a
.&. SigHash
0x1f)
sigHashAddForkId :: SigHash -> Word32 -> SigHash
sigHashAddForkId :: SigHash -> Word32 -> SigHash
sigHashAddForkId SigHash
sh Word32
w = (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
w forall a. Bits a => a -> Int -> a
`shiftL` Int
8) forall a. Bits a => a -> a -> a
.|. (SigHash
sh forall a. Bits a => a -> a -> a
.&. SigHash
0x000000ff)
sigHashAddNetworkId :: Network -> SigHash -> SigHash
sigHashAddNetworkId :: Network -> SigHash -> SigHash
sigHashAddNetworkId Network
net =
(SigHash -> Word32 -> SigHash
`sigHashAddForkId` forall a. a -> Maybe a -> a
fromMaybe Word32
0 (Network -> Maybe Word32
getSigHashForkId Network
net))
sigHashGetForkId :: SigHash -> Word32
sigHashGetForkId :: SigHash -> Word32
sigHashGetForkId (SigHash Word32
n) = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Word32
n forall a. Bits a => a -> Int -> a
`shiftR` Int
8
txSigHash ::
Network ->
Tx ->
Script ->
Word64 ->
Int ->
SigHash ->
Hash256
txSigHash :: Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
txSigHash Network
net Tx
tx Script
out Word64
v Int
i SigHash
sh
| SigHash -> Bool
hasForkIdFlag SigHash
sh Bool -> Bool -> 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
forall a. a -> Maybe a -> a
fromMaybe Hash256
one 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)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 forall a b. (a -> b) -> a -> b
$
Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ do
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Tx
newTx
forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral SigHash
sh
where
fout :: Script
fout = [ScriptOp] -> Script
Script forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Eq a => a -> a -> Bool
/= ScriptOp
OP_CODESEPARATOR) forall a b. (a -> b) -> a -> b
$ Script -> [ScriptOp]
scriptOps Script
out
one :: Hash256
one = Hash256
"0100000000000000000000000000000000000000000000000000000000000000"
buildInputs :: [TxIn] -> Script -> Int -> SigHash -> [TxIn]
buildInputs :: [TxIn] -> Script -> Int -> SigHash -> [TxIn]
buildInputs [TxIn]
txins Script
out Int
i SigHash
sh
| SigHash -> Bool
hasAnyoneCanPayFlag SigHash
sh =
[([TxIn]
txins forall a. [a] -> Int -> a
!! Int
i){scriptInput :: ByteString
scriptInput = Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Script
out}]
| SigHash -> Bool
isSigHashAll SigHash
sh Bool -> Bool -> Bool
|| SigHash -> Bool
isSigHashUnknown SigHash
sh = [TxIn]
single
| Bool
otherwise = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith TxIn -> Int -> TxIn
noSeq [TxIn]
single [Int
0 ..]
where
emptyIn :: [TxIn]
emptyIn = forall a b. (a -> b) -> [a] -> [b]
map (\TxIn
ti -> TxIn
ti{scriptInput :: ByteString
scriptInput = ByteString
BS.empty}) [TxIn]
txins
single :: [TxIn]
single =
forall a. Int -> [a] -> (a -> a) -> [a]
updateIndex Int
i [TxIn]
emptyIn forall a b. (a -> b) -> a -> b
$ \TxIn
ti -> TxIn
ti{scriptInput :: ByteString
scriptInput = Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Script
out}
noSeq :: TxIn -> Int -> TxIn
noSeq TxIn
ti Int
j =
if Int
i forall a. Eq a => a -> a -> Bool
== Int
j
then TxIn
ti
else TxIn
ti{txInSequence :: Word32
txInSequence = Word32
0}
buildOutputs :: [TxOut] -> Int -> SigHash -> Maybe [TxOut]
buildOutputs :: [TxOut] -> Int -> SigHash -> Maybe [TxOut]
buildOutputs [TxOut]
txos Int
i SigHash
sh
| SigHash -> Bool
isSigHashAll SigHash
sh Bool -> Bool -> Bool
|| SigHash -> Bool
isSigHashUnknown SigHash
sh = forall (m :: * -> *) a. Monad m => a -> m a
return [TxOut]
txos
| SigHash -> Bool
isSigHashNone SigHash
sh = forall (m :: * -> *) a. Monad m => a -> m a
return []
| Int
i forall a. Ord a => a -> a -> Bool
>= forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxOut]
txos = forall a. Maybe a
Nothing
| Bool
otherwise = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ [TxOut]
buffer forall a. [a] -> [a] -> [a]
++ [[TxOut]
txos forall a. [a] -> Int -> a
!! Int
i]
where
buffer :: [TxOut]
buffer = forall a. Int -> a -> [a]
replicate Int
i forall a b. (a -> b) -> a -> b
$ Word64 -> ByteString -> TxOut
TxOut forall a. Bounded a => a
maxBound ByteString
BS.empty
txSigHashForkId ::
Network ->
Tx ->
Script ->
Word64 ->
Int ->
SigHash ->
Hash256
txSigHashForkId :: Network -> Tx -> Script -> Word64 -> Int -> SigHash -> Hash256
txSigHashForkId Network
net Tx
tx Script
out Word64
v Int
i SigHash
sh =
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ do
forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le forall a b. (a -> b) -> a -> b
$ Tx -> Word32
txVersion Tx
tx
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Hash256
hashPrevouts
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Hash256
hashSequence
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize forall a b. (a -> b) -> a -> b
$ TxIn -> OutPoint
prevOutput forall a b. (a -> b) -> a -> b
$ Tx -> [TxIn]
txIn Tx
tx forall a. [a] -> Int -> a
!! Int
i
forall {m :: * -> *} {p}. (MonadPut m, Serial p) => p -> m ()
putScript Script
out
forall (m :: * -> *). MonadPut m => Word64 -> m ()
putWord64le Word64
v
forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le forall a b. (a -> b) -> a -> b
$ TxIn -> Word32
txInSequence forall a b. (a -> b) -> a -> b
$ Tx -> [TxIn]
txIn Tx
tx forall a. [a] -> Int -> a
!! Int
i
forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Hash256
hashOutputs
forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le forall a b. (a -> b) -> a -> b
$ Tx -> Word32
txLockTime Tx
tx
forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Network -> SigHash -> SigHash
sigHashAddNetworkId Network
net SigHash
sh
where
hashPrevouts :: Hash256
hashPrevouts
| Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ SigHash -> Bool
hasAnyoneCanPayFlag SigHash
sh =
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxIn -> OutPoint
prevOutput) 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) =
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxIn -> Word32
txInSequence) 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) =
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize forall a b. (a -> b) -> a -> b
$ Tx -> [TxOut]
txOut Tx
tx
| SigHash -> Bool
isSigHashSingle SigHash
sh Bool -> Bool -> Bool
&& Int
i forall a. Ord a => a -> a -> Bool
< forall (t :: * -> *) a. Foldable t => t a -> Int
length (Tx -> [TxOut]
txOut Tx
tx) =
forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 forall a b. (a -> b) -> a -> b
$ Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize forall a b. (a -> b) -> a -> b
$ Tx -> [TxOut]
txOut Tx
tx forall a. [a] -> Int -> a
!! Int
i
| Bool
otherwise = Hash256
zeros
putScript :: p -> m ()
putScript p
s = do
let encodedScript :: ByteString
encodedScript = Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize p
s
forall (m :: * -> *) a. (MonadPut m, Integral a) => a -> m ()
putVarInt forall a b. (a -> b) -> a -> b
$ ByteString -> Int
BS.length ByteString
encodedScript
forall (m :: * -> *). MonadPut m => ByteString -> m ()
putByteString ByteString
encodedScript
zeros :: Hash256
zeros :: Hash256
zeros = Hash256
"0000000000000000000000000000000000000000000000000000000000000000"
data TxSignature
= TxSignature
{ TxSignature -> Sig
txSignature :: !Sig
, TxSignature -> SigHash
txSignatureSigHash :: !SigHash
}
| TxSignatureEmpty
deriving (TxSignature -> TxSignature -> Bool
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
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. 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
encodeTxSig :: TxSignature -> BS.ByteString
encodeTxSig :: TxSignature -> ByteString
encodeTxSig TxSignature
TxSignatureEmpty = forall a. HasCallStack => String -> a
error String
"Can not encode an empty signature"
encodeTxSig (TxSignature Sig
sig (SigHash Word32
n)) =
Put -> ByteString
runPutS forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). MonadPut m => Sig -> m ()
putSig Sig
sig forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
n)
decodeTxSig :: Network -> BS.ByteString -> Either String TxSignature
decodeTxSig :: Network -> ByteString -> Either String TxSignature
decodeTxSig Network
_ ByteString
bs | ByteString -> Bool
BS.null ByteString
bs = forall a b. a -> Either a b
Left String
"Empty signature candidate"
decodeTxSig Network
net ByteString
bs =
case ByteString -> Maybe Sig
decodeStrictSig forall a b. (a -> b) -> a -> b
$ HasCallStack => ByteString -> ByteString
BS.init ByteString
bs of
Just Sig
sig -> do
let sh :: SigHash
sh = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ HasCallStack => ByteString -> Word8
BS.last ByteString
bs
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (SigHash -> Bool
isSigHashUnknown SigHash
sh) forall a b. (a -> b) -> a -> b
$
forall a b. a -> Either a b
Left String
"Non-canonical signature: unknown hashtype byte"
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall a. Maybe a -> Bool
isNothing (Network -> Maybe Word32
getSigHashForkId Network
net) Bool -> Bool -> Bool
&& SigHash -> Bool
hasForkIdFlag SigHash
sh) forall a b. (a -> b) -> a -> b
$
forall a b. a -> Either a b
Left String
"Non-canonical signature: invalid network for forkId"
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Sig -> SigHash -> TxSignature
TxSignature Sig
sig SigHash
sh
Maybe Sig
Nothing -> forall a b. a -> Either a b
Left String
"Non-canonical signature: could not parse signature"