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

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

Code related to transactions parsing and serialization.
-}
module Haskoin.Transaction.Common (
    -- * Transactions
    Tx (..),
    TxIn (..),
    TxOut (..),
    OutPoint (..),
    TxHash (..),
    WitnessData,
    WitnessStack,
    WitnessStackItem,
    txHash,
    hexToTxHash,
    txHashToHex,
    nosigTxHash,
    nullOutPoint,
) where

import Control.Applicative ((<|>))
import Control.DeepSeq
import Control.Monad (
    forM_,
    guard,
    liftM2,
    mzero,
    replicateM,
    unless,
    when,
    (<=<),
 )
import Data.Aeson as A
import Data.Aeson.Encoding (unsafeToEncoding)
import Data.Binary (Binary (..))
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.ByteString.Builder (char7)
import qualified Data.ByteString.Lazy as BL
import Data.Bytes.Get
import Data.Bytes.Put
import Data.Bytes.Serial
import Data.Hashable (Hashable)
import Data.Maybe (fromMaybe)
import Data.Serialize (Serialize (..))
import Data.String (IsString, fromString)
import Data.String.Conversions (cs)
import Data.Text (Text)
import Data.Word (Word32, Word64)
import GHC.Generics (Generic)
import Haskoin.Crypto.Hash
import Haskoin.Network.Common
import Haskoin.Util
import Text.Read as R

-- | Transaction id: hash of transaction excluding witness data.
newtype TxHash = TxHash {TxHash -> Hash256
getTxHash :: Hash256}
    deriving (TxHash -> TxHash -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxHash -> TxHash -> Bool
$c/= :: TxHash -> TxHash -> Bool
== :: TxHash -> TxHash -> Bool
$c== :: TxHash -> TxHash -> Bool
Eq, Eq TxHash
TxHash -> TxHash -> Bool
TxHash -> TxHash -> Ordering
TxHash -> TxHash -> TxHash
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 :: TxHash -> TxHash -> TxHash
$cmin :: TxHash -> TxHash -> TxHash
max :: TxHash -> TxHash -> TxHash
$cmax :: TxHash -> TxHash -> TxHash
>= :: TxHash -> TxHash -> Bool
$c>= :: TxHash -> TxHash -> Bool
> :: TxHash -> TxHash -> Bool
$c> :: TxHash -> TxHash -> Bool
<= :: TxHash -> TxHash -> Bool
$c<= :: TxHash -> TxHash -> Bool
< :: TxHash -> TxHash -> Bool
$c< :: TxHash -> TxHash -> Bool
compare :: TxHash -> TxHash -> Ordering
$ccompare :: TxHash -> TxHash -> Ordering
Ord, forall x. Rep TxHash x -> TxHash
forall x. TxHash -> Rep TxHash x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxHash x -> TxHash
$cfrom :: forall x. TxHash -> Rep TxHash x
Generic, Eq TxHash
Int -> TxHash -> Int
TxHash -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TxHash -> Int
$chash :: TxHash -> Int
hashWithSalt :: Int -> TxHash -> Int
$chashWithSalt :: Int -> TxHash -> Int
Hashable, forall a.
(forall (m :: * -> *). MonadPut m => a -> m ())
-> (forall (m :: * -> *). MonadGet m => m a) -> Serial a
forall (m :: * -> *). MonadGet m => m TxHash
forall (m :: * -> *). MonadPut m => TxHash -> m ()
deserialize :: forall (m :: * -> *). MonadGet m => m TxHash
$cdeserialize :: forall (m :: * -> *). MonadGet m => m TxHash
serialize :: forall (m :: * -> *). MonadPut m => TxHash -> m ()
$cserialize :: forall (m :: * -> *). MonadPut m => TxHash -> m ()
Serial, TxHash -> ()
forall a. (a -> ()) -> NFData a
rnf :: TxHash -> ()
$crnf :: TxHash -> ()
NFData)

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

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

instance Show TxHash where
    showsPrec :: Int -> TxHash -> ShowS
showsPrec Int
_ = forall a. Show a => a -> ShowS
shows forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxHash -> Text
txHashToHex

instance Read TxHash where
    readPrec :: ReadPrec TxHash
readPrec = do
        R.String String
str <- ReadPrec Lexeme
R.lexP
        forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. ReadPrec a
R.pfail forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text -> Maybe TxHash
hexToTxHash forall a b. (a -> b) -> a -> b
$ forall a b. ConvertibleStrings a b => a -> b
cs String
str

instance IsString TxHash where
    fromString :: String -> TxHash
fromString String
s =
        let e :: a
e = forall a. HasCallStack => String -> a
error String
"Could not read transaction hash from hex string"
         in forall a. a -> Maybe a -> a
