{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedRecordDot #-}

-- |
-- Module      : Haskoin.Test.Transaction
-- Copyright   : No rights reserved
-- License     : MIT
-- Maintainer  : jprupp@protonmail.ch
-- Stability   : experimental
-- Portability : POSIX
module Haskoin.Util.Arbitrary.Transaction where

import Control.Monad
import Data.ByteString qualified as BS
import Data.Either (fromRight)
import Data.List (nub, nubBy, permutations)
import Data.Word (Word64)
import Haskoin.Address
import Haskoin.Crypto (Ctx)
import Haskoin.Crypto.Keys.Common
import Haskoin.Network.Constants
import Haskoin.Network.Data
import Haskoin.Script
import Haskoin.Transaction
import Haskoin.Util
import Haskoin.Util.Arbitrary.Crypto
import Haskoin.Util.Arbitrary.Keys
import Haskoin.Util.Arbitrary.Script
import Haskoin.Util.Arbitrary.Util
import Test.QuickCheck

-- | Wrapped coin value for testing.
newtype TestCoin = TestCoin {TestCoin -> Word64
getTestCoin :: Word64}
  deriving (TestCoin -> TestCoin -> Bool
(TestCoin -> TestCoin -> Bool)
-> (TestCoin -> TestCoin -> Bool) -> Eq TestCoin
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TestCoin -> TestCoin -> Bool
== :: TestCoin -> TestCoin -> Bool
$c/= :: TestCoin -> TestCoin -> Bool
/= :: TestCoin -> TestCoin -> Bool
Eq, Int -> TestCoin -> ShowS
[TestCoin] -> ShowS
TestCoin -> String
(Int -> TestCoin -> ShowS)
-> (TestCoin -> String) -> ([TestCoin] -> ShowS) -> Show TestCoin
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TestCoin -> ShowS
showsPrec :: Int -> TestCoin -> ShowS
$cshow :: TestCoin -> String
show :: TestCoin -> String
$cshowList :: [TestCoin] -> ShowS
showList :: [TestCoin] -> ShowS
Show)

instance Coin TestCoin where
  coinValue :: TestCoin -> Word64
coinValue = TestCoin -> Word64
getTestCoin

-- | Arbitrary transaction hash (for non-existent transaction).
arbitraryTxHash :: Gen TxHash
arbitraryTxHash :: Gen TxHash
arbitraryTxHash = Hash256 -> TxHash
TxHash (Hash256 -> TxHash) -> Gen Hash256 -> Gen TxHash
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Hash256
arbitraryHash256

-- | Arbitrary amount of Satoshi as 'Word64' (Between 1 and 21e14)
arbitrarySatoshi :: Network -> Gen TestCoin
arbitrarySatoshi :: Network -> Gen TestCoin
arbitrarySatoshi Network
net = Word64 -> TestCoin
TestCoin (Word64 -> TestCoin) -> Gen Word64 -> Gen TestCoin
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word64, Word64) -> Gen Word64
forall a. Random a => (a, a) -> Gen a
choose (Word64
1, Network
net.maxSatoshi)

-- | Arbitrary 'OutPoint'.
arbitraryOutPoint :: Gen OutPoint
arbitraryOutPoint :: Gen OutPoint
arbitraryOutPoint = TxHash -> Word32 -> OutPoint
OutPoint (TxHash -> Word32 -> OutPoint)
-> Gen TxHash -> Gen (Word32 -> OutPoint)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen TxHash
arbitraryTxHash Gen (Word32 -> OutPoint) -> Gen Word32 -> Gen OutPoint
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary 'TxOut'.
arbitraryTxOut :: Network -> Ctx -> Gen TxOut
arbitraryTxOut :: Network -> Ctx -> Gen TxOut
arbitraryTxOut Network
net Ctx
ctx =
  Word64 -> ByteString -> TxOut
TxOut
    (Word64 -> ByteString -> TxOut)
-> Gen Word64 -> Gen (ByteString -> TxOut)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TestCoin -> Word64
getTestCoin (TestCoin -> Word64) -> Gen TestCoin -> Gen Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen TestCoin
arbitrarySatoshi Network
net)
    Gen (ByteString -> TxOut) -> Gen ByteString -> Gen TxOut
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Ctx -> ScriptOutput -> ByteString
forall s a. Marshal s a => s -> a -> ByteString
marshal Ctx
ctx (ScriptOutput -> ByteString) -> Gen ScriptOutput -> Gen ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen ScriptOutput
arbitraryScriptOutput Network
net Ctx
ctx)

-- | Arbitrary 'TxIn'.
arbitraryTxIn :: Network -> Ctx -> Gen TxIn
arbitraryTxIn :: Network -> Ctx -> Gen TxIn
arbitraryTxIn Network
net Ctx
ctx =
  OutPoint -> ByteString -> Word32 -> TxIn
TxIn
    (OutPoint -> ByteString -> Word32 -> TxIn)
