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

import qualified Data.HashMap.Strict as HashMap
import Haskoin.Block
import Haskoin.Crypto (Ctx)
import Haskoin.Network.Data
import Haskoin.Util.Arbitrary.Crypto
import Haskoin.Util.Arbitrary.Network
import Haskoin.Util.Arbitrary.Transaction
import Haskoin.Util.Arbitrary.Util
import Test.QuickCheck

-- | Block full or arbitrary transactions.
arbitraryBlock :: Network -> Ctx -> Gen Block
arbitraryBlock :: Network -> Ctx -> Gen Block
arbitraryBlock Network
net Ctx
ctx = do
  BlockHeader
h <- Gen BlockHeader
arbitraryBlockHeader
  Int
c <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
0, Int
10)
  [Tx]
txs <- Int -> Gen Tx -> Gen [Tx]
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
c (Network -> Ctx -> Gen Tx
arbitraryTx Network
net Ctx
ctx)
  Block -> Gen Block
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (Block -> Gen Block) -> Block -> Gen Block
forall a b. (a -> b) -> a -> b
$ BlockHeader -> [Tx] -> Block
Block BlockHeader
h [Tx]
txs

-- | Block header with random hash.
arbitraryBlockHeader :: Gen BlockHeader
arbitraryBlockHeader :: Gen BlockHeader
arbitraryBlockHeader =
  Word32
-> BlockHash
-> Hash256
-> Word32
-> Word32
-> Word32
-> BlockHeader
BlockHeader
    (Word32
 -> BlockHash
 -> Hash256
 -> Word32
 -> Word32
 -> Word32
 -> BlockHeader)
-> Gen Word32
-> Gen
     (BlockHash -> Hash256 -> Word32 -> Word32 -> Word32 -> BlockHeader)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
    Gen
  (BlockHash -> Hash256 -> Word32 -> Word32 -> Word32 -> BlockHeader)
-> Gen BlockHash
-> Gen (Hash256 -> Word32 -> Word32 -> Word32 -> BlockHeader)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen BlockHash
arbitraryBlockHash
    Gen (Hash256 -> Word32 -> Word32 -> Word32 -> BlockHeader)
-> Gen Hash256 -> Gen (Word32 -> Word32 -> Word32 -> BlockHeader)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Hash256
arbitraryHash256
    Gen (Word32 -> Word32 -> Word32 -> BlockHeader)
-> Gen Word32 -> Gen (Word32 -> Word32 -> BlockHeader)
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
    Gen (Word32 -> Word32 -> BlockHeader)
-> Gen Word32 -> Gen (Word32 -> BlockHeader)
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
    Gen (Word32 -> BlockHeader) -> Gen Word32 -> Gen BlockHeader
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 block hash.
arbitraryBlockHash :: Gen BlockHash
arbitraryBlockHash :: Gen BlockHash
arbitraryBlockHash = Hash256 -> BlockHash
BlockHash (Hash256 -> BlockHash) -> Gen Hash256 -> Gen BlockHash
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Hash256
arbitraryHash256

-- | Arbitrary 'GetBlocks' object with at least one block hash.
arbitraryGetBlocks :: Gen GetBlocks
arbitraryGetBlocks :: Gen GetBlocks
arbitraryGetBlocks =
  Word32 -> BlockLocator -> BlockHash -> GetBlocks
GetBlocks
    (Word32 -> BlockLocator -> BlockHash -> GetBlocks)
-> Gen Word32 -> Gen (BlockLocator -> BlockHash -> GetBlocks)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
    Gen (BlockLocator -> BlockHash -> GetBlocks)
-> Gen BlockLocator -> Gen (BlockHash -> GetBlocks)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen BlockHash -> Gen BlockLocator
forall a. Gen a -> Gen [a]
listOf1 Gen BlockHash
arbitraryBlockHash
    Gen (BlockHash -> GetBlocks) -> Gen BlockHash -> Gen GetBlocks
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen BlockHash
arbitraryBlockHash

-- | Arbitrary 'GetHeaders' object with at least one block header.
arbitraryGetHeaders :: Gen GetHeaders
arbitraryGetHeaders :: Gen GetHeaders
arbitraryGetHeaders =
  Word32 -> BlockLocator -> BlockHash -> GetHeaders
GetHeaders
    (Word32 -> BlockLocator -> BlockHash -> GetHeaders)
-> Gen Word32 -> Gen (BlockLocator -> BlockHash -> GetHeaders)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
    Gen (BlockLocator -> BlockHash -> GetHeaders)
-> Gen BlockLocator -> Gen (BlockHash -> GetHeaders)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen BlockHash -> Gen BlockLocator
forall a. Gen a -> Gen [a]
listOf1 Gen BlockHash
arbitraryBlockHash
    Gen (BlockHash -> GetHeaders) -> Gen BlockHash -> Gen GetHeaders
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen BlockHash
arbitraryBlockHash

-- | Arbitrary 'Headers' object with at least one block header.
arbitraryHeaders :: Gen Headers
arbitraryHeaders :: Gen Headers
arbitraryHeaders =
  [BlockHeaderCount] -> Headers