fromMaybe forall {a}. a
e forall a b. (a -> b) -> a -> b
$ Text -> Maybe TxHash
hexToTxHash forall a b. (a -> b) -> a -> b
$ forall a b. ConvertibleStrings a b => a -> b
cs String
s

instance FromJSON TxHash where
    parseJSON :: Value -> Parser TxHash
parseJSON =
        forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"txid" 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
. Text -> Maybe TxHash
hexToTxHash

instance ToJSON TxHash where
    toJSON :: TxHash -> Value
toJSON = Text -> Value
A.String forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxHash -> Text
txHashToHex
    toEncoding :: TxHash -> Encoding
toEncoding TxHash
h =
        forall a. Builder -> Encoding' a
unsafeToEncoding forall a b. (a -> b) -> a -> b
$
            Char -> Builder
char7 Char
'"'
                forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
hexBuilder (ByteString -> ByteString
BL.reverse (Put -> ByteString
runPutL (forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize TxHash
h)))
                forall a. Semigroup a => a -> a -> a
<> Char -> Builder
char7 Char
'"'

-- | Transaction hash excluding signatures.
nosigTxHash :: Tx -> TxHash
nosigTxHash :: Tx -> TxHash
nosigTxHash Tx
tx =
    Hash256 -> TxHash
TxHash forall a b. (a -> b) -> a -> b
$
        forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 forall a b. (a -> b) -> a -> b
$
            Put -> WitnessStackItem
runPutS forall a b. (a -> b) -> a -> b
$
                forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Tx
tx{txIn :: [TxIn]
txIn = forall a b. (a -> b) -> [a] -> [b]
map TxIn -> TxIn
clearInput forall a b. (a -> b) -> a -> b
$ Tx -> [TxIn]
txIn Tx
tx}
  where
    clearInput :: TxIn -> TxIn
clearInput TxIn
ti = TxIn
ti{scriptInput :: WitnessStackItem
scriptInput = WitnessStackItem
B.empty}

-- | Convert transaction hash to hex form, reversing bytes.
txHashToHex :: TxHash -> Text
txHashToHex :: TxHash -> Text
txHashToHex (TxHash Hash256
h) = WitnessStackItem -> Text
encodeHex (WitnessStackItem -> WitnessStackItem
B.reverse (Put -> WitnessStackItem
runPutS (forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Hash256
h)))

-- | Convert transaction hash from hex, reversing bytes.
hexToTxHash :: Text -> Maybe TxHash
hexToTxHash :: Text -> Maybe TxHash
hexToTxHash Text
hex = do
    WitnessStackItem
bs <- WitnessStackItem -> WitnessStackItem
B.reverse forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Maybe WitnessStackItem
decodeHex Text
hex
    Hash256
h <- forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> b -> a
const forall a. Maybe a
Nothing) forall a. a -> Maybe a
Just (forall a. Get a -> WitnessStackItem -> Either String a
runGetS forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize WitnessStackItem
bs)
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Hash256 -> TxHash
TxHash Hash256
h

-- | Witness stack for SegWit transactions.
type WitnessData = [WitnessStack]

-- | Witness stack for SegWit transactions.
type WitnessStack = [WitnessStackItem]

-- | Witness stack item for SegWit transactions.
type WitnessStackItem = ByteString