-> Gen OutPoint -> Gen (ByteString -> Word32 -> TxIn)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen OutPoint
arbitraryOutPoint
    Gen (ByteString -> Word32 -> TxIn)
-> Gen ByteString -> Gen (Word32 -> TxIn)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ((Network, Ctx) -> ScriptInput -> ByteString
forall s a. Marshal s a => s -> a -> ByteString
marshal (Network
net, Ctx
ctx) (ScriptInput -> ByteString) -> Gen ScriptInput -> Gen ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen ScriptInput
arbitraryScriptInput Network
net Ctx
ctx)
    Gen (Word32 -> TxIn) -> Gen Word32 -> Gen TxIn
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary transaction. Can be regular or with witnesses.
arbitraryTx :: Network -> Ctx -> Gen Tx
arbitraryTx :: Network -> Ctx -> Gen Tx
arbitraryTx Network
net Ctx
ctx =
  [Gen Tx] -> Gen Tx
forall a. [Gen a] -> Gen a
oneof [Network -> Ctx -> Gen Tx
arbitraryLegacyTx Network
net Ctx
ctx, Network -> Ctx -> Gen Tx
arbitraryWitnessTx Network
net Ctx
ctx]

-- | Arbitrary regular transaction.
arbitraryLegacyTx :: Network -> Ctx -> Gen Tx
arbitraryLegacyTx :: Network -> Ctx -> Gen Tx
arbitraryLegacyTx Network
net Ctx
ctx = Network -> Ctx -> Bool -> Gen Tx
arbitraryWLTx Network
net Ctx
ctx Bool
False

-- | Arbitrary witness transaction (witness data is fake).
arbitraryWitnessTx :: Network -> Ctx -> Gen Tx
arbitraryWitnessTx :: Network -> Ctx -> Gen Tx
arbitraryWitnessTx Network
net Ctx
ctx = Network -> Ctx -> Bool -> Gen Tx
arbitraryWLTx Network
net Ctx
ctx Bool
True

-- | Arbitrary witness or legacy transaction.
arbitraryWLTx :: Network -> Ctx -> Bool -> Gen Tx
arbitraryWLTx :: Network -> Ctx -> Bool -> Gen Tx
arbitraryWLTx Network
net Ctx
ctx Bool
wit = do
  Int
ni <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  Int
no <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  [TxIn]
inps <- Int -> Gen TxIn -> Gen [TxIn]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni (Network -> Ctx -> Gen TxIn
arbitraryTxIn Network
net Ctx
ctx)
  [TxOut]
outs <- Int -> Gen TxOut -> Gen [TxOut]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Ctx -> Gen TxOut
arbitraryTxOut Network
net Ctx
ctx)
  let uniqueInps :: [TxIn]
uniqueInps = (TxIn -> TxIn -> Bool) -> [TxIn] -> [TxIn]
forall a. (a -> a -> Bool) -> [a] -> [a]
nubBy (\TxIn
a TxIn
b -> TxIn
a.outpoint OutPoint -> OutPoint -> Bool
forall a. Eq a => a -> a -> Bool
== TxIn
b.outpoint) [TxIn]
inps
  [[ByteString]]
w <-
    if Bool
wit
      then Int -> Gen [ByteString] -> Gen [[ByteString]]