Headers ([BlockHeaderCount] -> Headers)
-> Gen [BlockHeaderCount] -> Gen Headers
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen BlockHeaderCount -> Gen [BlockHeaderCount]
forall a. Gen a -> Gen [a]
listOf1 ((,) (BlockHeader -> VarInt -> BlockHeaderCount)
-> Gen BlockHeader -> Gen (VarInt -> BlockHeaderCount)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen BlockHeader
arbitraryBlockHeader Gen (VarInt -> BlockHeaderCount)
-> Gen VarInt -> Gen BlockHeaderCount
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen VarInt
arbitraryVarInt)

-- | Arbitrary 'MerkleBlock' with at least one hash.
arbitraryMerkleBlock :: Gen MerkleBlock
arbitraryMerkleBlock :: Gen MerkleBlock
arbitraryMerkleBlock = do
  BlockHeader
bh <- Gen BlockHeader
arbitraryBlockHeader
  Word32
ntx <- Gen Word32
forall a. Arbitrary a => Gen a
arbitrary
  [Hash256]
hashes <- Gen Hash256 -> Gen [Hash256]
forall a. Gen a -> Gen [a]
listOf1 Gen Hash256
arbitraryHash256
  Int
c <- (Int, Int) -> Gen Int
forall a. Random a => (a, a) -> Gen a
choose (Int
1, Int
10)
  [Bool]
flags <- Int -> Gen Bool -> Gen [Bool]
forall a. Int -> Gen a -> Gen [a]
vectorOf (Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8) Gen Bool
forall a. Arbitrary a => Gen a
arbitrary
  MerkleBlock -> Gen MerkleBlock
forall a. a -> Gen a
forall (m :: * -> *) a. Monad m => a -> m a
return (MerkleBlock -> Gen MerkleBlock) -> MerkleBlock -> Gen MerkleBlock
forall a b. (a -> b) -> a -> b
$ BlockHeader -> Word32 -> [Hash256] -> [Bool] -> MerkleBlock
MerkleBlock BlockHeader
bh Word32
ntx [Hash256]
hashes [Bool]
flags

-- | Arbitrary 'BlockNode'
arbitraryBlockNode :: Gen BlockNode
arbitraryBlockNode :: Gen BlockNode
arbitraryBlockNode =
  BlockHeader -> Word32 -> BlockWork -> BlockHash -> BlockNode
BlockNode
    (BlockHeader -> Word32 -> BlockWork -> BlockHash -> BlockNode)
-> Gen BlockHeader
-> Gen (Word32 -> BlockWork -> BlockHash -> BlockNode)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen BlockHeader
arbitraryBlockHeader
    Gen (Word32 -> BlockWork -> BlockHash -> BlockNode)
-> Gen Word32 -> Gen (BlockWork -> BlockHash -> BlockNode)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Word32, Word32) -> Gen Word32
forall a. Random a => (a, a) -> Gen a
choose (Word32
0, Word32
forall a. Bounded a => a
maxBound)
    Gen (BlockWork -> BlockHash -> BlockNode)
-> Gen BlockWork -> Gen (BlockHash -> BlockNode)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen BlockWork
forall a. Integral a => Gen a
arbitrarySizedNatural
    Gen (BlockHash -> BlockNode) -> Gen BlockHash -> Gen BlockNode
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen BlockHash
arbitraryBlockHash

-- | Arbitrary 'HeaderMemory'
arbitraryHeaderMemory :: Gen HeaderMemory
arbitraryHeaderMemory :: Gen HeaderMemory
arbitraryHeaderMemory = do
  [(ShortBlockHash, ShortByteString)]
ls <- Gen (ShortBlockHash, ShortByteString)
-> Gen [(ShortBlockHash, ShortByteString)]
forall a. Gen a -> Gen [a]
listOf (Gen (ShortBlockHash, ShortByteString)
 -> Gen [(ShortBlockHash, ShortByteString)])
-> Gen (ShortBlockHash, ShortByteString)
-> Gen [(ShortBlockHash, ShortByteString)]
forall a b. (a -> b) -> a -> b
$ (,) (ShortBlockHash
 -> ShortByteString -> (ShortBlockHash, ShortByteString))
-> Gen ShortBlockHash
-> Gen (ShortByteString -> (ShortBlockHash, ShortByteString))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen ShortBlockHash
forall a. Arbitrary a => Gen a
arbitrary Gen (ShortByteString -> (ShortBlockHash, ShortByteString))
-> Gen ShortByteString -> Gen (ShortBlockHash, ShortByteString)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen ShortByteString
arbitraryBSS
  BlockMap -> BlockNode -> HeaderMemory
HeaderMemory ([(ShortBlockHash, ShortByteString)] -> BlockMap
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList [(ShortBlockHash, ShortByteString)]
ls) (BlockNode -> HeaderMemory) -> Gen BlockNode -> Gen HeaderMemory
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen BlockNode
arbitraryBlockNode