-- | Data type representing a transaction.
data Tx = Tx
    { -- | transaction data format version
      Tx -> Word32
txVersion :: !Word32
    , -- | list of transaction inputs
      Tx -> [TxIn]
txIn :: ![TxIn]
    , -- | list of transaction outputs
      Tx -> [TxOut]
txOut :: ![TxOut]
    , -- | witness data for the transaction
      Tx -> WitnessData
txWitness :: !WitnessData
    , -- | earliest mining height or time
      Tx -> Word32
txLockTime :: !Word32
    }
    deriving (Int -> Tx -> ShowS
[Tx] -> ShowS
Tx -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Tx] -> ShowS
$cshowList :: [Tx] -> ShowS
show :: Tx -> String
$cshow :: Tx -> String
showsPrec :: Int -> Tx -> ShowS
$cshowsPrec :: Int -> Tx -> ShowS
Show, ReadPrec [Tx]
ReadPrec Tx
Int -> ReadS Tx
ReadS [Tx]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Tx]
$creadListPrec :: ReadPrec [Tx]
readPrec :: ReadPrec Tx
$creadPrec :: ReadPrec Tx
readList :: ReadS [Tx]
$creadList :: ReadS [Tx]
readsPrec :: Int -> ReadS Tx
$creadsPrec :: Int -> ReadS Tx
Read, Tx -> Tx -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Tx -> Tx -> Bool
$c/= :: Tx -> Tx -> Bool
== :: Tx -> Tx -> Bool
$c== :: Tx -> Tx -> Bool
Eq, Eq Tx
Tx -> Tx -> Bool
Tx -> Tx -> Ordering
Tx -> Tx -> Tx
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 :: Tx -> Tx -> Tx
$cmin :: Tx -> Tx -> Tx
max :: Tx -> Tx -> Tx
$cmax :: Tx -> Tx -> Tx
>= :: Tx -> Tx -> Bool
$c>= :: Tx -> Tx -> Bool
> :: Tx -> Tx -> Bool
$c> :: Tx -> Tx -> Bool
<= :: Tx -> Tx -> Bool
$c<= :: Tx -> Tx -> Bool
< :: Tx -> Tx -> Bool
$c< :: Tx -> Tx -> Bool
compare :: Tx -> Tx -> Ordering
$ccompare :: Tx -> Tx -> Ordering
Ord, forall x. Rep Tx x -> Tx
forall x. Tx -> Rep Tx x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Tx x -> Tx
$cfrom :: forall x. Tx -> Rep Tx x
Generic, Eq Tx
Int -> Tx -> Int
Tx -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Tx -> Int
$chash :: Tx -> Int
hashWithSalt :: Int -> Tx -> Int
$chashWithSalt :: Int -> Tx -> Int
Hashable, Tx -> ()
forall a. (a -> ()) -> NFData a
rnf :: Tx -> ()
$crnf :: Tx -> ()
NFData)

-- | Compute transaction hash.
txHash :: Tx -> TxHash
txHash :: Tx -> TxHash
txHash Tx
tx = Hash256 -> TxHash
TxHash forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b. ByteArrayAccess b => b -> Hash256
doubleSHA256 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> WitnessStackItem
runPutS forall a b. (a -> b) -> a -> b
$ forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize Tx
tx{txWitness :: WitnessData
txWitness = []}

instance IsString Tx where
    fromString :: String -> Tx
fromString =
        forall a. a -> Maybe a -> a
fromMaybe forall {a}. a
e forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a b. Either a b -> Maybe b
eitherToMaybe forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Get a -> WitnessStackItem -> Either String a
runGetS forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< Text -> Maybe WitnessStackItem
decodeHex) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. ConvertibleStrings a b => a -> b
cs
      where
        e :: a
e = forall a. HasCallStack => String -> a
error String
"Could not read transaction from hex string"

instance Serial Tx where
    deserialize :: forall (m :: * -> *). MonadGet m => m Tx
deserialize =
        forall (m :: * -> *). MonadGet m => m Bool
isWitnessTx forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Bool
w -> if Bool
w then forall (m :: * -> *). MonadGet m => m Tx
parseWitnessTx else forall (m :: * -> *). MonadGet m => m Tx
parseLegacyTx
    serialize :: forall (m :: * -> *). MonadPut m => Tx -> m ()
serialize Tx
tx
        | forall (t :: * -> *) a. Foldable t => t a -> Bool
null (Tx -> WitnessData
txWitness Tx
tx) = forall (m :: * -> *). MonadPut m => Tx -> m ()
putLegacyTx Tx
tx
        | Bool
otherwise = forall (m :: * -> *). MonadPut m => Tx -> m ()
putWitnessTx Tx
tx

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

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

putInOut :: MonadPut m => Tx -> m ()
putInOut :: forall (m :: * -> *). MonadPut m => Tx -> m ()
putInOut Tx
tx = do
    forall (m :: * -> *) a. (MonadPut m, Integral a) => a -> m ()
putVarInt forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length (Tx -> [TxIn]
txIn Tx
tx)
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Tx -> [TxIn]
txIn Tx
tx) forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize
    forall (m :: * -> *) a. (MonadPut m, Integral a) => a -> m ()
putVarInt forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length (Tx -> [TxOut]
txOut Tx
tx)
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Tx -> [TxOut]
txOut Tx
tx) forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize

-- | Non-SegWit transaction serializer.
putLegacyTx :: MonadPut m => Tx -> m ()
putLegacyTx :: forall (m :: * -> *). MonadPut m => Tx -> m ()
putLegacyTx Tx
tx = do
    forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le (Tx -> Word32
txVersion Tx
tx)
    forall (m :: * -> *). MonadPut m => Tx -> m ()
putInOut Tx
tx
    forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le (Tx -> Word32
txLockTime Tx
tx)

-- | Witness transaciton serializer.
putWitnessTx :: MonadPut m => Tx -> m ()
putWitnessTx :: forall (m :: * -> *). MonadPut m => Tx -> m ()
putWitnessTx Tx
tx = do
    forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le (Tx -> Word32
txVersion Tx
tx)
    forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x00
    forall (m :: * -> *). MonadPut m => Word8 -> m ()