forall a. Int -> Gen a -> Gen [a]
vectorOf ([TxIn] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxIn]
uniqueInps) (Gen ByteString -> Gen [ByteString]
forall a. Gen a -> Gen [a]
listOf Gen ByteString
arbitraryBS)
      else [[ByteString]] -> Gen [[ByteString]]
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return []
  Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx (Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen Word32
-> Gen ([TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary Gen ([TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen [TxIn] -> Gen ([TxOut] -> [[ByteString]] -> Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [TxIn] -> Gen [TxIn]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxIn]
uniqueInps Gen ([TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen [TxOut] -> Gen ([[ByteString]] -> Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [TxOut] -> Gen [TxOut]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxOut]
outs Gen ([[ByteString]] -> Word32 -> Tx)
-> Gen [[ByteString]] -> Gen (Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [[ByteString]] -> Gen [[ByteString]]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [[ByteString]]
w Gen (Word32 -> Tx) -> Gen Word32 -> Gen Tx
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary transaction containing only inputs of type 'SpendPKHash',
-- 'SpendScriptHash' (multisig) and outputs of type 'PayPKHash' and 'PaySH'.
-- Only compressed public keys are used.
arbitraryAddrOnlyTx :: Network -> Ctx -> Gen Tx
arbitraryAddrOnlyTx :: Network -> Ctx -> Gen Tx
arbitraryAddrOnlyTx Network
net Ctx
ctx = do
  Int
ni <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  Int
no <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  [TxIn]
inps <- Int -> Gen TxIn -> Gen [TxIn]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni (Network -> Ctx -> Gen TxIn
arbitraryAddrOnlyTxIn Network
net Ctx
ctx)
  [TxOut]
outs <- Int -> Gen TxOut -> Gen [TxOut]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Ctx -> Gen TxOut
arbitraryAddrOnlyTxOut Network
net Ctx
ctx)
  Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx (Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen Word32
-> Gen ([TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary Gen ([TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen [TxIn] -> Gen ([TxOut] -> [[ByteString]] -> Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [TxIn] -> Gen [TxIn]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxIn]
inps Gen ([TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen [TxOut] -> Gen ([[ByteString]] -> Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [TxOut] -> Gen [TxOut]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxOut]
outs Gen ([[ByteString]] -> Word32 -> Tx)
-> Gen [[ByteString]] -> Gen (Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [[ByteString]] -> Gen [[ByteString]]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [] Gen (Word32 -> Tx) -> Gen Word32 -> Gen Tx
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary

-- | Like 'arbitraryAddrOnlyTx' without empty signatures in the inputs.
arbitraryAddrOnlyTxFull :: Network -> Ctx -> Gen Tx
arbitraryAddrOnlyTxFull :: Network -> Ctx -> Gen Tx
arbitraryAddrOnlyTxFull Network
net Ctx
ctx = do
  Int
ni <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  Int
no <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  [TxIn]
inps <- Int -> Gen TxIn -> Gen [TxIn]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni (Network -> Ctx -> Gen TxIn
arbitraryAddrOnlyTxInFull Network
net Ctx
ctx)
  [TxOut]
outs <- Int -> Gen TxOut -> Gen [TxOut]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Ctx -> Gen TxOut
arbitraryAddrOnlyTxOut Network
net Ctx
ctx)
  Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx (Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen Word32
-> Gen ([TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary Gen ([TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen [TxIn] -> Gen ([TxOut] -> [[ByteString]] -> Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [TxIn] -> Gen [TxIn]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxIn]
inps Gen ([TxOut] -> [[ByteString]] -> Word32 -> Tx)
-> Gen [TxOut] -> Gen ([[ByteString]] -> Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [TxOut] -> Gen [TxOut]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxOut]
outs Gen ([[ByteString]] -> Word32 -> Tx)
-> Gen [[ByteString]] -> Gen (Word32 -> Tx)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [[ByteString]] -> Gen [[ByteString]]
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [] Gen (Word32 -> Tx) -> Gen Word32 -> Gen Tx
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary TxIn that can only be of type 'SpendPKHash' or 'SpendScriptHash'
-- (multisig). Only compressed public keys are used.
arbitraryAddrOnlyTxIn :: Network -> Ctx -> Gen TxIn
arbitraryAddrOnlyTxIn :: Network -> Ctx -> Gen TxIn
arbitraryAddrOnlyTxIn Network
net Ctx
ctx = do
  ScriptInput
inp <- [Gen ScriptInput] -> Gen ScriptInput
forall a. [Gen a] -> Gen a
oneof [Network -> Ctx -> Gen ScriptInput
arbitraryPKHashInput Network
net Ctx
ctx, Network -> Ctx -> Gen ScriptInput
arbitraryMulSigSHInput Network
net Ctx
ctx]
  OutPoint -> ByteString -> Word32 -> TxIn
TxIn (OutPoint -> ByteString -> Word32 -> TxIn)
-> Gen OutPoint -> Gen (ByteString -> Word32 -> TxIn)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen OutPoint
arbitraryOutPoint Gen (ByteString -> Word32 -> TxIn)
-> Gen ByteString -> Gen (Word32 -> TxIn)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ByteString -> Gen ByteString
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Network, Ctx) -> ScriptInput -> ByteString
forall s a. Marshal s a => s -> a -> ByteString
marshal (Network
net, Ctx
ctx) ScriptInput
inp) Gen (Word32 -> TxIn) -> Gen Word32 -> Gen TxIn
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary

-- | like 'arbitraryAddrOnlyTxIn' with no empty signatures.
arbitraryAddrOnlyTxInFull :: Network -> Ctx -> Gen TxIn
arbitraryAddrOnlyTxInFull :: Network -> Ctx -> Gen TxIn
arbitraryAddrOnlyTxInFull Network
net Ctx
ctx = do
  ScriptInput
inp <-
    [Gen ScriptInput] -> Gen ScriptInput
forall a. [Gen a] -> Gen a
oneof [Network -> Ctx -> Gen ScriptInput
arbitraryPKHashInputFullC Network
net Ctx
ctx, Network -> Ctx -> Gen ScriptInput
arbitraryMulSigSHInputFullC Network
net Ctx
ctx]
  OutPoint -> ByteString -> Word32 -> TxIn
TxIn (OutPoint -> ByteString -> Word32 -> TxIn)
-> Gen OutPoint -> Gen (ByteString -> Word32 -> TxIn)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen OutPoint
arbitraryOutPoint Gen (ByteString -> Word32 -> TxIn)
-> Gen ByteString -> Gen (Word32 -> TxIn)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ByteString -> Gen ByteString
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Network, Ctx) -> ScriptInput -> ByteString
forall s a. Marshal s a => s -> a -> ByteString
marshal (Network
net, Ctx
ctx) ScriptInput
inp) Gen (Word32 -> TxIn) -> Gen Word32 -> Gen TxIn
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary

-- | Arbitrary 'TxOut' that can only be of type 'PayPKHash' or 'PaySH'.
arbitraryAddrOnlyTxOut :: Network -> Ctx -> Gen TxOut
arbitraryAddrOnlyTxOut :: Network -> Ctx -> Gen TxOut
arbitraryAddrOnlyTxOut Network
net Ctx
ctx = do
  Word64
v <- TestCoin -> Word64
getTestCoin (TestCoin -> Word64) -> Gen TestCoin -> Gen Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen TestCoin
arbitrarySatoshi Network
net
  ScriptOutput
out <- [Gen ScriptOutput] -> Gen ScriptOutput
forall a. [Gen a] -> Gen a
oneof [Gen ScriptOutput
arbitraryPKHashOutput, Gen ScriptOutput
arbitrarySHOutput]
  TxOut -> Gen TxOut
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxOut -> Gen TxOut) -> TxOut -> Gen TxOut
forall a b. (a -> b) -> a -> b
$ Word64 -> ByteString -> TxOut
TxOut Word64
v (ByteString -> TxOut) -> ByteString -> TxOut
forall a b. (a -> b) -> a -> b
$ Ctx -> ScriptOutput -> ByteString
forall s a. Marshal s a => s -> a -> ByteString
marshal Ctx
ctx ScriptOutput
out

-- | Arbitrary 'SigInput' with the corresponding private keys used
-- to generate the 'ScriptOutput' or 'RedeemScript'.
arbitrarySigInput :: Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitrarySigInput :: Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitrarySigInput Network
net Ctx
ctx =
  [Gen (SigInput, [PrivateKey])] -> Gen (SigInput, [PrivateKey])
forall a. [Gen a] -> Gen a
oneof
    [ (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey ((SigInput, PrivateKey) -> (SigInput, [PrivateKey]))
-> Gen (SigInput, PrivateKey) -> Gen (SigInput, [PrivateKey])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKSigInput Network
net Ctx
ctx,
      (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey ((SigInput, PrivateKey) -> (SigInput, [PrivateKey]))
-> Gen (SigInput, PrivateKey) -> Gen (SigInput, [PrivateKey])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKHashSigInput Network
net Ctx
ctx,
      Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitraryMSSigInput Network
net Ctx
ctx,
      Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitrarySHSigInput Network
net Ctx
ctx,
      (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey ((SigInput, PrivateKey) -> (SigInput, [PrivateKey]))
-> Gen (SigInput, PrivateKey) -> Gen (SigInput, [PrivateKey])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryWPKHSigInput Network
net Ctx
ctx,
      Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitraryWSHSigInput Network
net Ctx
ctx
    ]

-- | Arbitrary 'SigInput' with a 'ScriptOutput' of type 'PayPK'.
arbitraryPKSigInput :: Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKSigInput :: Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKSigInput Network
net Ctx
ctx = Network -> Ctx -> Bool -> Gen (SigInput, PrivateKey)
arbitraryAnyInput Network
net Ctx
ctx Bool
False

-- | Arbitrary 'SigInput' with a 'ScriptOutput' of type 'PayPKHash'.
arbitraryPKHashSigInput :: Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKHashSigInput :: Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKHashSigInput Network
net Ctx
ctx = Network -> Ctx -> Bool -> Gen (SigInput, PrivateKey)
arbitraryAnyInput Network
net Ctx
ctx Bool
True

-- | Arbitrary 'SigInput'.
arbitraryAnyInput :: Network -> Ctx -> Bool -> Gen (SigInput, PrivateKey)
arbitraryAnyInput :: Network -> Ctx -> Bool -> Gen (SigInput, PrivateKey)
arbitraryAnyInput Network
net Ctx
ctx Bool
pkh = do
  (PrivateKey
k, PublicKey
p) <- Ctx -> Gen (PrivateKey, PublicKey)
arbitraryKeyPair Ctx
ctx
  let out :: ScriptOutput
out
        | Bool
pkh = Hash160 -> ScriptOutput
PayPKHash (Ctx -> PublicKey -> Address
pubKeyAddr Ctx
ctx PublicKey
p).hash160
        | Bool
otherwise = PublicKey -> ScriptOutput
PayPK PublicKey
p
  (Word64
val, OutPoint
op, SigHash
sh) <- Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff Network
net
  (SigInput, PrivateKey) -> Gen (SigInput, PrivateKey)
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOutput
-> Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput
SigInput ScriptOutput
out Word64
val OutPoint
op SigHash
sh Maybe ScriptOutput
forall a. Maybe a
Nothing, PrivateKey
k)

-- | Arbitrary value, out point and sighash for an input.
arbitraryInputStuff :: Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff :: Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff Network
net = do
  Word64
val <- TestCoin -> Word64
getTestCoin (TestCoin -> Word64) -> Gen TestCoin -> Gen Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen TestCoin
arbitrarySatoshi Network
net
  OutPoint
op <- Gen OutPoint
arbitraryOutPoint
  SigHash
sh <- Network -> Gen SigHash
arbitraryValidSigHash Network
net
  (Word64, OutPoint, SigHash) -> Gen (Word64, OutPoint, SigHash)
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (Word64
val, OutPoint
op, SigHash
sh)

-- | Arbitrary 'SigInput' with a 'ScriptOutput' of type 'PayMulSig'.
arbitraryMSSigInput :: Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitraryMSSigInput :: Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitraryMSSigInput Network
net Ctx
ctx = do
  (Int
m, Int
n) <- Gen (Int, Int)
arbitraryMSParam
  [(PrivateKey, PublicKey)]
ks <- Int -> Gen (PrivateKey, PublicKey) -> Gen [(PrivateKey, PublicKey)]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
n (Ctx -> Gen (PrivateKey, PublicKey)
arbitraryKeyPair Ctx
ctx)
  let out :: ScriptOutput
out = [PublicKey] -> Int -> ScriptOutput
PayMulSig (((PrivateKey, PublicKey) -> PublicKey)
-> [(PrivateKey, PublicKey)] -> [PublicKey]
forall a b. (a -> b) -> [a] -> [b]
map (PrivateKey, PublicKey) -> PublicKey
forall a b. (a, b) -> b
snd [(PrivateKey, PublicKey)]
ks) Int
m
  (Word64
val, OutPoint
op, SigHash
sh) <- Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff Network
net
  Int
perm <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
0, Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
  let ksPerm :: [PrivateKey]
ksPerm = ((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
m ([(PrivateKey, PublicKey)] -> [(PrivateKey, PublicKey)])
-> [(PrivateKey, PublicKey)] -> [(PrivateKey, PublicKey)]
forall a b. (a -> b) -> a -> b
$ [(PrivateKey, PublicKey)] -> [[(PrivateKey, PublicKey)]]
forall a. [a] -> [[a]]
permutations [(PrivateKey, PublicKey)]
ks [[(PrivateKey, PublicKey)]] -> Int -> [(PrivateKey, PublicKey)]
forall a. HasCallStack => [a] -> Int -> a
!! Int
perm
  (SigInput, [PrivateKey]) -> Gen (SigInput, [PrivateKey])
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOutput
-> Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput
SigInput ScriptOutput
out Word64
val OutPoint
op SigHash
sh Maybe ScriptOutput
forall a. Maybe a
Nothing, [PrivateKey]
ksPerm)

-- | Arbitrary 'SigInput' with 'ScriptOutput' of type 'PaySH' and a
-- 'RedeemScript'.
arbitrarySHSigInput :: Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitrarySHSigInput :: Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitrarySHSigInput Network
net Ctx
ctx = do
  (SigInput ScriptOutput
rdm Word64
val OutPoint
op SigHash
sh Maybe ScriptOutput
_, [PrivateKey]
ks) <-
    [Gen (SigInput, [PrivateKey])] -> Gen (SigInput, [PrivateKey])
forall a. [Gen a] -> Gen a
oneof
      [ (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey ((SigInput, PrivateKey) -> (SigInput, [PrivateKey]))
-> Gen (SigInput, PrivateKey) -> Gen (SigInput, [PrivateKey])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKSigInput Network
net Ctx
ctx,
        (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey ((SigInput, PrivateKey) -> (SigInput, [PrivateKey]))
-> Gen (SigInput, PrivateKey) -> Gen (SigInput, [PrivateKey])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKHashSigInput Network
net Ctx
ctx,
        Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitraryMSSigInput Network
net Ctx
ctx
      ]
  let out :: ScriptOutput
out = Hash160 -> ScriptOutput
PayScriptHash (Ctx -> ScriptOutput -> Address
payToScriptAddress Ctx
ctx ScriptOutput
rdm).hash160
  (SigInput, [PrivateKey]) -> Gen (SigInput, [PrivateKey])
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOutput
-> Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput
SigInput ScriptOutput
out Word64
val OutPoint
op SigHash
sh (Maybe ScriptOutput -> SigInput) -> Maybe ScriptOutput -> SigInput
forall a b. (a -> b) -> a -> b
$ ScriptOutput -> Maybe ScriptOutput
forall a. a -> Maybe a
Just ScriptOutput
rdm, [PrivateKey]
ks)

arbitraryWPKHSigInput :: Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryWPKHSigInput :: Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryWPKHSigInput Network
net Ctx
ctx = do
  (PrivateKey
k, PublicKey
p) <- Ctx -> Gen (PrivateKey, PublicKey)
arbitraryKeyPair Ctx
ctx
  (Word64
val, OutPoint
op, SigHash
sh) <- Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff Network
net
  let out :: ScriptOutput
out = Hash160 -> ScriptOutput
PayWitnessPKHash (Ctx -> PublicKey -> Address
pubKeyAddr Ctx
ctx PublicKey
p).hash160
  (SigInput, PrivateKey) -> Gen (SigInput, PrivateKey)
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOutput
-> Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput
SigInput ScriptOutput
out Word64
val OutPoint
op SigHash
sh Maybe ScriptOutput
forall a. Maybe a
Nothing, PrivateKey
k)

arbitraryWSHSigInput :: Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitraryWSHSigInput :: Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitraryWSHSigInput Network
net Ctx
ctx = do
  (SigInput ScriptOutput
rdm Word64
val OutPoint
op SigHash
sh Maybe ScriptOutput
_, [PrivateKey]
ks) <-
    [Gen (SigInput, [PrivateKey])] -> Gen (SigInput, [PrivateKey])
forall a. [Gen a] -> Gen a
oneof
      [ (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey ((SigInput, PrivateKey) -> (SigInput, [PrivateKey]))
-> Gen (SigInput, PrivateKey) -> Gen (SigInput, [PrivateKey])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKSigInput Network
net Ctx
ctx,
        (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey ((SigInput, PrivateKey) -> (SigInput, [PrivateKey]))
-> Gen (SigInput, PrivateKey) -> Gen (SigInput, [PrivateKey])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Ctx -> Gen (SigInput, PrivateKey)
arbitraryPKHashSigInput Network
net Ctx
ctx,
        Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitraryMSSigInput Network
net Ctx
ctx
      ]
  let out :: ScriptOutput
out = Hash256 -> ScriptOutput
PayWitnessScriptHash (Ctx -> ScriptOutput -> Address
payToWitnessScriptAddress Ctx
ctx ScriptOutput
rdm).hash256
  (SigInput, [PrivateKey]) -> Gen (SigInput, [PrivateKey])
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (ScriptOutput
-> Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput
SigInput ScriptOutput
out Word64
val OutPoint
op SigHash
sh (Maybe ScriptOutput -> SigInput) -> Maybe ScriptOutput -> SigInput
forall a b. (a -> b) -> a -> b
$ ScriptOutput -> Maybe ScriptOutput
forall a. a -> Maybe a
Just ScriptOutput
rdm, [PrivateKey]
ks)

-- | Arbitrary 'Tx' (empty 'TxIn'), 'SigInputs' and private keys that can be
-- passed to 'signTx' or 'detSignTx' to fully sign the 'Tx'.
arbitrarySigningData :: Network -> Ctx -> Gen (Tx, [SigInput], [PrivateKey])
arbitrarySigningData :: Network -> Ctx -> Gen (Tx, [SigInput], [PrivateKey])
arbitrarySigningData Network
net Ctx
ctx = do
  Word32
v <- Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
  Int
ni <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  Int
no <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  [(SigInput, [PrivateKey])]
sigis <- Int
-> Gen (SigInput, [PrivateKey]) -> Gen [(SigInput, [PrivateKey])]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni (Network -> Ctx -> Gen (SigInput, [PrivateKey])
arbitrarySigInput Network
net Ctx
ctx)
  let uSigis :: [(SigInput, [PrivateKey])]
uSigis = ((SigInput, [PrivateKey]) -> (SigInput, [PrivateKey]) -> Bool)
-> [(SigInput, [PrivateKey])] -> [(SigInput, [PrivateKey])]
forall a. (a -> a -> Bool) -> [a] -> [a]
nubBy (\(SigInput
a, [PrivateKey]
_) (SigInput
b, [PrivateKey]
_) -> SigInput
a.outpoint OutPoint -> OutPoint -> Bool
forall a. Eq a => a -> a -> Bool
== SigInput
b.outpoint) [(SigInput, [PrivateKey])]
sigis
  [TxIn]
inps <- [(SigInput, [PrivateKey])]
-> ((SigInput, [PrivateKey]) -> Gen TxIn) -> Gen [TxIn]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [(SigInput, [PrivateKey])]
uSigis (((SigInput, [PrivateKey]) -> Gen TxIn) -> Gen [TxIn])
-> ((SigInput, [PrivateKey]) -> Gen TxIn) -> Gen [TxIn]
forall a b. (a -> b) -> a -> b
$ \(SigInput
s, [PrivateKey]
_) -> OutPoint -> ByteString -> Word32 -> TxIn
TxIn SigInput
s.outpoint ByteString
BS.empty (Word32 -> TxIn) -> Gen Word32 -> Gen TxIn
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
  [TxOut]
outs <- Int -> Gen TxOut -> Gen [TxOut]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Ctx -> Gen TxOut
arbitraryTxOut Network
net Ctx
ctx)
  Word32
l <- Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
  Int
perm <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
0, [TxIn] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxIn]
inps Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
  let tx :: Tx
tx = Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx Word32
v ([TxIn] -> [[TxIn]]
forall a. [a] -> [[a]]
permutations [TxIn]
inps [[TxIn]] -> Int -> [TxIn]
forall a. HasCallStack => [a] -> Int -> a
!! Int
perm) [TxOut]
outs [] Word32
l
      keys :: [PrivateKey]
keys = ((SigInput, [PrivateKey]) -> [PrivateKey])
-> [(SigInput, [PrivateKey])] -> [PrivateKey]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (SigInput, [PrivateKey]) -> [PrivateKey]
forall a b. (a, b) -> b
snd [(SigInput, [PrivateKey])]
uSigis
  (Tx, [SigInput], [PrivateKey])
-> Gen (Tx, [SigInput], [PrivateKey])
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (Tx
tx, ((SigInput, [PrivateKey]) -> SigInput)
-> [(SigInput, [PrivateKey])] -> [SigInput]
forall a b. (a -> b) -> [a] -> [b]
map (SigInput, [PrivateKey]) -> SigInput
forall a b. (a, b) -> a
fst [(SigInput, [PrivateKey])]
uSigis, [PrivateKey]
keys)

-- | Arbitrary transaction with empty inputs.
arbitraryEmptyTx :: Network -> Ctx -> Gen Tx
arbitraryEmptyTx :: Network -> Ctx -> Gen Tx
arbitraryEmptyTx Network
net Ctx
ctx = do
  Word32
v <- Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
  Int
no <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  Int
ni <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
  [TxOut]
outs <- Int -> Gen TxOut -> Gen [TxOut]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Ctx -> Gen TxOut
arbitraryTxOut Network
net Ctx
ctx)
  [OutPoint]
ops <- Int -> Gen OutPoint -> Gen [OutPoint]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni Gen OutPoint
arbitraryOutPoint
  Word32
t <- Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
  Word32
s <- Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
  Tx -> Gen Tx
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (Tx -> Gen Tx) -> Tx -> Gen Tx
forall a b. (a -> b) -> a -> b
$ Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx Word32
v ((OutPoint -> TxIn) -> [OutPoint] -> [TxIn]
forall a b. (a -> b) -> [a] -> [b]
map (\OutPoint
op -> OutPoint -> ByteString -> Word32 -> TxIn
TxIn OutPoint
op ByteString
BS.empty Word32
s) ([OutPoint] -> [OutPoint]
forall a. Eq a => [a] -> [a]
nub [OutPoint]
ops)) [TxOut]
outs [] Word32
t

-- | Arbitrary partially-signed transactions.
arbitraryPartialTxs ::
  Network -> Ctx -> Gen ([Tx], [(ScriptOutput, Word64, OutPoint, Int, Int)])
arbitraryPartialTxs :: Network
-> Ctx -> Gen ([Tx], [(ScriptOutput, Word64, OutPoint, Int, Int)])
arbitraryPartialTxs Network
net Ctx
ctx = do
  Tx
tx <- Network -> Ctx -> Gen Tx
arbitraryEmptyTx Network
net Ctx
ctx
  [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))]
res <-
    [OutPoint]
-> (OutPoint
    -> Gen ([Tx], (ScriptOutput, Word64, OutPoint, Int, Int)))
-> Gen [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM ((TxIn -> OutPoint) -> [TxIn] -> [OutPoint]
forall a b. (a -> b) -> [a] -> [b]
map (.outpoint) Tx
tx.inputs) ((OutPoint
  -> Gen ([Tx], (ScriptOutput, Word64, OutPoint, Int, Int)))
 -> Gen [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))])
-> (OutPoint
    -> Gen ([Tx], (ScriptOutput, Word64, OutPoint, Int, Int)))
-> Gen [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))]
forall a b. (a -> b) -> a -> b
$ \OutPoint
op -> do
      (ScriptOutput
so, Word64
val, Maybe ScriptOutput
rdmM, [PrivateKey]
prvs, Int
m, Int
n) <- Gen
  (ScriptOutput, Word64, Maybe ScriptOutput, [PrivateKey], Int, Int)
arbitraryData
      [Tx]
txs <- (PrivateKey -> Gen Tx) -> [PrivateKey] -> Gen [Tx]
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) -> [a] -> m [b]
mapM (ScriptOutput
-> Word64
-> Maybe ScriptOutput
-> Tx
-> OutPoint
-> SecKey
-> Gen Tx
singleSig ScriptOutput
so Word64
val Maybe ScriptOutput
rdmM Tx
tx OutPoint
op (SecKey -> Gen Tx)
-> (PrivateKey -> SecKey) -> PrivateKey -> Gen Tx
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.key)) [PrivateKey]
prvs
      ([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))
-> Gen ([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Tx]
txs, (ScriptOutput
so, Word64
val, OutPoint
op, Int
m, Int
n))
  ([Tx], [(ScriptOutput, Word64, OutPoint, Int, Int)])
-> Gen ([Tx], [(ScriptOutput, Word64, OutPoint, Int, Int)])
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return ((([Tx], (ScriptOutput, Word64, OutPoint, Int, Int)) -> [Tx])
-> [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))] -> [Tx]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Tx], (ScriptOutput, Word64, OutPoint, Int, Int)) -> [Tx]
forall a b. (a, b) -> a
fst [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))]
res, (([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))
 -> (ScriptOutput, Word64, OutPoint, Int, Int))
-> [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))]
-> [(ScriptOutput, Word64, OutPoint, Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map ([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))
-> (ScriptOutput, Word64, OutPoint, Int, Int)
forall a b. (a, b) -> b
snd [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))]
res)
  where
    singleSig :: ScriptOutput
-> Word64
-> Maybe ScriptOutput
-> Tx
-> OutPoint
-> SecKey
-> Gen Tx
singleSig ScriptOutput
so Word64
val Maybe ScriptOutput
rdmM Tx
tx OutPoint
op SecKey
prv = do
      SigHash
sh <- Network -> Gen SigHash
arbitraryValidSigHash Network
net
      let sigi :: SigInput
sigi = ScriptOutput
-> Word64 -> OutPoint -> SigHash -> Maybe ScriptOutput -> SigInput
SigInput ScriptOutput
so Word64
val OutPoint
op SigHash
sh Maybe ScriptOutput
rdmM
      Tx -> Gen Tx
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (Tx -> Gen Tx)
-> (Either String Tx -> Tx) -> Either String Tx -> Gen Tx
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tx -> Either String Tx -> Tx
forall b a. b -> Either a b -> b
fromRight (String -> Tx
forall a. HasCallStack => String -> a
error String
"Could not decode transaction") (Either String Tx -> Gen Tx) -> Either String Tx -> Gen Tx
forall a b. (a -> b) -> a -> b
$
        Network -> Ctx -> Tx -> [SigInput] -> [SecKey] -> Either String Tx
signTx Network
net Ctx
ctx Tx
tx [SigInput
sigi] [SecKey
prv]
    arbitraryData :: Gen
  (ScriptOutput, Word64, Maybe ScriptOutput, [PrivateKey], Int, Int)
arbitraryData = do
      (Int
m, Int
n) <- Gen (Int, Int)
arbitraryMSParam
      Word64
val <- TestCoin -> Word64
getTestCoin (TestCoin -> Word64) -> Gen TestCoin -> Gen Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen TestCoin
arbitrarySatoshi Network
net
      Int
nPrv <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
m, Int
n)
      [(PrivateKey, PublicKey)]
