module Haskoin.Util.Arbitrary.Transaction where
import Control.Monad
import qualified Data.ByteString as BS
import Data.Either (fromRight)
import Data.List (nub, nubBy, permutations)
import Data.Word (Word64)
import Haskoin.Address
import Haskoin.Constants
import Haskoin.Data
import Haskoin.Keys.Common
import Haskoin.Script
import Haskoin.Transaction
import Haskoin.Util.Arbitrary.Crypto
import Haskoin.Util.Arbitrary.Keys
import Haskoin.Util.Arbitrary.Script
import Haskoin.Util.Arbitrary.Util
import Test.QuickCheck
newtype TestCoin = TestCoin {TestCoin -> Word64
getTestCoin :: Word64}
deriving (TestCoin -> TestCoin -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TestCoin -> TestCoin -> Bool
$c/= :: TestCoin -> TestCoin -> Bool
== :: TestCoin -> TestCoin -> Bool
$c== :: TestCoin -> TestCoin -> Bool
Eq, Int -> TestCoin -> ShowS
[TestCoin] -> ShowS
TestCoin -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TestCoin] -> ShowS
$cshowList :: [TestCoin] -> ShowS
show :: TestCoin -> String
$cshow :: TestCoin -> String
showsPrec :: Int -> TestCoin -> ShowS
$cshowsPrec :: Int -> TestCoin -> ShowS
Show)
instance Coin TestCoin where
coinValue :: TestCoin -> Word64
coinValue = TestCoin -> Word64
getTestCoin
arbitraryTxHash :: Gen TxHash
arbitraryTxHash :: Gen TxHash
arbitraryTxHash = Hash256 -> TxHash
TxHash forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Hash256
arbitraryHash256
arbitrarySatoshi :: Network -> Gen TestCoin
arbitrarySatoshi :: Network -> Gen TestCoin
arbitrarySatoshi Network
net = Word64 -> TestCoin
TestCoin forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Random a => (a, a) -> Gen a
choose (Word64
1, Network -> Word64
getMaxSatoshi Network
net)
arbitraryOutPoint :: Gen OutPoint
arbitraryOutPoint :: Gen OutPoint
arbitraryOutPoint = TxHash -> Word32 -> OutPoint
OutPoint forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen TxHash
arbitraryTxHash forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
arbitraryTxOut :: Network -> Gen TxOut
arbitraryTxOut :: Network -> Gen TxOut
arbitraryTxOut Network
net =
Word64 -> ByteString -> TxOut
TxOut forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TestCoin -> Word64
getTestCoin forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen TestCoin
arbitrarySatoshi Network
net)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (ScriptOutput -> ByteString
encodeOutputBS forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen ScriptOutput
arbitraryScriptOutput Network
net)
arbitraryTxIn :: Network -> Gen TxIn
arbitraryTxIn :: Network -> Gen TxIn
arbitraryTxIn Network
net =
OutPoint -> ByteString -> Word32 -> TxIn
TxIn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen OutPoint
arbitraryOutPoint
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (ScriptInput -> ByteString
encodeInputBS forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen ScriptInput
arbitraryScriptInput Network
net)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
arbitraryTx :: Network -> Gen Tx
arbitraryTx :: Network -> Gen Tx
arbitraryTx Network
net = forall a. [Gen a] -> Gen a
oneof [Network -> Gen Tx
arbitraryLegacyTx Network
net, Network -> Gen Tx
arbitraryWitnessTx Network
net]
arbitraryLegacyTx :: Network -> Gen Tx
arbitraryLegacyTx :: Network -> Gen Tx
arbitraryLegacyTx Network
net = Network -> Bool -> Gen Tx
arbitraryWLTx Network
net Bool
False
arbitraryWitnessTx :: Network -> Gen Tx
arbitraryWitnessTx :: Network -> Gen Tx
arbitraryWitnessTx Network
net = Network -> Bool -> Gen Tx
arbitraryWLTx Network
net Bool
True
arbitraryWLTx :: Network -> Bool -> Gen Tx
arbitraryWLTx :: Network -> Bool -> Gen Tx
arbitraryWLTx Network
net Bool
wit = do
Int
ni <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
Int
no <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
[TxIn]
inps <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni (Network -> Gen TxIn
arbitraryTxIn Network
net)
[TxOut]
outs <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Gen TxOut
arbitraryTxOut Network
net)
let uniqueInps :: [TxIn]
uniqueInps = forall a. (a -> a -> Bool) -> [a] -> [a]
nubBy (\TxIn
a TxIn
b -> TxIn -> OutPoint
prevOutput TxIn
a forall a. Eq a => a -> a -> Bool
== TxIn -> OutPoint
prevOutput TxIn
b) [TxIn]
inps
[[ByteString]]
w <-
if Bool
wit
then forall a. Int -> Gen a -> Gen [a]
vectorOf (forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxIn]
uniqueInps) (forall a. Gen a -> Gen [a]
listOf Gen ByteString
arbitraryBS)
else forall (m :: * -> *) a. Monad m => a -> m a
return []
Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxIn]
uniqueInps forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxOut]
outs forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [[ByteString]]
w forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
arbitraryAddrOnlyTx :: Network -> Gen Tx
arbitraryAddrOnlyTx :: Network -> Gen Tx
arbitraryAddrOnlyTx Network
net = do
Int
ni <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
Int
no <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
[TxIn]
inps <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni (Network -> Gen TxIn
arbitraryAddrOnlyTxIn Network
net)
[TxOut]
outs <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Gen TxOut
arbitraryAddrOnlyTxOut Network
net)
Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxIn]
inps forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxOut]
outs forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [] forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
arbitraryAddrOnlyTxFull :: Network -> Gen Tx
arbitraryAddrOnlyTxFull :: Network -> Gen Tx
arbitraryAddrOnlyTxFull Network
net = do
Int
ni <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
Int
no <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
[TxIn]
inps <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni (Network -> Gen TxIn
arbitraryAddrOnlyTxInFull Network
net)
[TxOut]
outs <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Gen TxOut
arbitraryAddrOnlyTxOut Network
net)
Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxIn]
inps forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [TxOut]
outs forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure [] forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
arbitraryAddrOnlyTxIn :: Network -> Gen TxIn
arbitraryAddrOnlyTxIn :: Network -> Gen TxIn
arbitraryAddrOnlyTxIn Network
net = do
ScriptInput
inp <- forall a. [Gen a] -> Gen a
oneof [Network -> Gen ScriptInput
arbitraryPKHashInput Network
net, Network -> Gen ScriptInput
arbitraryMulSigSHInput Network
net]
OutPoint -> ByteString -> Word32 -> TxIn
TxIn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen OutPoint
arbitraryOutPoint forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure (ScriptInput -> ByteString
encodeInputBS ScriptInput
inp) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
arbitraryAddrOnlyTxInFull :: Network -> Gen TxIn
arbitraryAddrOnlyTxInFull :: Network -> Gen TxIn
arbitraryAddrOnlyTxInFull Network
net = do
ScriptInput
inp <-
forall a. [Gen a] -> Gen a
oneof [Network -> Gen ScriptInput
arbitraryPKHashInputFullC Network
net, Network -> Gen ScriptInput
arbitraryMulSigSHInputFullC Network
net]
OutPoint -> ByteString -> Word32 -> TxIn
TxIn forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen OutPoint
arbitraryOutPoint forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure (ScriptInput -> ByteString
encodeInputBS ScriptInput
inp) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Arbitrary a => Gen a
arbitrary
arbitraryAddrOnlyTxOut :: Network -> Gen TxOut
arbitraryAddrOnlyTxOut :: Network -> Gen TxOut
arbitraryAddrOnlyTxOut Network
net = do
Word64
v <- TestCoin -> Word64
getTestCoin forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen TestCoin
arbitrarySatoshi Network
net
ScriptOutput
out <- forall a. [Gen a] -> Gen a
oneof [Gen ScriptOutput
arbitraryPKHashOutput, Gen ScriptOutput
arbitrarySHOutput]
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Word64 -> ByteString -> TxOut
TxOut Word64
v forall a b. (a -> b) -> a -> b
$ ScriptOutput -> ByteString
encodeOutputBS ScriptOutput
out
arbitrarySigInput :: Network -> Gen (SigInput, [SecKeyI])
arbitrarySigInput :: Network -> Gen (SigInput, [SecKeyI])
arbitrarySigInput Network
net =
forall a. [Gen a] -> Gen a
oneof
[ (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen (SigInput, SecKeyI)
arbitraryPKSigInput Network
net
, (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen (SigInput, SecKeyI)
arbitraryPKHashSigInput Network
net
, Network -> Gen (SigInput, [SecKeyI])
arbitraryMSSigInput Network
net
, Network -> Gen (SigInput, [SecKeyI])
arbitrarySHSigInput Network
net
, (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen (SigInput, SecKeyI)
arbitraryWPKHSigInput Network
net
, Network -> Gen (SigInput, [SecKeyI])
arbitraryWSHSigInput Network
net
]
arbitraryPKSigInput :: Network -> Gen (SigInput, SecKeyI)
arbitraryPKSigInput :: Network -> Gen (SigInput, SecKeyI)
arbitraryPKSigInput Network
net = Network -> Bool -> Gen (SigInput, SecKeyI)
arbitraryAnyInput Network
net Bool
False
arbitraryPKHashSigInput :: Network -> Gen (SigInput, SecKeyI)
arbitraryPKHashSigInput :: Network -> Gen (SigInput, SecKeyI)
arbitraryPKHashSigInput Network
net = Network -> Bool -> Gen (SigInput, SecKeyI)
arbitraryAnyInput Network
net Bool
True
arbitraryAnyInput :: Network -> Bool -> Gen (SigInput, SecKeyI)
arbitraryAnyInput :: Network -> Bool -> Gen (SigInput, SecKeyI)
arbitraryAnyInput Network
net Bool
pkh = do
(SecKeyI
k, PubKeyI
p) <- Gen (SecKeyI, PubKeyI)
arbitraryKeyPair
let out :: ScriptOutput
out
| Bool
pkh = Hash160 -> ScriptOutput
PayPKHash forall a b. (a -> b) -> a -> b
$ Address -> Hash160
getAddrHash160 forall a b. (a -> b) -> a -> b
$ PubKeyI -> Address
pubKeyAddr PubKeyI
p
| Bool
otherwise = PubKeyI -> ScriptOutput
PayPK PubKeyI
p
(Word64
val, OutPoint
op, SigHash
sh) <- Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff Network
net
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 forall a. Maybe a
Nothing, SecKeyI
k)
arbitraryInputStuff :: Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff :: Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff Network
net = do
Word64
val <- TestCoin -> Word64
getTestCoin 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
forall (m :: * -> *) a. Monad m => a -> m a
return (Word64
val, OutPoint
op, SigHash
sh)
arbitraryMSSigInput :: Network -> Gen (SigInput, [SecKeyI])
arbitraryMSSigInput :: Network -> Gen (SigInput, [SecKeyI])
arbitraryMSSigInput Network
net = do
(Int
m, Int
n) <- Gen (Int, Int)
arbitraryMSParam
[(SecKeyI, PubKeyI)]
ks <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
n Gen (SecKeyI, PubKeyI)
arbitraryKeyPair
let out :: ScriptOutput
out = [PubKeyI] -> Int -> ScriptOutput
PayMulSig (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd [(SecKeyI, PubKeyI)]
ks) Int
m
(Word64
val, OutPoint
op, SigHash
sh) <- Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff Network
net
Int
perm <- forall a. Random a => (a, a) -> Gen a
choose (Int
0, Int
n forall a. Num a => a -> a -> a
- Int
1)
let ksPerm :: [SecKeyI]
ksPerm = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> [a]
take Int
m forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [[a]]
permutations [(SecKeyI, PubKeyI)]
ks forall a. [a] -> Int -> a
!! Int
perm
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 forall a. Maybe a
Nothing, [SecKeyI]
ksPerm)
arbitrarySHSigInput :: Network -> Gen (SigInput, [SecKeyI])
arbitrarySHSigInput :: Network -> Gen (SigInput, [SecKeyI])
arbitrarySHSigInput Network
net = do
(SigInput ScriptOutput
rdm Word64
val OutPoint
op SigHash
sh Maybe ScriptOutput
_, [SecKeyI]
ks) <-
forall a. [Gen a] -> Gen a
oneof
[ (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen (SigInput, SecKeyI)
arbitraryPKSigInput Network
net
, (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen (SigInput, SecKeyI)
arbitraryPKHashSigInput Network
net
, Network -> Gen (SigInput, [SecKeyI])
arbitraryMSSigInput Network
net
]
let out :: ScriptOutput
out = Hash160 -> ScriptOutput
PayScriptHash forall a b. (a -> b) -> a -> b
$ Address -> Hash160
getAddrHash160 forall a b. (a -> b) -> a -> b
$ ScriptOutput -> Address
payToScriptAddress ScriptOutput
rdm
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 forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just ScriptOutput
rdm, [SecKeyI]
ks)
arbitraryWPKHSigInput :: Network -> Gen (SigInput, SecKeyI)
arbitraryWPKHSigInput :: Network -> Gen (SigInput, SecKeyI)
arbitraryWPKHSigInput Network
net = do
(SecKeyI
k, PubKeyI
p) <- Gen (SecKeyI, PubKeyI)
arbitraryKeyPair
(Word64
val, OutPoint
op, SigHash
sh) <- Network -> Gen (Word64, OutPoint, SigHash)
arbitraryInputStuff Network
net
let out :: ScriptOutput
out = Hash160 -> ScriptOutput
PayWitnessPKHash forall b c a. (b -> c) -> (a -> b) -> a -> c
. Address -> Hash160
getAddrHash160 forall a b. (a -> b) -> a -> b
$ PubKeyI -> Address
pubKeyAddr PubKeyI
p
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 forall a. Maybe a
Nothing, SecKeyI
k)
arbitraryWSHSigInput :: Network -> Gen (SigInput, [SecKeyI])
arbitraryWSHSigInput :: Network -> Gen (SigInput, [SecKeyI])
arbitraryWSHSigInput Network
net = do
(SigInput ScriptOutput
rdm Word64
val OutPoint
op SigHash
sh Maybe ScriptOutput
_, [SecKeyI]
ks) <-
forall a. [Gen a] -> Gen a
oneof
[ (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen (SigInput, SecKeyI)
arbitraryPKSigInput Network
net
, (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen (SigInput, SecKeyI)
arbitraryPKHashSigInput Network
net
, Network -> Gen (SigInput, [SecKeyI])
arbitraryMSSigInput Network
net
]
let out :: ScriptOutput
out = Hash256 -> ScriptOutput
PayWitnessScriptHash forall b c a. (b -> c) -> (a -> b) -> a -> c
. Address -> Hash256
getAddrHash256 forall a b. (a -> b) -> a -> b
$ ScriptOutput -> Address
payToWitnessScriptAddress ScriptOutput
rdm
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 forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just ScriptOutput
rdm, [SecKeyI]
ks)
arbitrarySigningData :: Network -> Gen (Tx, [SigInput], [SecKeyI])
arbitrarySigningData :: Network -> Gen (Tx, [SigInput], [SecKeyI])
arbitrarySigningData Network
net = do
Word32
v <- forall a. Arbitrary a => Gen a
arbitrary
Int
ni <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
Int
no <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
[(SigInput, [SecKeyI])]
sigis <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni (Network -> Gen (SigInput, [SecKeyI])
arbitrarySigInput Network
net)
let uSigis :: [(SigInput, [SecKeyI])]
uSigis = forall a. (a -> a -> Bool) -> [a] -> [a]
nubBy (\(SigInput
a, [SecKeyI]
_) (SigInput
b, [SecKeyI]
_) -> SigInput -> OutPoint
sigInputOP SigInput
a forall a. Eq a => a -> a -> Bool
== SigInput -> OutPoint
sigInputOP SigInput
b) [(SigInput, [SecKeyI])]
sigis
[TxIn]
inps <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [(SigInput, [SecKeyI])]
uSigis forall a b. (a -> b) -> a -> b
$ \(SigInput
s, [SecKeyI]
_) -> OutPoint -> ByteString -> Word32 -> TxIn
TxIn (SigInput -> OutPoint
sigInputOP SigInput
s) ByteString
BS.empty forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary
[TxOut]
outs <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Gen TxOut
arbitraryTxOut Network
net)
Word32
l <- forall a. Arbitrary a => Gen a
arbitrary
Int
perm <- forall a. Random a => (a, a) -> Gen a
choose (Int
0, forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxIn]
inps forall a. Num a => a -> a -> a
- Int
1)
let tx :: Tx
tx = Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx Word32
v (forall a. [a] -> [[a]]
permutations [TxIn]
inps forall a. [a] -> Int -> a
!! Int
perm) [TxOut]
outs [] Word32
l
keys :: [SecKeyI]
keys = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall a b. (a, b) -> b
snd [(SigInput, [SecKeyI])]
uSigis
forall (m :: * -> *) a. Monad m => a -> m a
return (Tx
tx, forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(SigInput, [SecKeyI])]
uSigis, [SecKeyI]
keys)
arbitraryEmptyTx :: Network -> Gen Tx
arbitraryEmptyTx :: Network -> Gen Tx
arbitraryEmptyTx Network
net = do
Word32
v <- forall a. Arbitrary a => Gen a
arbitrary
Int
no <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
Int
ni <- forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
5)
[TxOut]
outs <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
no (Network -> Gen TxOut
arbitraryTxOut Network
net)
[OutPoint]
ops <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
ni Gen OutPoint
arbitraryOutPoint
Word32
t <- forall a. Arbitrary a => Gen a
arbitrary
Word32
s <- forall a. Arbitrary a => Gen a
arbitrary
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Word32 -> [TxIn] -> [TxOut] -> [[ByteString]] -> Word32 -> Tx
Tx Word32
v (forall a b. (a -> b) -> [a] -> [b]
map (\OutPoint
op -> OutPoint -> ByteString -> Word32 -> TxIn
TxIn OutPoint
op ByteString
BS.empty Word32
s) (forall a. Eq a => [a] -> [a]
nub [OutPoint]
ops)) [TxOut]
outs [] Word32
t
arbitraryPartialTxs ::
Network -> Gen ([Tx], [(ScriptOutput, Word64, OutPoint, Int, Int)])
arbitraryPartialTxs :: Network -> Gen ([Tx], [(ScriptOutput, Word64, OutPoint, Int, Int)])
arbitraryPartialTxs Network
net = do
Tx
tx <- Network -> Gen Tx
arbitraryEmptyTx Network
net
[([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))]
res <-
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (forall a b. (a -> b) -> [a] -> [b]
map TxIn -> OutPoint
prevOutput forall a b. (a -> b) -> a -> b
$ Tx -> [TxIn]
txIn Tx
tx) forall a b. (a -> b) -> a -> b
$ \OutPoint
op -> do
(ScriptOutput
so, Word64
val, Maybe ScriptOutput
rdmM, [SecKeyI]
prvs, Int
m, Int
n) <- Gen (ScriptOutput, Word64, Maybe ScriptOutput, [SecKeyI], Int, Int)
arbitraryData
[Tx]
txs <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (ScriptOutput
-> Word64
-> Maybe ScriptOutput
-> Tx
-> OutPoint
-> SecKey
-> Gen Tx
singleSig ScriptOutput
so Word64
val Maybe ScriptOutput
rdmM Tx
tx OutPoint
op forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecKeyI -> SecKey
secKeyData) [SecKeyI]
prvs
forall (m :: * -> *) a. Monad m => a -> m a
return ([Tx]
txs, (ScriptOutput
so, Word64
val, OutPoint
op, Int
m, Int
n))
forall (m :: * -> *) a. Monad m => a -> m a
return (forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall a b. (a, b) -> a
fst [([Tx], (ScriptOutput, Word64, OutPoint, Int, Int))]
res, forall a b. (a -> b) -> [a] -> [b]
map 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
forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. b -> Either a b -> b
fromRight (forall a. HasCallStack => String -> a
error String
"Could not decode transaction") forall a b. (a -> b) -> a -> b
$
Network -> Tx -> [SigInput] -> [SecKey] -> Either String Tx
signTx Network
net Tx
tx [SigInput
sigi] [SecKey
prv]
arbitraryData :: Gen (ScriptOutput, Word64, Maybe ScriptOutput, [SecKeyI], Int, Int)
arbitraryData = do
(Int
m, Int
n) <- Gen (Int, Int)
arbitraryMSParam
Word64
val <- TestCoin -> Word64
getTestCoin forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Gen TestCoin
arbitrarySatoshi Network
net
Int
nPrv <- forall a. Random a => (a, a) -> Gen a
choose (Int
m, Int
n)
[(SecKeyI, PubKeyI)]
keys <- forall a. Int -> Gen a -> Gen [a]
vectorOf Int
n Gen (SecKeyI, PubKeyI)
arbitraryKeyPair
Int
perm <- forall a. Random a => (a, a) -> Gen a
choose (Int
0, forall (t :: * -> *) a. Foldable t => t a -> Int
length [(SecKeyI, PubKeyI)]
keys forall a. Num a => a -> a -> a
- Int
1)
let pubKeys :: [PubKeyI]
pubKeys = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd [(SecKeyI, PubKeyI)]
keys
prvKeys :: [SecKeyI]
prvKeys = forall a. Int -> [a] -> [a]
take Int
nPrv forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [[a]]
permutations (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(SecKeyI, PubKeyI)]
keys) forall a. [a] -> Int -> a
!! Int
perm
let so :: ScriptOutput
so = [PubKeyI] -> Int -> ScriptOutput
PayMulSig [PubKeyI]
pubKeys Int
m
forall a. [a] -> Gen a
elements
[ (ScriptOutput
so, Word64
val, forall a. Maybe a
Nothing, [SecKeyI]
prvKeys, Int
m, Int
n)
,
( Hash160 -> ScriptOutput
PayScriptHash forall a b. (a -> b) -> a -> b
$ Address -> Hash160
getAddrHash160 forall a b. (a -> b) -> a -> b
$ ScriptOutput -> Address
payToScriptAddress ScriptOutput
so
, Word64
val
, forall a. a -> Maybe a
Just ScriptOutput
so
, [SecKeyI]
prvKeys
, Int
m
, Int
n
)
]
wrapKey :: (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey :: (SigInput, SecKeyI) -> (SigInput, [SecKeyI])
wrapKey (SigInput
s, SecKeyI
k) = (SigInput
s, [SecKeyI
k])