putWord8 Word8
0x01
    forall (m :: * -> *). MonadPut m => Tx -> m ()
putInOut Tx
tx
    forall (m :: * -> *). MonadPut m => WitnessData -> m ()
putWitnessData (Tx -> WitnessData
txWitness Tx
tx)
    forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le (Tx -> Word32
txLockTime Tx
tx)

isWitnessTx :: MonadGet m => m Bool
isWitnessTx :: forall (m :: * -> *). MonadGet m => m Bool
isWitnessTx = forall (m :: * -> *) a. MonadGet m => m a -> m a
lookAhead forall a b. (a -> b) -> a -> b
$ do
    Word32
_ <- forall (m :: * -> *). MonadGet m => m Word32
getWord32le
    Word8
m <- forall (m :: * -> *). MonadGet m => m Word8
getWord8
    Word8
f <- forall (m :: * -> *). MonadGet m => m Word8
getWord8
    forall (m :: * -> *) a. Monad m => a -> m a
return (Word8
m forall a. Eq a => a -> a -> Bool
== Word8
0x00 Bool -> Bool -> Bool
&& Word8
f forall a. Eq a => a -> a -> Bool
== Word8
0x01)

-- | Non-SegWit transaction deseralizer.
parseLegacyTx :: MonadGet m => m Tx
parseLegacyTx :: forall (m :: * -> *). MonadGet m => m Tx
parseLegacyTx = do
    Word32
v <- forall (m :: * -> *). MonadGet m => m Word32
getWord32le
    [TxIn]
is <- forall {m :: * -> *} {a}. (Serial a, MonadGet m) => VarInt -> m [a]
replicateList forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize
    [TxOut]
os <- forall {m :: * -> *} {a}. (Serial a, MonadGet m) => VarInt -> m [a]
replicateList forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxIn]
is forall a. Eq a => a -> a -> Bool
== Int
0x00 Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxOut]
os forall a. Eq a => a -> a -> Bool
== Int
0x01) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Witness transaction"
    Word32
l <- forall (m :: * -> *). MonadGet m => m Word32
getWord32le
    forall (m :: * -> *) a. Monad m => a -> m a
return
        Tx
            { txVersion :: Word32
txVersion = Word32
v
            , txIn :: [TxIn]
txIn = [TxIn]
is
            , txOut :: [TxOut]
txOut = [TxOut]
os
            , txWitness :: WitnessData
txWitness = []
            , txLockTime :: Word32
txLockTime = Word32
l
            }
  where
    replicateList :: VarInt -> m [a]
replicateList (VarInt Word64
c) = forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
c) forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize

-- | Witness transaction deserializer.
parseWitnessTx :: MonadGet m => m Tx
parseWitnessTx :: forall (m :: * -> *). MonadGet m => m Tx
parseWitnessTx = do
    Word32
v <- forall (m :: * -> *). MonadGet m => m Word32
getWord32le
    Word8
m <- forall (m :: * -> *). MonadGet m => m Word8
getWord8
    Word8
f <- forall (m :: * -> *). MonadGet m => m Word8
getWord8
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Word8
m forall a. Eq a => a -> a -> Bool
== Word8
0x00 Bool -> Bool -> Bool
&& Word8
f forall a. Eq a => a -> a -> Bool
== Word8
0x01) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Not a witness transaction"
    [TxIn]
is <- forall {m :: * -> *} {a}. (Serial a, MonadGet m) => VarInt -> m [a]
replicateList forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize
    [TxOut]
os <- forall {m :: * -> *} {a}. (Serial a, MonadGet m) => VarInt -> m [a]
replicateList forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize
    WitnessData
w <- forall (m :: * -> *). MonadGet m => Int -> m WitnessData
parseWitnessData forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxIn]
is
    Word32
l <- forall (m :: * -> *). MonadGet m => m Word32
getWord32le
    forall (m :: * -> *) a. Monad m => a -> m a
return
        Tx{txVersion :: Word32
txVersion = Word32
v, txIn :: [TxIn]
txIn = [TxIn]
is, txOut :: [TxOut]
txOut = [TxOut]
os, txWitness :: WitnessData
txWitness = WitnessData
w, txLockTime :: Word32
txLockTime = Word32
l}
  where
    replicateList :: VarInt -> m [a]
replicateList (VarInt Word64
c) = forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
c) forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize

-- | Witness data deserializer. Requires count of inputs.
parseWitnessData :: MonadGet m => Int -> m WitnessData
parseWitnessData :: forall (m :: * -> *). MonadGet m => Int -> m WitnessData
parseWitnessData Int
n = forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
n m [WitnessStackItem]
parseWitnessStack
  where
    parseWitnessStack :: m [WitnessStackItem]