keys <- Int -> Gen (PrivateKey, PublicKey) -> Gen [(PrivateKey, PublicKey)]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
n (Ctx -> Gen (PrivateKey, PublicKey)
arbitraryKeyPair Ctx
ctx)
      Int
perm <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
0, [(PrivateKey, PublicKey)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(PrivateKey, PublicKey)]
keys Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
      let pubKeys :: [PublicKey]
pubKeys = ((PrivateKey, PublicKey) -> PublicKey)
-> [(PrivateKey, PublicKey)] -> [PublicKey]
forall a b. (a -> b) -> [a] -> [b]
map (PrivateKey, PublicKey) -> PublicKey
forall a b. (a, b) -> b
snd [(PrivateKey, PublicKey)]
keys
          prvKeys :: [PrivateKey]
prvKeys = Int -> [PrivateKey] -> [PrivateKey]
forall a. Int -> [a] -> [a]
take Int
nPrv ([PrivateKey] -> [PrivateKey]) -> [PrivateKey] -> [PrivateKey]
forall a b. (a -> b) -> a -> b
$ [PrivateKey] -> [[PrivateKey]]
forall a. [a] -> [[a]]
permutations (((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)]
keys) [[PrivateKey]] -> Int -> [PrivateKey]
forall a. HasCallStack => [a] -> Int -> a
!! Int
perm
      let so :: ScriptOutput
so = [PublicKey] -> Int -> ScriptOutput
PayMulSig [PublicKey]
pubKeys Int
m
      [(ScriptOutput, Word64, Maybe ScriptOutput, [PrivateKey], Int,
  Int)]
-> Gen
     (ScriptOutput, Word64, Maybe ScriptOutput, [PrivateKey], Int, Int)
forall a. [a] -> Gen a
elements
        [ (ScriptOutput
so, Word64
val, Maybe ScriptOutput
forall a. Maybe a
Nothing, [PrivateKey]
prvKeys, Int
m, Int
n),
          ( Hash160 -> ScriptOutput
PayScriptHash (Ctx -> ScriptOutput -> Address
payToScriptAddress Ctx
ctx ScriptOutput
so).hash160,
            Word64
val,
            ScriptOutput -> Maybe ScriptOutput
forall a. a -> Maybe a
Just ScriptOutput
so,
            [PrivateKey]
prvKeys,
            Int
m,
            Int
n
          )
        ]

wrapKey :: (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey :: (SigInput, PrivateKey) -> (SigInput, [PrivateKey])
wrapKey (SigInput
s, PrivateKey
k) = (SigInput
s, [PrivateKey
k])