parseWitnessStack = do
        VarInt Word64
i <- forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize
        forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
i) m WitnessStackItem
parseWitnessStackItem
    parseWitnessStackItem :: m WitnessStackItem
parseWitnessStackItem = do
        VarInt Word64
i <- forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize
        forall (m :: * -> *). MonadGet m => Int -> m WitnessStackItem
getByteString forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
i

-- | Witness data serializer.
putWitnessData :: MonadPut m => WitnessData -> m ()
putWitnessData :: forall (m :: * -> *). MonadPut m => WitnessData -> m ()
putWitnessData = forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ forall {m :: * -> *} {t :: * -> *}.
(MonadPut m, Foldable t) =>
t WitnessStackItem -> m ()
putWitnessStack
  where
    putWitnessStack :: t WitnessStackItem -> m ()
putWitnessStack t WitnessStackItem
ws = do
        forall (m :: * -> *) a. (MonadPut m, Integral a) => a -> m ()
putVarInt forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length t WitnessStackItem
ws
        forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ forall {m :: * -> *}. MonadPut m => WitnessStackItem -> m ()
putWitnessStackItem t WitnessStackItem
ws
    putWitnessStackItem :: WitnessStackItem -> m ()
putWitnessStackItem WitnessStackItem
bs = do
        forall (m :: * -> *) a. (MonadPut m, Integral a) => a -> m ()
putVarInt forall a b. (a -> b) -> a -> b
$ WitnessStackItem -> Int
B.length WitnessStackItem
bs
        forall {m :: * -> *}. MonadPut m => WitnessStackItem -> m ()
putByteString WitnessStackItem
bs

instance FromJSON Tx where
    parseJSON :: Value -> Parser Tx
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Tx" forall a b. (a -> b) -> a -> b
$ \Object
o ->
        Word32 -> [TxIn] -> [TxOut] -> WitnessData -> Word32 -> Tx
Tx forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"version"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"inputs"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"outputs"
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Text -> Parser WitnessStackItem
f) forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"witnessdata")
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"locktime"
      where
        f :: Text -> Parser WitnessStackItem
f = 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
. Text -> Maybe WitnessStackItem
decodeHex

instance ToJSON Tx where
    toJSON :: Tx -> Value
toJSON (Tx Word32
v [TxIn]
i [TxOut]
o WitnessData
w Word32
l) =
        [Pair] -> Value
object
            [ Key
"version" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word32
v
            , Key
"inputs" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [TxIn]
i
            , Key
"outputs" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [TxOut]
o
            , Key
"witnessdata" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WitnessStackItem -> Text
encodeHex) WitnessData
w
            , Key
"locktime" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word32
l
            ]
    toEncoding :: Tx -> Encoding
toEncoding (Tx Word32
v [TxIn]
i [TxOut]
o WitnessData
w Word32
l) =
        Series -> Encoding
pairs
            ( Key
"version" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word32
v
                forall a. Semigroup a => a -> a -> a
<> Key
"inputs" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [TxIn]
i
                forall a. Semigroup a => a -> a -> a
<> Key
"outputs" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= [TxOut]
o
                forall a. Semigroup a => a -> a -> a
<> Key
"witnessdata" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap WitnessStackItem -> Text
encodeHex) WitnessData
w
                forall a. Semigroup a => a -> a -> a
<> Key
"locktime" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word32
l
            )

-- | Data type representing a transaction input.
data TxIn = TxIn
    { -- | output being spent
      TxIn -> OutPoint
prevOutput :: !OutPoint
    , -- | signatures and redeem script
      TxIn -> WitnessStackItem
scriptInput :: !ByteString
    , -- | lock-time using sequence numbers (BIP-68)
      TxIn -> Word32
txInSequence :: !Word32
    }
    deriving (TxIn -> TxIn -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxIn -> TxIn -> Bool
$c/= :: TxIn -> TxIn -> Bool
== :: TxIn -> TxIn -> Bool
$c== :: TxIn -> TxIn -> Bool
Eq, Int -> TxIn -> ShowS
[TxIn] -> ShowS
TxIn -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxIn] -> ShowS
$cshowList :: [TxIn] -> ShowS
show :: TxIn -> String
$cshow :: TxIn -> String
showsPrec :: Int -> TxIn -> ShowS
$cshowsPrec :: Int -> TxIn -> ShowS
Show, ReadPrec [TxIn]
ReadPrec TxIn
Int -> ReadS TxIn
ReadS [TxIn]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TxIn]
$creadListPrec :: ReadPrec [TxIn]
readPrec :: ReadPrec TxIn
$creadPrec :: ReadPrec TxIn
readList :: ReadS [TxIn]
$creadList :: ReadS [TxIn]
readsPrec :: Int -> ReadS TxIn
$creadsPrec :: Int -> ReadS TxIn
Read, Eq TxIn
TxIn -> TxIn -> Bool
TxIn -> TxIn -> Ordering
TxIn -> TxIn -> TxIn
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 :: TxIn -> TxIn -> TxIn
$cmin :: TxIn -> TxIn -> TxIn
max :: TxIn -> TxIn -> TxIn
$cmax :: TxIn -> TxIn -> TxIn
>= :: TxIn -> TxIn -> Bool
$c>= :: TxIn -> TxIn -> Bool
> :: TxIn -> TxIn -> Bool
$c> :: TxIn -> TxIn -> Bool
<= :: TxIn -> TxIn -> Bool
$c<= :: TxIn -> TxIn -> Bool
< :: TxIn -> TxIn -> Bool
$c< :: TxIn -> TxIn -> Bool
compare :: TxIn -> TxIn -> Ordering
$ccompare :: TxIn -> TxIn -> Ordering
Ord, forall x. Rep TxIn x -> TxIn
forall x. TxIn -> Rep TxIn x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxIn x -> TxIn
$cfrom :: forall x. TxIn -> Rep TxIn x
Generic, Eq TxIn
Int -> TxIn -> Int
TxIn -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TxIn -> Int
$chash :: TxIn -> Int
hashWithSalt :: Int -> TxIn -> Int
$chashWithSalt :: Int -> TxIn -> Int
Hashable, TxIn -> ()
forall a. (a -> ()) -> NFData a
rnf :: TxIn -> ()
$crnf :: TxIn -> ()
NFData)

instance Serial TxIn where
    deserialize :: forall (m :: * -> *). MonadGet m => m TxIn
deserialize =
        OutPoint -> WitnessStackItem -> Word32 -> TxIn
TxIn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (forall {m :: * -> *}. MonadGet m => VarInt -> m WitnessStackItem
readBS forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (m :: * -> *). MonadGet m => m Word32
getWord32le
      where
        readBS :: VarInt -> m WitnessStackItem
readBS (VarInt Word64
len) = forall (m :: * -> *). MonadGet m => Int -> m WitnessStackItem
getByteString forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
len

    serialize :: forall (m :: * -> *). MonadPut m => TxIn -> m ()
serialize (TxIn OutPoint
o WitnessStackItem
s Word32
q) = do
        forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize OutPoint
o
        forall (m :: * -> *) a. (MonadPut m, Integral a) => a -> m ()
putVarInt forall a b. (a -> b) -> a -> b
$ WitnessStackItem -> Int
B.length WitnessStackItem
s
        forall {m :: * -> *}. MonadPut m => WitnessStackItem -> m ()
putByteString WitnessStackItem
s
        forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le Word32
q

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

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

instance FromJSON TxIn where
    parseJSON :: Value -> Parser TxIn
parseJSON =
        forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"TxIn" forall a b. (a -> b) -> a -> b
$ \Object
o ->
            OutPoint -> WitnessStackItem -> Word32 -> TxIn
TxIn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"prevoutput"
                forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f 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
. Text -> Maybe WitnessStackItem
decodeHex forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"inputscript")
                forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"sequence"

instance ToJSON TxIn where
    toJSON :: TxIn -> Value
toJSON (TxIn OutPoint
o WitnessStackItem
s Word32
q) =
        [Pair] -> Value
object
            [ Key
"prevoutput" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= OutPoint
o
            , Key
"inputscript" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= WitnessStackItem -> Text
encodeHex WitnessStackItem
s
            , Key
"sequence" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word32
q
            ]
    toEncoding :: TxIn -> Encoding
toEncoding (TxIn OutPoint
o WitnessStackItem
s Word32
q) =
        Series -> Encoding
pairs
            ( Key
"prevoutput" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= OutPoint
o
                forall a. Semigroup a => a -> a -> a
<> Key
"inputscript" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= WitnessStackItem -> Text
encodeHex WitnessStackItem
s
                forall a. Semigroup a => a -> a -> a
<> Key
"sequence" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word32
q
            )

-- | Data type representing a transaction output.
data TxOut = TxOut
    { -- | value of output is satoshi
      TxOut -> Word64
outValue :: !Word64
    , -- | pubkey script
      TxOut -> WitnessStackItem
scriptOutput :: !ByteString
    }
    deriving (TxOut -> TxOut -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TxOut -> TxOut -> Bool
$c/= :: TxOut -> TxOut -> Bool
== :: TxOut -> TxOut -> Bool
$c== :: TxOut -> TxOut -> Bool
Eq, Int -> TxOut -> ShowS
[TxOut] -> ShowS
TxOut -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TxOut] -> ShowS
$cshowList :: [TxOut] -> ShowS
show :: TxOut -> String
$cshow :: TxOut -> String
showsPrec :: Int -> TxOut -> ShowS
$cshowsPrec :: Int -> TxOut -> ShowS
Show, ReadPrec [TxOut]
ReadPrec TxOut
Int -> ReadS TxOut
ReadS [TxOut]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TxOut]
$creadListPrec :: ReadPrec [TxOut]
readPrec :: ReadPrec TxOut
$creadPrec :: ReadPrec TxOut
readList :: ReadS [TxOut]
$creadList :: ReadS [TxOut]
readsPrec :: Int -> ReadS TxOut
$creadsPrec :: Int -> ReadS TxOut
Read, Eq TxOut
TxOut -> TxOut -> Bool
TxOut -> TxOut -> Ordering
TxOut -> TxOut -> TxOut
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 :: TxOut -> TxOut -> TxOut
$cmin :: TxOut -> TxOut -> TxOut
max :: TxOut -> TxOut -> TxOut
$cmax :: TxOut -> TxOut -> TxOut
>= :: TxOut -> TxOut -> Bool
$c>= :: TxOut -> TxOut -> Bool
> :: TxOut -> TxOut -> Bool
$c> :: TxOut -> TxOut -> Bool
<= :: TxOut -> TxOut -> Bool
$c<= :: TxOut -> TxOut -> Bool
< :: TxOut -> TxOut -> Bool
$c< :: TxOut -> TxOut -> Bool
compare :: TxOut -> TxOut -> Ordering
$ccompare :: TxOut -> TxOut -> Ordering
Ord, forall x. Rep TxOut x -> TxOut
forall x. TxOut -> Rep TxOut x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TxOut x -> TxOut
$cfrom :: forall x. TxOut -> Rep TxOut x
Generic, Eq TxOut
Int -> TxOut -> Int
TxOut -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TxOut -> Int
$chash :: TxOut -> Int
hashWithSalt :: Int -> TxOut -> Int
$chashWithSalt :: Int -> TxOut -> Int
Hashable, TxOut -> ()
forall a. (a -> ()) -> NFData a
rnf :: TxOut -> ()
$crnf :: TxOut -> ()
NFData)

instance Serial TxOut where
    deserialize :: forall (m :: * -> *). MonadGet m => m TxOut
deserialize = do
        Word64
val <- forall (m :: * -> *). MonadGet m => m Word64
getWord64le
        VarInt Word64
len <- forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize
        Word64 -> WitnessStackItem -> TxOut
TxOut Word64
val forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). MonadGet m => Int -> m WitnessStackItem
getByteString (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
len)

    serialize :: forall (m :: * -> *). MonadPut m => TxOut -> m ()
serialize (TxOut Word64
o WitnessStackItem
s) = do
        forall (m :: * -> *). MonadPut m => Word64 -> m ()
putWord64le Word64
o
        forall (m :: * -> *) a. (MonadPut m, Integral a) => a -> m ()
putVarInt forall a b. (a -> b) -> a -> b
$ WitnessStackItem -> Int
B.length WitnessStackItem
s
        forall {m :: * -> *}. MonadPut m => WitnessStackItem -> m ()
putByteString WitnessStackItem
s

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

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

instance FromJSON TxOut where
    parseJSON :: Value -> Parser TxOut
parseJSON =
        forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"TxOut" forall a b. (a -> b) -> a -> b
$ \Object
o ->
            Word64 -> WitnessStackItem -> TxOut
TxOut forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"value"
                forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f 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
. Text -> Maybe WitnessStackItem
decodeHex forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"outputscript")

instance ToJSON TxOut where
    toJSON :: TxOut -> Value
toJSON (TxOut Word64
o WitnessStackItem
s) =
        [Pair] -> Value
object [Key
"value" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word64
o, Key
"outputscript" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= WitnessStackItem -> Text
encodeHex WitnessStackItem
s]
    toEncoding :: TxOut -> Encoding
toEncoding (TxOut Word64
o WitnessStackItem
s) =
        Series -> Encoding
pairs (Key
"value" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word64
o forall a. Semigroup a => a -> a -> a
<> Key
"outputscript" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= WitnessStackItem -> Text
encodeHex WitnessStackItem
s)

-- | The 'OutPoint' refers to a transaction output being spent.
data OutPoint = OutPoint
    { -- | hash of previous transaction
      OutPoint -> TxHash
outPointHash :: !TxHash
    , -- | position of output in previous transaction
      OutPoint -> Word32
outPointIndex :: !Word32
    }
    deriving (Int -> OutPoint -> ShowS
[OutPoint] -> ShowS
OutPoint -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OutPoint] -> ShowS
$cshowList :: [OutPoint] -> ShowS
show :: OutPoint -> String
$cshow :: OutPoint -> String
showsPrec :: Int -> OutPoint -> ShowS
$cshowsPrec :: Int -> OutPoint -> ShowS
Show, ReadPrec [OutPoint]
ReadPrec OutPoint
Int -> ReadS OutPoint
ReadS [OutPoint]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [OutPoint]
$creadListPrec :: ReadPrec [OutPoint]
readPrec :: ReadPrec OutPoint
$creadPrec :: ReadPrec OutPoint
readList :: ReadS [OutPoint]
$creadList :: ReadS [OutPoint]
readsPrec :: Int -> ReadS OutPoint
$creadsPrec :: Int -> ReadS OutPoint
Read, OutPoint -> OutPoint -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: OutPoint -> OutPoint -> Bool
$c/= :: OutPoint -> OutPoint -> Bool
== :: OutPoint -> OutPoint -> Bool
$c== :: OutPoint -> OutPoint -> Bool
Eq, Eq OutPoint
OutPoint -> OutPoint -> Bool
OutPoint -> OutPoint -> Ordering
OutPoint -> OutPoint -> OutPoint
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 :: OutPoint -> OutPoint -> OutPoint
$cmin :: OutPoint -> OutPoint -> OutPoint
max :: OutPoint -> OutPoint -> OutPoint
$cmax :: OutPoint -> OutPoint -> OutPoint
>= :: OutPoint -> OutPoint -> Bool
$c>= :: OutPoint -> OutPoint -> Bool
> :: OutPoint -> OutPoint -> Bool
$c> :: OutPoint -> OutPoint -> Bool
<= :: OutPoint -> OutPoint -> Bool
$c<= :: OutPoint -> OutPoint -> Bool
< :: OutPoint -> OutPoint -> Bool
$c< :: OutPoint -> OutPoint -> Bool
compare :: OutPoint -> OutPoint -> Ordering
$ccompare :: OutPoint -> OutPoint -> Ordering
Ord, forall x. Rep OutPoint x -> OutPoint
forall x. OutPoint -> Rep OutPoint x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep OutPoint x -> OutPoint
$cfrom :: forall x. OutPoint -> Rep OutPoint x
Generic, Eq OutPoint
Int -> OutPoint -> Int
OutPoint -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: OutPoint -> Int
$chash :: OutPoint -> Int
hashWithSalt :: Int -> OutPoint -> Int
$chashWithSalt :: Int -> OutPoint -> Int
Hashable, OutPoint -> ()
forall a. (a -> ()) -> NFData a
rnf :: OutPoint -> ()
$crnf :: OutPoint -> ()
NFData)

instance Serial OutPoint where
    deserialize :: forall (m :: * -> *). MonadGet m => m OutPoint
deserialize = do
        (TxHash
h, Word32
i) <- forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (,) forall a (m :: * -> *). (Serial a, MonadGet m) => m a
deserialize forall (m :: * -> *). MonadGet m => m Word32
getWord32le
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ TxHash -> Word32 -> OutPoint
OutPoint TxHash
h Word32
i
    serialize :: forall (m :: * -> *). MonadPut m => OutPoint -> m ()
serialize (OutPoint TxHash
h Word32
i) = forall a (m :: * -> *). (Serial a, MonadPut m) => a -> m ()
serialize TxHash
h forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *). MonadPut m => Word32 -> m ()
putWord32le Word32
i

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

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

instance FromJSON OutPoint where
    parseJSON :: Value -> Parser OutPoint
parseJSON =
        forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"OutPoint" forall a b. (a -> b) -> a -> b
$ \Object
o ->
            TxHash -> Word32 -> OutPoint
OutPoint forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"txid" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"index"

instance ToJSON OutPoint where
    toJSON :: OutPoint -> Value
toJSON (OutPoint TxHash
h Word32
i) = [Pair] -> Value
object [Key
"txid" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= TxHash
h, Key
"index" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word32
i]
    toEncoding :: OutPoint -> Encoding
toEncoding (OutPoint TxHash
h Word32
i) = Series -> Encoding
pairs (Key
"txid" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= TxHash
h forall a. Semigroup a => a -> a -> a
<> Key
"index" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= Word32
i)

-- | Outpoint used in coinbase transactions.
nullOutPoint :: OutPoint
nullOutPoint :: OutPoint
nullOutPoint =
    OutPoint
        { outPointHash :: TxHash
outPointHash =
            TxHash
"0000000000000000000000000000000000000000000000000000000000000000"
        , outPointIndex :: Word32
outPointIndex = forall a. Bounded a => a
maxBound
        }